--- /dev/null
+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
+
--- /dev/null
+#ifndef LOCALISATION_H
+#define LOCALISATION_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#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 <libintl.h>
+#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 */
+
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#include <config.h> /* For GETTEXT_PACKAGE, etc */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtkwidget.h>
+#include <gtk/gtkmain.h>
+#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;
+}
+
--- /dev/null
+412 osso_db_country_afghanistan\r
+276 osso_db_country_albania\r
+603 osso_db_country_algeria\r
+544 osso_db_country_american_samoa\r
+213 osso_db_country_andorra\r
+631 osso_db_country_angola\r
+365 osso_db_country_anguilla\r
+344 osso_db_country_antigua_and_barbuda\r
+722 osso_db_country_argentina\r
+283 osso_db_country_armenia\r
+363 osso_db_country_aruba\r
+505 osso_db_country_australia\r
+232 osso_db_country_austria\r
+400 osso_db_country_azerbaijani_republic\r
+364 osso_db_country_bahamas\r
+426 osso_db_country_bahrain\r
+470 osso_db_country_bangladesh\r
+342 osso_db_country_barbados\r
+257 osso_db_country_belarus\r
+206 osso_db_country_belgium\r
+702 osso_db_country_belize\r
+616 osso_db_country_benin\r
+350 osso_db_country_bermuda\r
+402 osso_db_country_bhutan\r
+736 osso_db_country_bolivia\r
+218 osso_db_country_bosnia_and_herzegovina\r
+652 osso_db_country_botswana\r
+724 osso_db_country_brazil\r
+348 osso_db_country_british_virgin_islands\r
+528 osso_db_country_brunei_darussalam\r
+284 osso_db_country_bulgaria\r
+613 osso_db_country_burkina_faso\r
+642 osso_db_country_burundi\r
+456 osso_db_country_cambodia\r
+624 osso_db_country_cameroon\r
+302 osso_db_country_canada\r
+625 osso_db_country_cape_verde\r
+346 osso_db_country_cayman_islands\r
+623 osso_db_country_central_african_republic\r
+622 osso_db_country_chad\r
+730 osso_db_country_chile\r
+461 osso_db_country_china\r
+460 osso_db_country_china\r
+732 osso_db_country_colombia\r
+654 osso_db_country_comoros\r
+629 osso_db_country_republic_of_the_congo\r
+548 osso_db_country_cook_islands\r
+712 osso_db_country_costa_rica\r
+612 osso_db_country_cote_dlvoire\r
+219 osso_db_country_croatia\r
+368 osso_db_country_cuba\r
+280 osso_db_country_cyprus\r
+230 osso_db_country_czech_republic\r
+630 osso_db_country_democratic_republic_of_the_congo\r
+238 osso_db_country_denmark\r
+638 osso_db_country_djibouti\r
+366 osso_db_country_dominica\r
+370 osso_db_country_dominican_republic\r
+514 osso_db_country_east_timor\r
+740 osso_db_country_ecuador\r
+602 osso_db_country_egypt\r
+706 osso_db_country_el_salvador\r
+627 osso_db_country_equatorial_guinea\r
+657 osso_db_country_eritrea\r
+248 osso_db_country_estonia\r
+636 osso_db_country_ethiopia\r
+288 osso_db_country_faroe_islands\r
+542 osso_db_country_fiji\r
+244 osso_db_country_finland\r
+208 osso_db_country_france\r
+742 osso_db_country_french_guiana\r
+547 osso_db_country_french_polynesia\r
+628 osso_db_country_gobonese_republic\r
+607 osso_db_country_gambia\r
+282 osso_db_country_georgia\r
+262 osso_db_country_germany\r
+620 osso_db_country_ghana\r
+266 osso_db_country_gibraltar\r
+202 osso_db_country_greece\r
+290 osso_db_country_greenland\r
+352 osso_db_country_grenada\r
+340 osso_db_country_guadeloupe\r
+535 osso_db_country_guam\r
+704 osso_db_country_guatemala\r
+611 osso_db_country_guinea\r
+632 osso_db_country_guinea_bissaus\r
+738 osso_db_country_guyana\r
+372 osso_db_country_haiti\r
+708 osso_db_country_honduras\r
+454 osso_db_country_hong_kong\r
+216 osso_db_country_hungary\r
+274 osso_db_country_iceland\r
+404 osso_db_country_india\r
+510 osso_db_country_indonesia\r
+432 osso_db_country_iran\r
+418 osso_db_country_iraq\r
+272 osso_db_country_republic_of_ireland\r
+425 osso_db_country_israel\r
+222 osso_db_country_italy\r
+338 osso_db_country_jamaica\r
+441 osso_db_country_japan\r
+440 osso_db_country_japan\r
+416 osso_db_country_jordan\r
+401 osso_db_country_kazakhstan\r
+639 osso_db_country_kenya\r
+545 osso_db_country_kiribati\r
+467 osso_db_country_korea_north\r
+450 osso_db_country_country_south_korea\r
+419 osso_db_country_kuwait\r
+437 osso_db_country_kyrgyz_republic\r
+457 osso_db_country_laos\r
+247 osso_db_country_latvia\r
+415 osso_db_country_lebanon\r
+651 osso_db_country_lesotho\r
+618 osso_db_country_liberia\r
+606 osso_db_country_libya\r
+295 osso_db_country_liechtenstein\r
+246 osso_db_country_lithuania\r
+270 osso_db_country_luxembourg\r
+455 osso_db_country_macao\r
+294 osso_db_country_the_former_yugoslav_republic_of_macedonia\r
+646 osso_db_country_madagascar\r
+650 osso_db_country_malawi\r
+502 osso_db_country_malaysia\r
+472 osso_db_country_maldives\r
+610 osso_db_country_mali\r
+278 osso_db_country_malta\r
+551 osso_db_country_marshall_islands\r
+340 osso_db_country_martinique\r
+609 osso_db_country_mauritania\r
+617 osso_db_country_mauritius\r
+334 osso_db_country_mexico\r
+550 osso_db_country_micronesia\r
+259 osso_db_country_republic_of_moldova\r
+212 osso_db_country_monaco\r
+428 osso_db_country_mongolia\r
+354 osso_db_country_montserrat\r
+604 osso_db_country_morocco\r
+643 osso_db_country_mozambique\r
+414 osso_db_country_myanmar\r
+649 osso_db_country_namibia\r
+536 osso_db_country_nauru\r
+429 osso_db_country_nepal\r
+204 osso_db_country_netherlands\r
+362 osso_db_country_netherlands_antilles\r
+546 osso_db_country_new_caledonia\r
+530 osso_db_country_new_zealand\r
+710 osso_db_country_nicaraqua\r
+614 osso_db_country_niger\r
+621 osso_db_country_nigeria\r
+534 osso_db_country_northern_mariana_islands\r
+242 osso_db_country_norway\r
+422 osso_db_country_oman\r
+410 osso_db_country_pakistan\r
+552 osso_db_country_palau\r
+714 osso_db_country_panama\r
+537 osso_db_country_papua_new_guinea\r
+744 osso_db_country_paraquay\r
+716 osso_db_country_peru\r
+515 osso_db_country_philippines\r
+260 osso_db_country_poland\r
+268 osso_db_country_portugal\r
+330 osso_db_country_puerto_rico\r
+427 osso_db_country_qatar\r
+647 osso_db_country_reunion\r
+226 osso_db_country_romania\r
+250 osso_db_country_russian_federation\r
+635 osso_db_country_rwandese_republic\r
+356 osso_db_country_saint_kitts_and_nevis\r
+358 osso_db_country_saint_lucia\r
+308 osso_db_country_saint_pierre_and_miquelon\r
+360 osso_db_country_saint_vincent_and_grenadines\r
+549 osso_db_country_samoa\r
+292 osso_db_country_san_marino\r
+626 osso_db_country_sao_tome_and_principe\r
+420 osso_db_country_saudi_arabia\r
+608 osso_db_country_senegal\r
+220 osso_db_country_serbia_and_montenegro\r
+633 osso_db_country_seychelles\r
+619 osso_db_country_sierra_leone\r
+525 osso_db_country_singapore\r
+231 osso_db_country_slovakia\r
+293 osso_db_country_slovenia\r
+540 osso_db_country_solomon_islands\r
+637 osso_db_country_somalia\r
+655 osso_db_country_south_africa\r
+214 osso_db_country_spain\r
+413 osso_db_country_sri_lanka\r
+634 osso_db_country_sudan\r
+746 osso_db_country_suriname\r
+653 osso_db_country_swaziland\r
+240 osso_db_country_sweden\r
+228 osso_db_country_switzerland\r
+417 osso_db_country_syrian_arab_republic\r
+466 osso_db_country_taiwan\r
+436 osso_db_country_tajikistan\r
+640 osso_db_country_united_republic_of_tanzania\r
+520 osso_db_country_thailand\r
+615 osso_db_country_togolese_republic\r
+539 osso_db_country_tonga\r
+374 osso_db_country_trinidad_and_tobago\r
+605 osso_db_country_tunisia\r
+286 osso_db_country_turkey\r
+438 osso_db_country_turkmenistan\r
+376 osso_db_country_turks_and_caicos_islands\r
+641 osso_db_country_uganda\r
+255 osso_db_country_ukraine\r
+424 osso_db_country_united_arab_emirates\r
+430 osso_db_country_united_arab_emirates_abu_dhabi\r
+431 osso_db_country_united_arab_emirates_dubai\r
+235 osso_db_country_united_kingdom_of_great_britain_and_northern_ireland\r
+234 osso_db_country_united_kingdom_of_great_britain_and_northern_ireland\r
+310 osso_db_country_united_states_of_america\r
+316 osso_db_country_united_states_of_america\r
+311 osso_db_country_united_states_of_america\r
+312 osso_db_country_united_states_of_america\r
+313 osso_db_country_united_states_of_america\r
+314 osso_db_country_united_states_of_america\r
+315 osso_db_country_united_states_of_america\r
+332 osso_db_country_unites_states_virgin_islands\r
+748 osso_db_country_uruguay\r
+434 osso_db_country_uzbekistan\r
+541 osso_db_country_vanuatu\r
+225 osso_db_country_the_vatican\r
+734 osso_db_country_venezuela\r
+452 osso_db_country_viet_nam\r
+543 osso_db_country_wallis_and_futuna\r
+421 osso_db_country_yemen\r
+645 osso_db_country_zambia\r
+648 osso_db_country_zimbabwe\r
--- /dev/null
+276 Albania\r
+213 Andorra\r
+722 Argentina\r
+363 Aruba\r
+505 Australia\r
+232 Austria\r
+400 Azerbaijan\r
+426 Bahrain\r
+470 Bangladesh\r
+257 Belarus\r
+206 Belgium\r
+736 Bolivia\r
+218 Bosnia and Herzegovina\r
+652 Botswana\r
+724 Brazil\r
+528 Brunei Darussalam\r
+284 Bulgaria\r
+456 Cambodia\r
+302 Canada\r
+730 Chile\r
+460 China\r
+732 Colombia\r
+219 Croatia\r
+280 Cyprus\r
+230 Czech Republic\r
+238 Denmark\r
+370 Dominican Republic\r
+740 Ecuador\r
+602 Egypt\r
+706 El Salvador\r
+248 Estonia\r
+244 Finland\r
+208 France\r
+282 Georgia\r
+262 Germany\r
+620 Ghana\r
+266 Gibraltar\r
+202 Greece\r
+340 Guadeloupe\r
+704 Guatemala\r
+708 Honduras\r
+454 Hong Kong, China\r
+216 Hungary\r
+274 Iceland\r
+404 India\r
+510 Indonesia\r
+272 Ireland\r
+425 Israel\r
+222 Italy\r
+338 Jamaica\r
+440 Japan\r
+416 Jordan\r
+401 Kazakhstan\r
+639 Kenya\r
+419 Kuwait\r
+247 Latvia\r
+415 Lebanon\r
+295 Liechtenstein\r
+246 Lithuania\r
+270 Luxembourg\r
+455 Macao, China\r
+294 Macedonia\r
+502 Malaysia\r
+472 Maldives\r
+278 Malta\r
+340 Martinique\r
+334 Mexico\r
+259 Moldova\r
+212 Monaco\r
+428 Mongolia\r
+220 Montenegro\r
+604 Morocco\r
+204 Netherlands\r
+530 New Zealand\r
+621 Nigeria\r
+242 Norway\r
+422 Oman\r
+410 Pakistan\r
+714 Panama\r
+744 Paraguay\r
+716 Peru\r
+515 Philippines\r
+260 Poland\r
+268 Portugal\r
+427 Qatar\r
+226 Romania\r
+250 Russian Federation\r
+420 Saudi Arabia\r
+220 Serbia\r
+525 Singapore\r
+231 Slovakia\r
+293 Slovenia\r
+655 South Africa\r
+214 Spain\r
+413 Sri Lanka\r
+240 Sweden\r
+228 Switzerland\r
+417 Syria\r
+466 Taiwan\r
+520 Thailand\r
+374 Trinidad and Tobago\r
+286 Turkey\r
+255 Ukraine\r
+234 United Kingdom\r
+748 Uruguay\r
+310 USA\r
+734 Venezuela\r
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#define _GNU_SOURCE /* So we can use the getline() function, which is a convenient GNU extension. */
+#include <stdio.h>
+
+#include "modest-easysetup-country-combo-box.h"
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderertext.h>
+
+#include <stdlib.h>
+#include <string.h> /* For memcpy() */
+
+#include <libintl.h> /* 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;
+}
+
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#ifndef _EASYSETUP_COUNTRY_COMBO_BOX
+#define _EASYSETUP_COUNTRY_COMBO_BOX
+
+#include <gtk/gtkcombobox.h>
+
+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 */
--- /dev/null
+/* 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 <stdio.h>
+
+#include "modest-easysetup-provider-combo-box.h"
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <glib/gi18n.h>
+
+#include <stdlib.h>
+#include <string.h> /* For memcpy() */
+
+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. */
+}
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#ifndef _EASYSETUP_PROVIDER_COMBO_BOX
+#define _EASYSETUP_PROVIDER_COMBO_BOX
+
+#include <gtk/gtkcombobox.h>
+#include "modest-presets.h"
+
+G_BEGIN_DECLS
+
+#define EASYSETUP_TYPE_PROVIDER_COMBO_BOX easysetup_provider_combo_box_get_type()
+
+#define EASYSETUP_PROVIDER_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ EASYSETUP_TYPE_PROVIDER_COMBO_BOX, EasysetupProviderComboBox))
+
+#define EASYSETUP_PROVIDER_COMBO_BOX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ EASYSETUP_TYPE_PROVIDER_COMBO_BOX, EasysetupProviderComboBoxClass))
+
+#define EASYSETUP_IS_PROVIDER_COMBO_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ EASYSETUP_TYPE_PROVIDER_COMBO_BOX))
+
+#define EASYSETUP_IS_PROVIDER_COMBO_BOX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ EASYSETUP_TYPE_PROVIDER_COMBO_BOX))
+
+#define EASYSETUP_PROVIDER_COMBO_BOX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ EASYSETUP_TYPE_PROVIDER_COMBO_BOX, EasysetupProviderComboBoxClass))
+
+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 */
--- /dev/null
+/* 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 <stdio.h>
+
+#include "modest-easysetup-secureauth-combo-box.h"
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <glib/gi18n.h>
+
+#include <stdlib.h>
+#include <string.h> /* For memcpy() */
+
+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;
+}
+
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#ifndef _EASYSETUP_SECUREAUTH_COMBO_BOX
+#define _EASYSETUP_SECUREAUTH_COMBO_BOX
+
+#include <gtk/gtkcombobox.h>
+#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 */
--- /dev/null
+/* 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 <stdio.h>
+
+#include "modest-easysetup-serversecurity-combo-box.h"
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <glib/gi18n.h>
+
+#include <stdlib.h>
+#include <string.h> /* For memcpy() */
+
+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;
+}
+
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#ifndef _EASYSETUP_SERVERSECURITY_COMBO_BOX
+#define _EASYSETUP_SERVERSECURITY_COMBO_BOX
+
+#include <gtk/gtkcombobox.h>
+#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 */
--- /dev/null
+/* 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 <stdio.h>
+
+#include "modest-easysetup-servertype-combo-box.h"
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <glib/gi18n.h>
+
+#include <stdlib.h>
+#include <string.h> /* For memcpy() */
+
+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;
+}
+
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#ifndef _EASYSETUP_SERVERTYPE_COMBO_BOX
+#define _EASYSETUP_SERVERTYPE_COMBO_BOX
+
+#include <gtk/gtkcombobox.h>
+#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 */
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+
+#include "modest-easysetup-wizard.h"
+#include <glib/gi18n.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkcombobox.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkmessagedialog.h>
+#include <hildon-widgets/hildon-caption.h>
+#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 <gconf/gconf-client.h>
+#include <string.h> /* 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;
+}
+
+
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#ifndef _MODEST_EAYSETUP_WIZARD_DIALOG
+#define _MODEST_EAYSETUP_WIZARD_DIALOG
+
+/* #include <hildon-widgets/hildon-wizard-dialog.h> */
+#include "modest-wizard-dialog.h" /* We use a copied-and-improved HildonWizardDialog. */
+#include "modest-account-mgr/modest-account-mgr.h"
+#include <hildon-widgets/hildon-caption.h>
+
+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 */
--- /dev/null
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h> /* for strcmp */
+#include "modest-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);
+}
--- /dev/null
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MODEST_PRESETS_H__
+#define __MODEST_PRESETS_H__
+
+#include <glib.h>
+
+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__*/
+
+
--- /dev/null
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <glib/gi18n.h>
+#include <regex.h>
+#include <modest-text-utils.h>
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#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 <body> 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<br>\n<table width=\"100%\" border=\"0\" cellspacing=\"2\" cellpadding=\"2\">\n" \
+ "<tr><td>%s</td><td>%s</td></tr>\n" \
+ "<tr><td>%s</td><td>%s</td></tr>\n" \
+ "<tr><td>%s</td><td>%s</td></tr>\n" \
+ "<tr><td>%s</td><td>%s</td></tr>\n" \
+ "<br><br>%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 <body> 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,
+ "<html>"
+ "<head>"
+ "<meta http-equiv=\"content-type\""
+ " content=\"text/html; charset=utf8\">"
+ "</head>"
+ "<body><tt>");
+
+ /* 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, "<br>\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, "</tt></body></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 = \
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" \
+ "<html>\n" \
+ "<body>\n" \
+ "%s" \
+ "<blockquote type=\"cite\">\n%s\n</blockquote>\n" \
+ "</body>\n" \
+ "</html>\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 (<offset, len, prefix> 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 ("<a href=\"%s%s\">%s</a>",
+ 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 */
+
+ /* <email@address> 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"));
+}
--- /dev/null
+/* Copyright (c) 2006, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* modest-text-utils.h */
+
+#ifndef __MODEST_TEXT_UTILS_H__
+#define __MODEST_TEXT_UTILS_H__
+
+#include <time.h>
+#include <glib.h>
+
+/**
+ * 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 <foo@bar.cx> (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__ */
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#include "modest-validating-entry.h"
+#include <gtk/gtksignal.h> /* For the gtk_signal_stop_emit_by_name() convenience function. */
+#include <string.h> /* 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;
+}
--- /dev/null
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ */
+
+#ifndef _EASYSETUP_VALIDATING_ENTRY
+#define _EASYSETUP_VALIDATING_ENTRY
+
+#include <gtk/gtkentry.h>
+
+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 */
--- /dev/null
+/*
+ * 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 <gtk/gtkdialog.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkbox.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkbutton.h>
+#include <hildon-widgets/hildon-defines.h>
+
+#include "modest-wizard-dialog.h"
+
+#include <libintl.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#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);
+ }
+}
--- /dev/null
+/*
+ * 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 <gtk/gtkwidget.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtkdialog.h>
+
+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__ */
--- /dev/null
+# 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"\r\r# \r
+msgid "osso_db_country_afghanistan"
+msgstr "Afghanistan"
+
+# \r
+msgid "osso_db_country_albania"
+msgstr "Albania"
+
+# \r
+msgid "osso_db_country_algeria"
+msgstr "Algeria"
+
+# \r
+msgid "osso_db_country_american_samoa"
+msgstr "American Samoa"
+
+# \r
+msgid "osso_db_country_andorra"
+msgstr "Andorra"
+
+# \r
+msgid "osso_db_country_angola"
+msgstr "Angola"
+
+# \r
+msgid "osso_db_country_anguilla"
+msgstr "Anguilla"
+
+# \r
+msgid "osso_db_country_antigua_and_barbuda"
+msgstr "Antigua and Barbuda"
+
+# \r
+msgid "osso_db_country_argentina"
+msgstr "Argentine Republic"
+
+# \r
+msgid "osso_db_country_armenia"
+msgstr "Armenia"
+
+# \r
+msgid "osso_db_country_aruba"
+msgstr "Aruba"
+
+# \r
+msgid "osso_db_country_australia"
+msgstr "Australia"
+
+# \r
+msgid "osso_db_country_austria"
+msgstr "Austria"
+
+# \r
+msgid "osso_db_country_azerbaijani_republic"
+msgstr "Azerbaijani Republic"
+
+# \r
+msgid "osso_db_country_bahamas"
+msgstr "Bahamas"
+
+# \r
+msgid "osso_db_country_bahrain"
+msgstr "Bahrain"
+
+# \r
+msgid "osso_db_country_bangladesh"
+msgstr "Bangladesh"
+
+# \r
+msgid "osso_db_country_barbados"
+msgstr "Barbados"
+
+# \r
+msgid "osso_db_country_belarus"
+msgstr "Belarus"
+
+# \r
+msgid "osso_db_country_belgium"
+msgstr "Belgium"
+
+# \r
+msgid "osso_db_country_belize"
+msgstr "Belize"
+
+# \r
+msgid "osso_db_country_benin"
+msgstr "Benin"
+
+# \r
+msgid "osso_db_country_bermuda"
+msgstr "Bermuda"
+
+# \r
+msgid "osso_db_country_bhutan"
+msgstr "Bhutan"
+
+# \r
+msgid "osso_db_country_bolivia"
+msgstr "Bolivia"
+
+# \r
+msgid "osso_db_country_bosnia_and_herzegovina"
+msgstr "Bosnia and Herzegovina"
+
+# \r
+msgid "osso_db_country_botswana"
+msgstr "Botswana"
+
+# \r
+msgid "osso_db_country_brazil"
+msgstr "Brazil"
+
+# \r
+msgid "osso_db_country_british_virgin_islands"
+msgstr "British Virgin Islands"
+
+# \r
+msgid "osso_db_country_brunei_darussalam"
+msgstr "Brunei Darussalam"
+
+# \r
+msgid "osso_db_country_bulgaria"
+msgstr "Bulgaria"
+
+# \r
+msgid "osso_db_country_burkina_faso"
+msgstr "Burkina Faso"
+
+# \r
+msgid "osso_db_country_burundi"
+msgstr "Burundi"
+
+# \r
+msgid "osso_db_country_cambodia"
+msgstr "Cambodia"
+
+# \r
+msgid "osso_db_country_cameroon"
+msgstr "Cameroon"
+
+# \r
+msgid "osso_db_country_canada"
+msgstr "Canada"
+
+# \r
+msgid "osso_db_country_canary_islands_spain"
+msgstr "Canary Islands (Spain)"
+
+# \r
+msgid "osso_db_country_cape_verde"
+msgstr "Cape Verde"
+
+# \r
+msgid "osso_db_country_cayman_islands"
+msgstr "Cayman Islands"
+
+# \r
+msgid "osso_db_country_central_african_republic"
+msgstr "Central African Republic"
+
+# \r
+msgid "osso_db_country_chad"
+msgstr "Chad"
+
+# \r
+msgid "osso_db_country_chile"
+msgstr "Chile"
+
+# \r
+msgid "osso_db_country_china"
+msgstr "China"
+
+# \r
+msgid "osso_db_country_colombia"
+msgstr "Colombia"
+
+# \r
+msgid "osso_db_country_comoros"
+msgstr "Comoros"
+
+# \r
+msgid "osso_db_country_republic_of_the_congo"
+msgstr "Republic of the Congo"
+
+# \r
+msgid "osso_db_country_cook_islands"
+msgstr "Cook Islands"
+
+# \r
+msgid "osso_db_country_costa_rica"
+msgstr "Costa Rica"
+
+# \r
+msgid "osso_db_country_cote_dlvoire"
+msgstr "Cote d'Ivoire"
+
+# \r
+msgid "osso_db_country_croatia"
+msgstr "Croatia"
+
+# \r
+msgid "osso_db_country_cuba"
+msgstr "Cuba"
+
+# \r
+msgid "osso_db_country_cyprus"
+msgstr "Cyprus"
+
+# \r
+msgid "osso_db_country_czech_republic"
+msgstr "Czech Republic"
+
+# \r
+msgid "osso_db_country_democratic_republic_of_the_congo"
+msgstr "Democratic Republic of the Congo"
+
+# \r
+msgid "osso_db_country_denmark"
+msgstr "Denmark"
+
+# \r
+msgid "osso_db_country_djibouti"
+msgstr "Djibouti"
+
+# \r
+msgid "osso_db_country_dominica"
+msgstr "Dominica"
+
+# \r
+msgid "osso_db_country_dominican_republic"
+msgstr "Dominican Republic"
+
+# \r
+msgid "osso_db_country_east_timor"
+msgstr "East Timor"
+
+# \r
+msgid "osso_db_country_ecuador"
+msgstr "Ecuador"
+
+# \r
+msgid "osso_db_country_egypt"
+msgstr "Egypt"
+
+# \r
+msgid "osso_db_country_el_salvador"
+msgstr "El Salvador"
+
+# \r
+msgid "osso_db_country_equatorial_guinea"
+msgstr "Equatorial Guinea"
+
+# \r
+msgid "osso_db_country_eritrea"
+msgstr "Eritrea"
+
+# \r
+msgid "osso_db_country_estonia"
+msgstr "Estonia"
+
+# \r
+msgid "osso_db_country_ethiopia"
+msgstr "Ethiopia"
+
+# \r
+msgid "osso_db_country_faroe_islands"
+msgstr "Faroe Islands"
+
+# \r
+msgid "osso_db_country_fiji"
+msgstr "Fiji"
+
+# \r
+msgid "osso_db_country_finland"
+msgstr "Finland"
+
+# \r
+msgid "osso_db_country_france"
+msgstr "France"
+
+# \r
+msgid "osso_db_country_french_guiana"
+msgstr "French Guiana"
+
+# \r
+msgid "osso_db_country_french_polynesia"
+msgstr "French Polynesia"
+
+# \r
+msgid "osso_db_country_gobonese_republic"
+msgstr "Gabonese Republic"
+
+# \r
+msgid "osso_db_country_gambia"
+msgstr "Gambia"
+
+# \r
+msgid "osso_db_country_georgia"
+msgstr "Georgia"
+
+# \r
+msgid "osso_db_country_germany"
+msgstr "Germany"
+
+# \r
+msgid "osso_db_country_ghana"
+msgstr "Ghana"
+
+# \r
+msgid "osso_db_country_gibraltar"
+msgstr "Gibraltar"
+
+# \r
+msgid "osso_db_country_greece"
+msgstr "Greece"
+
+# \r
+msgid "osso_db_country_greenland"
+msgstr "Greenland"
+
+# \r
+msgid "osso_db_country_hong_kong"
+msgstr "Hong Kong, China"
+
+# \r
+msgid "osso_db_country_grenada"
+msgstr "Grenada"
+
+# \r
+msgid "osso_db_country_guadeloupe"
+msgstr "Guadeloupe"
+
+# \r
+msgid "osso_db_country_guam"
+msgstr "Guam"
+
+# \r
+msgid "osso_db_country_guatemala"
+msgstr "Guatemala"
+
+# \r
+msgid "osso_db_country_guinea"
+msgstr "Guinea"
+
+# \r
+msgid "osso_db_country_guinea_bissaus"
+msgstr "Guinea-Bissau"
+
+# \r
+msgid "osso_db_country_guyana"
+msgstr "Guyana"
+
+# \r
+msgid "osso_db_country_haiti"
+msgstr "Haiti"
+
+# \r
+msgid "osso_db_country_honduras"
+msgstr "Honduras"
+
+# \r
+msgid "osso_db_country_hungary"
+msgstr "Hungary"
+
+# \r
+msgid "osso_db_country_iceland"
+msgstr "Iceland"
+
+# \r
+msgid "osso_db_country_india"
+msgstr "India"
+
+# \r
+msgid "osso_db_country_indonesia"
+msgstr "Indonesia"
+
+# \r
+msgid "osso_db_country_iran"
+msgstr "Iran"
+
+# \r
+msgid "osso_db_country_iraq"
+msgstr "Iraq"
+
+# \r
+msgid "osso_db_country_republic_of_ireland"
+msgstr "Ireland"
+
+# \r
+msgid "osso_db_country_israel"
+msgstr "Israel"
+
+# \r
+msgid "osso_db_country_italy"
+msgstr "Italy"
+
+# \r
+msgid "osso_db_country_jamaica"
+msgstr "Jamaica"
+
+# \r
+msgid "osso_db_country_japan"
+msgstr "Japan"
+
+# \r
+msgid "osso_db_country_jordan"
+msgstr "Jordan"
+
+# \r
+msgid "osso_db_country_kazakhstan"
+msgstr "Kazakhstan"
+
+# \r
+msgid "osso_db_country_kenya"
+msgstr "Kenya"
+
+# \r
+msgid "osso_db_country_kiribati"
+msgstr "Kiribati"
+
+# \r
+msgid "osso_db_country_korea_north"
+msgstr "Korea, North"
+
+# \r
+msgid "osso_db_country_country_south_korea"
+msgstr "Korea, South"
+
+# \r
+msgid "osso_db_country_kuwait"
+msgstr "Kuwait"
+
+# \r
+msgid "osso_db_country_kyrgyz_republic"
+msgstr "Kyrgyz Republic"
+
+# \r
+msgid "osso_db_country_laos"
+msgstr "Laos"
+
+# \r
+msgid "osso_db_country_latvia"
+msgstr "Latvia"
+
+# \r
+msgid "osso_db_country_lebanon"
+msgstr "Lebanon"
+
+# \r
+msgid "osso_db_country_lesotho"
+msgstr "Lesotho"
+
+# \r
+msgid "osso_db_country_liberia"
+msgstr "Liberia"
+
+# \r
+msgid "osso_db_country_libya"
+msgstr "Libya"
+
+# \r
+msgid "osso_db_country_liechtenstein"
+msgstr "Liechtenstein"
+
+# \r
+msgid "osso_db_country_lithuania"
+msgstr "Lithuania"
+
+# \r
+msgid "osso_db_country_luxembourg"
+msgstr "Luxembourg"
+
+# \r
+msgid "osso_db_country_macao"
+msgstr "Macao, China"
+
+# \r
+msgid "osso_db_country_the_former_yugoslav_republic_of_macedonia"
+msgstr "Macedonia"
+
+# \r
+msgid "osso_db_country_madagascar"
+msgstr "Madagascar"
+
+# \r
+msgid "osso_db_country_malawi"
+msgstr "Malawi"
+
+# \r
+msgid "osso_db_country_malaysia"
+msgstr "Malaysia"
+
+# \r
+msgid "osso_db_country_maldives"
+msgstr "Maldives"
+
+# \r
+msgid "osso_db_country_mali"
+msgstr "Mali"
+
+# \r
+msgid "osso_db_country_malta"
+msgstr "Malta"
+
+# \r
+msgid "osso_db_country_marshall_islands"
+msgstr "Marshall Islands"
+
+# \r
+msgid "osso_db_country_martinique"
+msgstr "Martinique"
+
+# \r
+msgid "osso_db_country_mauritania"
+msgstr "Mauritania"
+
+# \r
+msgid "osso_db_country_mauritius"
+msgstr "Mauritius"
+
+# \r
+msgid "osso_db_country_mexico"
+msgstr "Mexico"
+
+# \r
+msgid "osso_db_country_micronesia"
+msgstr "Micronesia"
+
+# \r
+msgid "osso_db_country_republic_of_moldova"
+msgstr "Moldova"
+
+# \r
+msgid "osso_db_country_monaco"
+msgstr "Monaco"
+
+# \r
+msgid "osso_db_country_mongolia"
+msgstr "Mongolia"
+
+# \r
+msgid "osso_db_country_montserrat"
+msgstr "Montserrat"
+
+# \r
+msgid "osso_db_country_morocco"
+msgstr "Morocco"
+
+# \r
+msgid "osso_db_country_mozambique"
+msgstr "Mozambique"
+
+# \r
+msgid "osso_db_country_myanmar"
+msgstr "Myanmar"
+
+# \r
+msgid "osso_db_country_namibia"
+msgstr "Namibia"
+
+# \r
+msgid "osso_db_country_nauru"
+msgstr "Nauru"
+
+# \r
+msgid "osso_db_country_nepal"
+msgstr "Nepal"
+
+# \r
+msgid "osso_db_country_netherlands"
+msgstr "Netherlands"
+
+# \r
+msgid "osso_db_country_netherlands_antilles"
+msgstr "Netherlands Antilles"
+
+# \r
+msgid "osso_db_country_new_caledonia"
+msgstr "New Caledonia"
+
+# \r
+msgid "osso_db_country_new_zealand"
+msgstr "New Zealand"
+
+# \r
+msgid "osso_db_country_nicaraqua"
+msgstr "Nicaragua"
+
+# \r
+msgid "osso_db_country_niger"
+msgstr "Niger"
+
+# \r
+msgid "osso_db_country_nigeria"
+msgstr "Nigeria"
+
+# \r
+msgid "osso_db_country_northern_mariana_islands"
+msgstr "Northern Mariana Islands"
+
+# \r
+msgid "osso_db_country_norway"
+msgstr "Norway"
+
+# \r
+msgid "osso_db_country_oman"
+msgstr "Oman"
+
+# \r
+msgid "osso_db_country_pakistan"
+msgstr "Pakistan"
+
+# \r
+msgid "osso_db_country_palau"
+msgstr "Palau"
+
+# \r
+msgid "osso_db_country_panama"
+msgstr "Panama"
+
+# \r
+msgid "osso_db_country_papua_new_guinea"
+msgstr "Papua New Guinea"
+
+# \r
+msgid "osso_db_country_paraquay"
+msgstr "Paraguay"
+
+# \r
+msgid "osso_db_country_peru"
+msgstr "Peru"
+
+# \r
+msgid "osso_db_country_philippines"
+msgstr "Philippines"
+
+# \r
+msgid "osso_db_country_poland"
+msgstr "Poland"
+
+# \r
+msgid "osso_db_country_portugal"
+msgstr "Portugal"
+
+# \r
+msgid "osso_db_country_puerto_rico"
+msgstr "Puerto Rico"
+
+# \r
+msgid "osso_db_country_qatar"
+msgstr "Qatar"
+
+# \r
+msgid "osso_db_country_reunion"
+msgstr "Reunion"
+
+# \r
+msgid "osso_db_country_romania"
+msgstr "Romania"
+
+# \r
+msgid "osso_db_country_russian_federation"
+msgstr "Russian Federation"
+
+# \r
+msgid "osso_db_country_rwandese_republic"
+msgstr "Rwandese Republic"
+
+# \r
+msgid "osso_db_country_saint_kitts_and_nevis"
+msgstr "Saint Kitts and Nevis"
+
+# \r
+msgid "osso_db_country_saint_lucia"
+msgstr "Saint Lucia"
+
+# \r
+msgid "osso_db_country_saint_pierre_and_miquelon"
+msgstr "Saint Pierre and Miquelon"
+
+# \r
+msgid "osso_db_country_saint_vincent_and_grenadines"
+msgstr "Saint Vincent and the Grenadines"
+
+# \r
+msgid "osso_db_country_samoa"
+msgstr "Samoa"
+
+# \r
+msgid "osso_db_country_san_marino"
+msgstr "San Marino"
+
+# \r
+msgid "osso_db_country_sao_tome_and_principe"
+msgstr "Sao Tome and Principe"
+
+# \r
+msgid "osso_db_country_saudi_arabia"
+msgstr "Saudi Arabia"
+
+# \r
+msgid "osso_db_country_senegal"
+msgstr "Senegal"
+
+# \r
+msgid "osso_db_country_serbia_and_montenegro"
+msgstr "Serbia and Montenegro"
+
+# \r
+msgid "osso_db_country_seychelles"
+msgstr "Seychelles"
+
+# \r
+msgid "osso_db_country_sierra_leone"
+msgstr "Sierra Leone"
+
+# \r
+msgid "osso_db_country_singapore"
+msgstr "Singapore"
+
+# \r
+msgid "osso_db_country_slovakia"
+msgstr "Slovakia"
+
+# \r
+msgid "osso_db_country_slovenia"
+msgstr "Slovenia"
+
+# \r
+msgid "osso_db_country_solomon_islands"
+msgstr "Solomon Islands"
+
+# \r
+msgid "osso_db_country_somalia"
+msgstr "Somalia"
+
+# \r
+msgid "osso_db_country_south_africa"
+msgstr "South Africa"
+
+# \r
+msgid "osso_db_country_spain"
+msgstr "Spain"
+
+# \r
+msgid "osso_db_country_sri_lanka"
+msgstr "Sri Lanka"
+
+# \r
+msgid "osso_db_country_sudan"
+msgstr "Sudan"
+
+# \r
+msgid "osso_db_country_suriname"
+msgstr "Suriname"
+
+# \r
+msgid "osso_db_country_swaziland"
+msgstr "Swaziland"
+
+# \r
+msgid "osso_db_country_sweden"
+msgstr "Sweden"
+
+# \r
+msgid "osso_db_country_switzerland"
+msgstr "Switzerland"
+
+# \r
+msgid "osso_db_country_syrian_arab_republic"
+msgstr "Syria"
+
+# \r
+msgid "osso_db_country_taiwan"
+msgstr "Taiwan"
+
+# \r
+msgid "osso_db_country_tajikistan"
+msgstr "Tajikistan"
+
+# \r
+msgid "osso_db_country_united_republic_of_tanzania"
+msgstr "Tanzania"
+
+# \r
+msgid "osso_db_country_thailand"
+msgstr "Thailand"
+
+# \r
+msgid "osso_db_country_the_vatican"
+msgstr "Vatican City State"
+
+# \r
+msgid "osso_db_country_tibet"
+msgstr "Tibet"
+
+# \r
+msgid "osso_db_country_tunisia"
+msgstr "Tunisia"
+
+# \r
+msgid "osso_db_country_turkey"
+msgstr "Turkey"
+
+# \r
+msgid "osso_db_country_ukraine"
+msgstr "Ukraine"
+
+# \r
+msgid "osso_db_country_united_arab_emirates"
+msgstr "United Arab Emirates"
+
+# \r
+msgid "osso_db_country_united_arab_emirates_abu_dhabi"
+msgstr "United Arab Emirates (Abu Dhabi)"
+
+# \r
+msgid "osso_db_country_united_arab_emirates_dubai"
+msgstr "United Arab Emirates (Dubai)"
+
+# \r
+msgid "osso_db_country_togolese_republic"
+msgstr "Togolese Republic"
+
+# \r
+msgid "osso_db_country_tonga"
+msgstr "Tonga"
+
+# \r
+msgid "osso_db_country_trinidad_and_tobago"
+msgstr "Trinidad and Tobago"
+
+# \r
+msgid "osso_db_country_turkmenistan"
+msgstr "Turkmenistan"
+
+# \r
+msgid "osso_db_country_turks_and_caicos_islands"
+msgstr "Turks and Caicos Islands"
+
+# \r
+msgid "osso_db_country_uganda"
+msgstr "Uganda"
+
+# \r
+msgid "osso_db_country_united_kingdom_of_great_britain_and_northern_ireland"
+msgstr "United Kingdom"
+
+# \r
+msgid "osso_db_country_united_states_of_america"
+msgstr "United States of America"
+
+# \r
+msgid "osso_db_country_unites_states_virgin_islands"
+msgstr "United States Virgin Islands"
+
+# \r
+msgid "osso_db_country_uruguay"
+msgstr "Uruguay"
+
+# \r
+msgid "osso_db_country_uzbekistan"
+msgstr "Uzbekistan"
+
+# \r
+msgid "osso_db_country_vanuatu"
+msgstr "Vanuatu"
+
+# \r
+msgid "osso_db_country_venezuela"
+msgstr "Venezuela"
+
+# \r
+msgid "osso_db_country_viet_nam"
+msgstr "Viet Nam"
+
+# \r
+msgid "osso_db_country_wallis_and_futuna"
+msgstr "Wallis and Futuna"
+
+# \r
+msgid "osso_db_country_yemen"
+msgstr "Yemen"
+
+# \r
+msgid "osso_db_country_zambia"
+msgstr "Zambia"
+
+# \r
+msgid "osso_db_country_zimbabwe"
+msgstr "Zimbabwe"
+
--- /dev/null
+[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