90dd408534866869fcf1d8e5aca67c579dbbca9b
[modest] / src / maemo / easysetup / modest-easysetup-servertype-combo-box.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "modest-easysetup-servertype-combo-box.h"
31 #include <gtk/gtkliststore.h>
32 #include <gtk/gtkcelllayout.h>
33 #include <gtk/gtkcellrenderertext.h>
34 #include <glib/gi18n.h>
35
36 #include <stdlib.h>
37 #include <string.h> /* For memcpy() */
38
39 /* Include config.h so that _() works: */
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43
44 G_DEFINE_TYPE (EasysetupServertypeComboBox, easysetup_servertype_combo_box, GTK_TYPE_COMBO_BOX);
45
46 #define SERVERTYPE_COMBO_BOX_GET_PRIVATE(o) \
47         (G_TYPE_INSTANCE_GET_PRIVATE ((o), EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX, EasysetupServertypeComboBoxPrivate))
48
49 typedef struct _EasysetupServertypeComboBoxPrivate EasysetupServertypeComboBoxPrivate;
50
51 struct _EasysetupServertypeComboBoxPrivate
52 {
53         GtkTreeModel *model;
54 };
55
56 static void
57 easysetup_servertype_combo_box_get_property (GObject *object, guint property_id,
58                                                                                                                         GValue *value, GParamSpec *pspec)
59 {
60         switch (property_id) {
61         default:
62                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
63         }
64 }
65
66 static void
67 easysetup_servertype_combo_box_set_property (GObject *object, guint property_id,
68                                                                                                                         const GValue *value, GParamSpec *pspec)
69 {
70         switch (property_id) {
71         default:
72                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
73         }
74 }
75
76 static void
77 easysetup_servertype_combo_box_dispose (GObject *object)
78 {
79         if (G_OBJECT_CLASS (easysetup_servertype_combo_box_parent_class)->dispose)
80                 G_OBJECT_CLASS (easysetup_servertype_combo_box_parent_class)->dispose (object);
81 }
82
83 static void
84 easysetup_servertype_combo_box_finalize (GObject *object)
85 {
86         EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (object);
87
88         g_object_unref (G_OBJECT (priv->model));
89
90         G_OBJECT_CLASS (easysetup_servertype_combo_box_parent_class)->finalize (object);
91 }
92
93 static void
94 easysetup_servertype_combo_box_class_init (EasysetupServertypeComboBoxClass *klass)
95 {
96         GObjectClass *object_class = G_OBJECT_CLASS (klass);
97
98         g_type_class_add_private (klass, sizeof (EasysetupServertypeComboBoxPrivate));
99
100         object_class->get_property = easysetup_servertype_combo_box_get_property;
101         object_class->set_property = easysetup_servertype_combo_box_set_property;
102         object_class->dispose = easysetup_servertype_combo_box_dispose;
103         object_class->finalize = easysetup_servertype_combo_box_finalize;
104 }
105
106 enum MODEL_COLS {
107         MODEL_COL_NAME = 0, /* a string */
108         MODEL_COL_ID = 1 /* an int. */
109 };
110
111 static void
112 easysetup_servertype_combo_box_fill (EasysetupServertypeComboBox *combobox);
113
114 static void
115 easysetup_servertype_combo_box_init (EasysetupServertypeComboBox *self)
116 {
117         EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (self);
118
119         /* Create a tree model for the combo box,
120          * with a string for the name, and an ID for the servertype.
121          * This must match our MODEL_COLS enum constants.
122          */
123         priv->model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
124
125         /* Setup the combo box: */
126         GtkComboBox *combobox = GTK_COMBO_BOX (self);
127         gtk_combo_box_set_model (combobox, priv->model);
128
129         /* Servertype column:
130          * The ID model column in not shown in the view. */
131         GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
132         gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (combobox), renderer, TRUE);
133         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, 
134         "text", MODEL_COL_NAME, NULL);
135         
136         easysetup_servertype_combo_box_fill (self);
137 }
138
139 EasysetupServertypeComboBox*
140 easysetup_servertype_combo_box_new (void)
141 {
142         return g_object_new (EASYSETUP_TYPE_SERVERTYPE_COMBO_BOX, NULL);
143 }
144
145 void easysetup_servertype_combo_box_fill (EasysetupServertypeComboBox *combobox)
146 {       
147         EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (combobox);
148         
149         /* Remove any existing rows: */
150         GtkListStore *liststore = GTK_LIST_STORE (priv->model);
151         gtk_list_store_clear (liststore);
152         
153         GtkTreeIter iter;
154         gtk_list_store_append (liststore, &iter);
155         gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_STORE_POP, MODEL_COL_NAME, _("mail_fi_emailtype_pop3"), -1);
156         
157         /* Select the POP item: */
158         gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox), &iter);
159         
160         gtk_list_store_append (liststore, &iter);
161         gtk_list_store_set (liststore, &iter, MODEL_COL_ID, (gint)MODEST_PROTOCOL_STORE_IMAP, MODEL_COL_NAME, _("mail_fi_emailtype_imap"), -1);
162 }
163
164 /**
165  * Returns the selected servertype, 
166  * or MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN if no servertype was selected.
167  */
168 ModestTransportStoreProtocol
169 easysetup_servertype_combo_box_get_active_servertype (EasysetupServertypeComboBox *combobox)
170 {
171         GtkTreeIter active;
172         const gboolean found = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &active);
173         if (found) {
174                 EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (combobox);
175
176                 ModestTransportStoreProtocol servertype = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
177                 gtk_tree_model_get (priv->model, &active, MODEL_COL_ID, &servertype, -1);
178                 return servertype;      
179         }
180
181         return MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN; /* Failed. */
182 }
183
184 /* This allows us to pass more than one piece of data to the signal handler,
185  * and get a result: */
186 typedef struct 
187 {
188                 EasysetupServertypeComboBox* self;
189                 gint id;
190                 gboolean found;
191 } ForEachData;
192
193 static gboolean
194 on_model_foreach_select_id(GtkTreeModel *model, 
195         GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
196 {
197         ForEachData *state = (ForEachData*)(user_data);
198         
199         /* Select the item if it has the matching ID: */
200         guint id = 0;
201         gtk_tree_model_get (model, iter, MODEL_COL_ID, &id, -1); 
202         if(id == state->id) {
203                 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (state->self), iter);
204                 
205                 state->found = TRUE;
206                 return TRUE; /* Stop walking the tree. */
207         }
208         
209         return FALSE; /* Keep walking the tree. */
210 }
211
212 /**
213  * Selects the specified servertype, 
214  * or MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN if no servertype was selected.
215  */
216 gboolean
217 easysetup_servertype_combo_box_set_active_servertype (EasysetupServertypeComboBox *combobox, ModestTransportStoreProtocol servertype)
218 {
219         EasysetupServertypeComboBoxPrivate *priv = SERVERTYPE_COMBO_BOX_GET_PRIVATE (combobox);
220         
221         /* Create a state instance so we can send two items of data to the signal handler: */
222         ForEachData *state = g_new0 (ForEachData, 1);
223         state->self = combobox;
224         state->id = servertype;
225         state->found = FALSE;
226         
227         /* Look at each item, and select the one with the correct ID: */
228         gtk_tree_model_foreach (priv->model, &on_model_foreach_select_id, state);
229
230         const gboolean result = state->found;
231         
232         /* Free the state instance: */
233         g_free(state);
234         
235         return result;
236 }
237