1 /*
2  * e-mail-config-provider-page.c
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17 
18 #include "evolution-config.h"
19 
20 #include <string.h>
21 #include <glib/gi18n-lib.h>
22 
23 #include <libebackend/libebackend.h>
24 
25 #include "e-mail-config-provider-page.h"
26 
27 #define E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE(obj) \
28 	(G_TYPE_INSTANCE_GET_PRIVATE \
29 	((obj), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, EMailConfigProviderPagePrivate))
30 
31 #define STANDARD_MARGIN   12
32 #define DEPENDENCY_MARGIN 24
33 
34 struct _EMailConfigProviderPagePrivate {
35 	EMailConfigServiceBackend *backend;
36 	gboolean is_empty;
37 };
38 
39 enum {
40 	PROP_0,
41 	PROP_BACKEND
42 };
43 
44 /* Forward Declarations */
45 static void	e_mail_config_provider_page_interface_init
46 					(EMailConfigPageInterface *iface);
47 
G_DEFINE_TYPE_WITH_CODE(EMailConfigProviderPage,e_mail_config_provider_page,E_TYPE_MAIL_CONFIG_ACTIVITY_PAGE,G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE,NULL)G_IMPLEMENT_INTERFACE (E_TYPE_MAIL_CONFIG_PAGE,e_mail_config_provider_page_interface_init))48 G_DEFINE_TYPE_WITH_CODE (
49 	EMailConfigProviderPage,
50 	e_mail_config_provider_page,
51 	E_TYPE_MAIL_CONFIG_ACTIVITY_PAGE,
52 	G_IMPLEMENT_INTERFACE (
53 		E_TYPE_EXTENSIBLE, NULL)
54 	G_IMPLEMENT_INTERFACE (
55 		E_TYPE_MAIL_CONFIG_PAGE,
56 		e_mail_config_provider_page_interface_init))
57 
58 static void
59 mail_config_provider_page_handle_dependency (EMailConfigProviderPage *page,
60                                              CamelProviderConfEntry *entry,
61                                              GtkWidget *widget)
62 {
63 	EMailConfigServiceBackend *backend;
64 	CamelSettings *settings;
65 	GBindingFlags binding_flags = G_BINDING_SYNC_CREATE;
66 	const gchar *depname = entry->depname;
67 	gint margin;
68 
69 	if (depname == NULL)
70 		return;
71 
72 	if (*depname == '!') {
73 		binding_flags |= G_BINDING_INVERT_BOOLEAN;
74 		depname++;
75 	}
76 
77 	backend = e_mail_config_provider_page_get_backend (page);
78 	settings = e_mail_config_service_backend_get_settings (backend);
79 
80 	e_binding_bind_property (
81 		settings, depname,
82 		widget, "sensitive",
83 		binding_flags);
84 
85 	/* Further indent the widget to show its dependency. */
86 	margin = gtk_widget_get_margin_left (widget);
87 	gtk_widget_set_margin_left (widget, margin + DEPENDENCY_MARGIN);
88 }
89 
90 static void
mail_config_provider_page_add_section(EMailConfigProviderPage * page,GtkBox * main_box,CamelProviderConfEntry * entry)91 mail_config_provider_page_add_section (EMailConfigProviderPage *page,
92 				       GtkBox *main_box,
93                                        CamelProviderConfEntry *entry)
94 {
95 	EMailConfigServiceBackend *backend;
96 	CamelProvider *provider;
97 	GtkWidget *widget;
98 	gchar *markup;
99 
100 	g_return_if_fail (entry->text != NULL);
101 
102 	backend = e_mail_config_provider_page_get_backend (page);
103 	provider = e_mail_config_service_backend_get_provider (backend);
104 
105 	markup = g_markup_printf_escaped ("<b>%s</b>", entry->text);
106 
107 	widget = gtk_label_new (markup);
108 	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
109 	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
110 	gtk_box_pack_start (main_box, widget, FALSE, FALSE, 0);
111 	gtk_widget_show (widget);
112 
113 	/* Skip the top margin if this is the first entry. */
114 	if (entry != provider->extra_conf)
115 		gtk_widget_set_margin_top (widget, 6);
116 
117 	g_free (markup);
118 }
119 
120 static void
mail_config_provider_page_add_checkbox(EMailConfigProviderPage * page,GtkBox * main_box,CamelProviderConfEntry * entry)121 mail_config_provider_page_add_checkbox (EMailConfigProviderPage *page,
122 					GtkBox *main_box,
123                                         CamelProviderConfEntry *entry)
124 {
125 	EMailConfigServiceBackend *backend;
126 	CamelSettings *settings;
127 	GtkWidget *widget;
128 
129 	g_return_if_fail (entry->text != NULL);
130 
131 	backend = e_mail_config_provider_page_get_backend (page);
132 	settings = e_mail_config_service_backend_get_settings (backend);
133 
134 	widget = gtk_check_button_new_with_mnemonic (entry->text);
135 	gtk_widget_set_margin_left (widget, STANDARD_MARGIN);
136 	gtk_box_pack_start (main_box, widget, FALSE, FALSE, 0);
137 	gtk_widget_show (widget);
138 
139 	e_binding_bind_property (
140 		settings, entry->name,
141 		widget, "active",
142 		G_BINDING_BIDIRECTIONAL |
143 		G_BINDING_SYNC_CREATE);
144 
145 	mail_config_provider_page_handle_dependency (page, entry, widget);
146 }
147 
148 static void
mail_config_provider_page_add_checkspin(EMailConfigProviderPage * page,GtkBox * main_box,CamelProviderConfEntry * entry)149 mail_config_provider_page_add_checkspin (EMailConfigProviderPage *page,
150 					 GtkBox *main_box,
151                                          CamelProviderConfEntry *entry)
152 {
153 	EMailConfigServiceBackend *backend;
154 	CamelSettings *settings;
155 	GObjectClass *class;
156 	GParamSpec *pspec;
157 	GParamSpec *use_pspec;
158 	GtkAdjustment *adjustment;
159 	GtkWidget *hbox, *spin;
160 	GtkWidget *prefix;
161 	gchar *use_property_name;
162 	gchar *pre, *post;
163 
164 	g_return_if_fail (entry->text != NULL);
165 
166 	backend = e_mail_config_provider_page_get_backend (page);
167 	settings = e_mail_config_service_backend_get_settings (backend);
168 
169 	/* The entry->name property (e.g. "foo") should be numeric for the
170 	 * spin button.  If a "use" boolean property exists (e.g. "use-foo")
171 	 * then a checkbox is also shown. */
172 
173 	class = G_OBJECT_GET_CLASS (settings);
174 	pspec = g_object_class_find_property (class, entry->name);
175 	g_return_if_fail (pspec != NULL);
176 
177 	use_property_name = g_strconcat ("use-", entry->name, NULL);
178 	use_pspec = g_object_class_find_property (class, use_property_name);
179 	if (use_pspec != NULL && use_pspec->value_type != G_TYPE_BOOLEAN)
180 		use_pspec = NULL;
181 	g_free (use_property_name);
182 
183 	/* Make sure we can convert to and from doubles. */
184 	g_return_if_fail (
185 		g_value_type_transformable (
186 		pspec->value_type, G_TYPE_DOUBLE));
187 	g_return_if_fail (
188 		g_value_type_transformable (
189 		G_TYPE_DOUBLE, pspec->value_type));
190 
191 	if (G_IS_PARAM_SPEC_CHAR (pspec)) {
192 		GParamSpecChar *pspec_char;
193 		pspec_char = G_PARAM_SPEC_CHAR (pspec);
194 		adjustment = gtk_adjustment_new (
195 			(gdouble) pspec_char->default_value,
196 			(gdouble) pspec_char->minimum,
197 			(gdouble) pspec_char->maximum,
198 			1.0, 1.0, 0.0);
199 
200 	} else if (G_IS_PARAM_SPEC_UCHAR (pspec)) {
201 		GParamSpecUChar *pspec_uchar;
202 		pspec_uchar = G_PARAM_SPEC_UCHAR (pspec);
203 		adjustment = gtk_adjustment_new (
204 			(gdouble) pspec_uchar->default_value,
205 			(gdouble) pspec_uchar->minimum,
206 			(gdouble) pspec_uchar->maximum,
207 			1.0, 1.0, 0.0);
208 
209 	} else if (G_IS_PARAM_SPEC_INT (pspec)) {
210 		GParamSpecInt *pspec_int;
211 		pspec_int = G_PARAM_SPEC_INT (pspec);
212 		adjustment = gtk_adjustment_new (
213 			(gdouble) pspec_int->default_value,
214 			(gdouble) pspec_int->minimum,
215 			(gdouble) pspec_int->maximum,
216 			1.0, 1.0, 0.0);
217 
218 	} else if (G_IS_PARAM_SPEC_UINT (pspec)) {
219 		GParamSpecUInt *pspec_uint;
220 		pspec_uint = G_PARAM_SPEC_UINT (pspec);
221 		adjustment = gtk_adjustment_new (
222 			(gdouble) pspec_uint->default_value,
223 			(gdouble) pspec_uint->minimum,
224 			(gdouble) pspec_uint->maximum,
225 			1.0, 1.0, 0.0);
226 
227 	} else if (G_IS_PARAM_SPEC_LONG (pspec)) {
228 		GParamSpecLong *pspec_long;
229 		pspec_long = G_PARAM_SPEC_LONG (pspec);
230 		adjustment = gtk_adjustment_new (
231 			(gdouble) pspec_long->default_value,
232 			(gdouble) pspec_long->minimum,
233 			(gdouble) pspec_long->maximum,
234 			1.0, 1.0, 0.0);
235 
236 	} else if (G_IS_PARAM_SPEC_ULONG (pspec)) {
237 		GParamSpecULong *pspec_ulong;
238 		pspec_ulong = G_PARAM_SPEC_ULONG (pspec);
239 		adjustment = gtk_adjustment_new (
240 			(gdouble) pspec_ulong->default_value,
241 			(gdouble) pspec_ulong->minimum,
242 			(gdouble) pspec_ulong->maximum,
243 			1.0, 1.0, 0.0);
244 
245 	} else if (G_IS_PARAM_SPEC_FLOAT (pspec)) {
246 		GParamSpecFloat *pspec_float;
247 		pspec_float = G_PARAM_SPEC_FLOAT (pspec);
248 		adjustment = gtk_adjustment_new (
249 			(gdouble) pspec_float->default_value,
250 			(gdouble) pspec_float->minimum,
251 			(gdouble) pspec_float->maximum,
252 			1.0, 1.0, 0.0);
253 
254 	} else if (G_IS_PARAM_SPEC_DOUBLE (pspec)) {
255 		GParamSpecDouble *pspec_double;
256 		pspec_double = G_PARAM_SPEC_DOUBLE (pspec);
257 		adjustment = gtk_adjustment_new (
258 			(gdouble) pspec_double->default_value,
259 			(gdouble) pspec_double->minimum,
260 			(gdouble) pspec_double->maximum,
261 			1.0, 1.0, 0.0);
262 
263 	} else
264 		g_return_if_reached ();
265 
266 	pre = g_alloca (strlen (entry->text) + 1);
267 	strcpy (pre, entry->text);
268 	post = strstr (pre, "%s");
269 	if (post != NULL) {
270 		*post = '\0';
271 		post += 2;
272 	}
273 
274 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
275 	gtk_widget_set_margin_left (hbox, STANDARD_MARGIN);
276 	gtk_box_pack_start (main_box, hbox, FALSE, FALSE, 0);
277 	gtk_widget_show (hbox);
278 
279 	if (use_pspec != NULL) {
280 		prefix = gtk_check_button_new_with_mnemonic (pre);
281 
282 		e_binding_bind_property (
283 			settings, use_pspec->name,
284 			prefix, "active",
285 			G_BINDING_BIDIRECTIONAL |
286 			G_BINDING_SYNC_CREATE);
287 	} else {
288 		prefix = gtk_label_new_with_mnemonic (pre);
289 	}
290 	gtk_box_pack_start (GTK_BOX (hbox), prefix, FALSE, TRUE, 0);
291 	gtk_widget_show (prefix);
292 
293 	spin = gtk_spin_button_new (adjustment, 1.0, 0);
294 	gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, TRUE, 0);
295 	gtk_widget_show (spin);
296 
297 	if (!use_pspec)
298 		gtk_label_set_mnemonic_widget (GTK_LABEL (prefix), spin);
299 
300 	e_binding_bind_property (
301 		settings, entry->name,
302 		spin, "value",
303 		G_BINDING_BIDIRECTIONAL |
304 		G_BINDING_SYNC_CREATE);
305 
306 	if (use_pspec != NULL)
307 		e_binding_bind_property (
308 			prefix, "active",
309 			spin, "sensitive",
310 			G_BINDING_SYNC_CREATE);
311 
312 	if (post != NULL) {
313 		GtkWidget *label = gtk_label_new_with_mnemonic (post);
314 		gtk_label_set_mnemonic_widget (GTK_LABEL (label), use_pspec ? prefix : spin);
315 		gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
316 		gtk_widget_show (label);
317 	}
318 
319 	mail_config_provider_page_handle_dependency (page, entry, hbox);
320 }
321 
322 static void
mail_config_provider_page_add_entry(EMailConfigProviderPage * page,GtkBox * main_box,CamelProviderConfEntry * entry)323 mail_config_provider_page_add_entry (EMailConfigProviderPage *page,
324 				     GtkBox *main_box,
325                                      CamelProviderConfEntry *entry)
326 {
327 	EMailConfigServiceBackend *backend;
328 	CamelSettings *settings;
329 	GtkWidget *hbox;
330 	GtkWidget *input;
331 	GtkWidget *label;
332 
333 	g_return_if_fail (entry->text != NULL);
334 
335 	backend = e_mail_config_provider_page_get_backend (page);
336 	settings = e_mail_config_service_backend_get_settings (backend);
337 
338 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
339 	gtk_box_set_spacing (GTK_BOX (hbox), 6);
340 	gtk_widget_set_margin_left (hbox, STANDARD_MARGIN);
341 	gtk_box_pack_start (main_box, hbox, FALSE, FALSE, 0);
342 	gtk_widget_show (hbox);
343 
344 	label = gtk_label_new_with_mnemonic (entry->text);
345 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
346 	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
347 	gtk_widget_show (label);
348 
349 	input = gtk_entry_new ();
350 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), input);
351 	gtk_box_pack_start (GTK_BOX (hbox), input, TRUE, TRUE, 0);
352 	gtk_widget_show (input);
353 
354 	e_binding_bind_object_text_property (
355 		settings, entry->name,
356 		input, "text",
357 		G_BINDING_BIDIRECTIONAL |
358 		G_BINDING_SYNC_CREATE);
359 
360 	e_binding_bind_property (
361 		input, "sensitive",
362 		label, "sensitive",
363 		G_BINDING_SYNC_CREATE);
364 
365 	mail_config_provider_page_handle_dependency (page, entry, hbox);
366 }
367 
368 static void
mail_config_provider_page_add_label(EMailConfigProviderPage * page,GtkBox * main_box,CamelProviderConfEntry * entry)369 mail_config_provider_page_add_label (EMailConfigProviderPage *page,
370 				     GtkBox *main_box,
371 				     CamelProviderConfEntry *entry)
372 {
373 	GtkWidget *hbox;
374 	GtkWidget *label;
375 
376 	g_return_if_fail (entry->text != NULL);
377 
378 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
379 	gtk_box_set_spacing (GTK_BOX (hbox), 6);
380 	gtk_widget_set_margin_left (hbox, STANDARD_MARGIN);
381 	gtk_box_pack_start (main_box, hbox, FALSE, FALSE, 0);
382 	gtk_widget_show (hbox);
383 
384 	label = gtk_label_new (entry->text);
385 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
386 	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
387 	gtk_widget_show (label);
388 
389 	mail_config_provider_page_handle_dependency (page, entry, hbox);
390 }
391 
392 static void
mail_config_provider_page_add_options(EMailConfigProviderPage * page,GtkBox * main_box,CamelProviderConfEntry * entry)393 mail_config_provider_page_add_options (EMailConfigProviderPage *page,
394 				       GtkBox *main_box,
395                                        CamelProviderConfEntry *entry)
396 {
397 	EMailConfigServiceBackend *backend;
398 	CamelProvider *provider;
399 	CamelSettings *settings;
400 	GtkCellRenderer *renderer;
401 	GtkListStore *store;
402 	GtkWidget *hbox;
403 	GtkWidget *combo;
404 	GtkWidget *label;
405 	gchar **tokens;
406 	guint length, ii;
407 
408 	/* The 'value' string is of the format:
409 	 *
410 	 *   'nick0:caption0:nick1:caption1:...nickN:captionN'
411 	 *
412 	 * where 'nick' is the nickname a GEnumValue and 'caption'
413 	 * is the localized combo box item displayed to the user. */
414 
415 	g_return_if_fail (entry->text != NULL);
416 	g_return_if_fail (entry->value != NULL);
417 
418 	backend = e_mail_config_provider_page_get_backend (page);
419 	provider = e_mail_config_service_backend_get_provider (backend);
420 	settings = e_mail_config_service_backend_get_settings (backend);
421 
422 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
423 	gtk_box_set_spacing (GTK_BOX (hbox), 6);
424 	gtk_widget_set_margin_left (hbox, STANDARD_MARGIN);
425 	gtk_box_pack_start (main_box, hbox, FALSE, FALSE, 0);
426 	gtk_widget_show (hbox);
427 
428 	label = gtk_label_new_with_mnemonic (entry->text);
429 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
430 	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
431 	gtk_widget_show (label);
432 
433 	/* 0: 'nick', 1: caption */
434 	store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
435 
436 	tokens = g_strsplit (entry->value, ":", -1);
437 	length = g_strv_length (tokens);
438 
439 	/* Take the strings two at a time. */
440 	for (ii = 0; ii + 1 < length; ii += 2) {
441 		GtkTreeIter iter;
442 		const gchar *nick;
443 		const gchar *caption;
444 
445 		nick = tokens[ii + 0];
446 		caption = tokens[ii + 1];
447 
448 		/* Localize the caption. */
449 		caption = dgettext (provider->translation_domain, caption);
450 
451 		gtk_list_store_append (store, &iter);
452 		gtk_list_store_set (store, &iter, 0, nick, 1, caption, -1);
453 	}
454 
455 	g_strfreev (tokens);
456 
457 	combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
458 	gtk_combo_box_set_id_column (GTK_COMBO_BOX (combo), 0);
459 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
460 	gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
461 	gtk_widget_show (combo);
462 	g_object_unref (store);
463 
464 	e_binding_bind_property_full (
465 		settings, entry->name,
466 		combo, "active-id",
467 		G_BINDING_BIDIRECTIONAL |
468 		G_BINDING_SYNC_CREATE,
469 		e_binding_transform_enum_value_to_nick,
470 		e_binding_transform_enum_nick_to_value,
471 		NULL, (GDestroyNotify) NULL);
472 
473 	renderer = gtk_cell_renderer_text_new ();
474 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
475 	gtk_cell_layout_set_attributes (
476 		GTK_CELL_LAYOUT (combo), renderer, "text", 1, NULL);
477 
478 	mail_config_provider_page_handle_dependency (page, entry, hbox);
479 }
480 
481 static void
mail_config_provider_page_add_placeholder(EMailConfigProviderPage * page,GtkBox * main_box,CamelProviderConfEntry * entry)482 mail_config_provider_page_add_placeholder (EMailConfigProviderPage *page,
483 					   GtkBox *main_box,
484 					   CamelProviderConfEntry *entry)
485 {
486 	GtkWidget *hbox;
487 
488 	/* The entry->name is used as an identifier of the placeholder,
489 	   which is used with e_mail_config_provider_page_get_placeholder(). */
490 
491 	g_return_if_fail (entry->name && *(entry->name));
492 
493 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
494 	gtk_widget_set_name (hbox, entry->name);
495 	gtk_box_set_spacing (GTK_BOX (hbox), 6);
496 	gtk_widget_set_margin_left (hbox, STANDARD_MARGIN);
497 	gtk_box_pack_start (main_box, hbox, FALSE, FALSE, 0);
498 	gtk_widget_show (hbox);
499 
500 	mail_config_provider_page_handle_dependency (page, entry, hbox);
501 }
502 
503 static void
mail_config_provider_page_add_widgets(EMailConfigProviderPage * page,GtkBox * main_box)504 mail_config_provider_page_add_widgets (EMailConfigProviderPage *page,
505 				       GtkBox *main_box)
506 {
507 	EMailConfigServiceBackend *backend;
508 	CamelProviderConfEntry *entries;
509 	CamelProvider *provider;
510 	GtkWidget *container;
511 	GtkWidget *widget;
512 	ESource *source;
513 	ESourceExtension *extension;
514 	gboolean first_section = TRUE;
515 	const gchar *extension_name;
516 	const gchar *text;
517 	gchar *markup;
518 	gint ii;
519 
520 	/* XXX We begin the page with our own section header and refresh
521 	 *     interval setting, and then skip the CamelProvider's first
522 	 *     CAMEL_PROVIDER_CONF_SECTION_START entry.
523 	 *
524 	 *     This is all very brittle.  I'm convinced that generating
525 	 *     a user interface from an array of records like this is a
526 	 *     bad idea.  We already have EMailConfigServiceBackend for
527 	 *     building provider-specific "Receving Email" and "Sending
528 	 *     EMail" pages by hand.  We should do similarly here. */
529 
530 	backend = e_mail_config_provider_page_get_backend (page);
531 	source = e_mail_config_service_backend_get_source (backend);
532 	provider = e_mail_config_service_backend_get_provider (backend);
533 	g_return_if_fail (provider != NULL);
534 
535 	/* XXX I guess refresh options go in the mail account source,
536 	 *     even if the source is part of a collection.  I did not
537 	 *     think about it too hard, so hopefully this is right. */
538 	extension_name = E_SOURCE_EXTENSION_REFRESH;
539 	extension = e_source_get_extension (source, extension_name);
540 
541 	text = _("Checking for New Mail");
542 	markup = g_markup_printf_escaped ("<b>%s</b>", text);
543 	widget = gtk_label_new (markup);
544 	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
545 	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
546 	gtk_box_pack_start (main_box, widget, FALSE, FALSE, 0);
547 	gtk_widget_show (widget);
548 	g_free (markup);
549 
550 	widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
551 	gtk_widget_set_margin_left (widget, STANDARD_MARGIN);
552 	gtk_box_pack_start (main_box, widget, FALSE, FALSE, 0);
553 	gtk_widget_show (widget);
554 
555 	container = widget;
556 
557 	text = _("Check for _new messages every");
558 	widget = gtk_check_button_new_with_mnemonic (text);
559 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
560 	gtk_widget_show (widget);
561 
562 	e_binding_bind_property (
563 		extension, "enabled",
564 		widget, "active",
565 		G_BINDING_BIDIRECTIONAL |
566 		G_BINDING_SYNC_CREATE);
567 
568 	widget = gtk_spin_button_new_with_range (1.0, 1440.0, 1.0);
569 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
570 	gtk_widget_show (widget);
571 
572 	e_binding_bind_property (
573 		extension, "enabled",
574 		widget, "sensitive",
575 		G_BINDING_SYNC_CREATE);
576 
577 	e_binding_bind_property (
578 		extension, "interval-minutes",
579 		widget, "value",
580 		G_BINDING_BIDIRECTIONAL |
581 		G_BINDING_SYNC_CREATE);
582 
583 	widget = gtk_label_new (_("minutes"));
584 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
585 	gtk_widget_show (widget);
586 
587 	/* Note the "text" member of each CamelProviderConfEntry is
588 	 * already localized, so we can use it directly in widgets. */
589 
590 	entries = provider->extra_conf;
591 
592 	/* Loop until we see CAMEL_PROVIDER_CONF_END. */
593 	for (ii = 0; entries[ii].type != CAMEL_PROVIDER_CONF_END; ii++) {
594 
595 		/* Skip entries with no name. */
596 		if (entries[ii].name == NULL)
597 			continue;
598 
599 		switch (entries[ii].type) {
600 			case CAMEL_PROVIDER_CONF_SECTION_START:
601 				/* Skip the first section start. */
602 				if (first_section) {
603 					first_section = FALSE;
604 					continue;
605 				}
606 				mail_config_provider_page_add_section (
607 					page, main_box, &entries[ii]);
608 				break;
609 
610 			case CAMEL_PROVIDER_CONF_CHECKBOX:
611 				mail_config_provider_page_add_checkbox (
612 					page, main_box, &entries[ii]);
613 				break;
614 
615 			case CAMEL_PROVIDER_CONF_CHECKSPIN:
616 				mail_config_provider_page_add_checkspin (
617 					page, main_box, &entries[ii]);
618 				break;
619 
620 			case CAMEL_PROVIDER_CONF_ENTRY:
621 				mail_config_provider_page_add_entry (
622 					page, main_box, &entries[ii]);
623 				break;
624 
625 			case CAMEL_PROVIDER_CONF_LABEL:
626 				mail_config_provider_page_add_label (
627 					page, main_box, &entries[ii]);
628 				break;
629 
630 			case CAMEL_PROVIDER_CONF_OPTIONS:
631 				mail_config_provider_page_add_options (
632 					page, main_box, &entries[ii]);
633 				break;
634 
635 			case CAMEL_PROVIDER_CONF_PLACEHOLDER:
636 				mail_config_provider_page_add_placeholder (
637 					page, main_box, &entries[ii]);
638 				break;
639 
640 			default:
641 				break;  /* skip it */
642 		}
643 	}
644 }
645 
646 static void
mail_config_provider_page_set_backend(EMailConfigProviderPage * page,EMailConfigServiceBackend * backend)647 mail_config_provider_page_set_backend (EMailConfigProviderPage *page,
648                                        EMailConfigServiceBackend *backend)
649 {
650 	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
651 	g_return_if_fail (page->priv->backend == NULL);
652 
653 	page->priv->backend = g_object_ref (backend);
654 }
655 
656 static void
mail_config_provider_page_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)657 mail_config_provider_page_set_property (GObject *object,
658                                         guint property_id,
659                                         const GValue *value,
660                                         GParamSpec *pspec)
661 {
662 	switch (property_id) {
663 		case PROP_BACKEND:
664 			mail_config_provider_page_set_backend (
665 				E_MAIL_CONFIG_PROVIDER_PAGE (object),
666 				g_value_get_object (value));
667 			return;
668 	}
669 
670 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
671 }
672 
673 static void
mail_config_provider_page_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)674 mail_config_provider_page_get_property (GObject *object,
675                                         guint property_id,
676                                         GValue *value,
677                                         GParamSpec *pspec)
678 {
679 	switch (property_id) {
680 		case PROP_BACKEND:
681 			g_value_set_object (
682 				value,
683 				e_mail_config_provider_page_get_backend (
684 				E_MAIL_CONFIG_PROVIDER_PAGE (object)));
685 			return;
686 	}
687 
688 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
689 }
690 
691 static void
mail_config_provider_page_dispose(GObject * object)692 mail_config_provider_page_dispose (GObject *object)
693 {
694 	EMailConfigProviderPagePrivate *priv;
695 
696 	priv = E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE (object);
697 	g_clear_object (&priv->backend);
698 
699 	/* Chain up parent's dispose() method. */
700 	G_OBJECT_CLASS (e_mail_config_provider_page_parent_class)->
701 		dispose (object);
702 }
703 
704 static void
mail_config_provider_page_constructed(GObject * object)705 mail_config_provider_page_constructed (GObject *object)
706 {
707 	EMailConfigProviderPage *page;
708 	EMailConfigServiceBackend *backend;
709 	CamelProvider *provider;
710 	GtkWidget *main_box;
711 
712 	page = E_MAIL_CONFIG_PROVIDER_PAGE (object);
713 
714 	/* Chain up parent's constructed() method. */
715 	G_OBJECT_CLASS (e_mail_config_provider_page_parent_class)->constructed (object);
716 
717 	main_box = e_mail_config_activity_page_get_internal_box (E_MAIL_CONFIG_ACTIVITY_PAGE (page));
718 
719 	gtk_box_set_spacing (GTK_BOX (main_box), 6);
720 
721 	backend = e_mail_config_provider_page_get_backend (page);
722 	provider = e_mail_config_service_backend_get_provider (backend);
723 
724 	if (provider != NULL && provider->extra_conf != NULL)
725 		mail_config_provider_page_add_widgets (page, GTK_BOX (main_box));
726 	else
727 		page->priv->is_empty = TRUE;
728 
729 	e_mail_config_page_set_content (E_MAIL_CONFIG_PAGE (page), main_box);
730 
731 	e_extensible_load_extensions (E_EXTENSIBLE (page));
732 }
733 
734 static void
e_mail_config_provider_page_class_init(EMailConfigProviderPageClass * class)735 e_mail_config_provider_page_class_init (EMailConfigProviderPageClass *class)
736 {
737 	GObjectClass *object_class;
738 
739 	g_type_class_add_private (class, sizeof (EMailConfigProviderPagePrivate));
740 
741 	object_class = G_OBJECT_CLASS (class);
742 	object_class->set_property = mail_config_provider_page_set_property;
743 	object_class->get_property = mail_config_provider_page_get_property;
744 	object_class->dispose = mail_config_provider_page_dispose;
745 	object_class->constructed = mail_config_provider_page_constructed;
746 
747 	g_object_class_install_property (
748 		object_class,
749 		PROP_BACKEND,
750 		g_param_spec_object (
751 			"backend",
752 			"Backend",
753 			"Service backend to generate options from",
754 			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
755 			G_PARAM_READWRITE |
756 			G_PARAM_CONSTRUCT_ONLY |
757 			G_PARAM_STATIC_STRINGS));
758 }
759 
760 static void
e_mail_config_provider_page_interface_init(EMailConfigPageInterface * iface)761 e_mail_config_provider_page_interface_init (EMailConfigPageInterface *iface)
762 {
763 	iface->title = _("Receiving Options");
764 	iface->sort_order = E_MAIL_CONFIG_PROVIDER_PAGE_SORT_ORDER;
765 }
766 
767 static void
e_mail_config_provider_page_init(EMailConfigProviderPage * page)768 e_mail_config_provider_page_init (EMailConfigProviderPage *page)
769 {
770 	page->priv = E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE (page);
771 }
772 
773 EMailConfigPage *
e_mail_config_provider_page_new(EMailConfigServiceBackend * backend)774 e_mail_config_provider_page_new (EMailConfigServiceBackend *backend)
775 {
776 	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
777 
778 	return g_object_new (
779 		E_TYPE_MAIL_CONFIG_PROVIDER_PAGE,
780 		"backend", backend, NULL);
781 }
782 
783 gboolean
e_mail_config_provider_page_is_empty(EMailConfigProviderPage * page)784 e_mail_config_provider_page_is_empty (EMailConfigProviderPage *page)
785 {
786 	g_return_val_if_fail (E_IS_MAIL_CONFIG_PROVIDER_PAGE (page), TRUE);
787 
788 	return page->priv->is_empty;
789 }
790 
791 EMailConfigServiceBackend *
e_mail_config_provider_page_get_backend(EMailConfigProviderPage * page)792 e_mail_config_provider_page_get_backend (EMailConfigProviderPage *page)
793 {
794 	g_return_val_if_fail (E_IS_MAIL_CONFIG_PROVIDER_PAGE (page), NULL);
795 
796 	return page->priv->backend;
797 }
798 
799 typedef struct _FindPlaceholderData {
800 	const gchar *name;
801 	GtkBox *box;
802 } FindPlaceholderData;
803 
804 static void
mail_config_provider_page_find_placeholder(GtkWidget * widget,gpointer user_data)805 mail_config_provider_page_find_placeholder (GtkWidget *widget,
806 					    gpointer user_data)
807 {
808 	FindPlaceholderData *fpd = user_data;
809 
810 	g_return_if_fail (fpd != NULL);
811 
812 	if (g_strcmp0 (fpd->name, gtk_widget_get_name (widget)) == 0) {
813 		if (fpd->box) {
814 			g_warning ("%s: Found multiple placeholders named '%s'", G_STRFUNC, fpd->name);
815 		} else {
816 			g_return_if_fail (GTK_IS_BOX (widget));
817 
818 			fpd->box = GTK_BOX (widget);
819 		}
820 	}
821 }
822 
823 GtkBox *
e_mail_config_provider_page_get_placeholder(EMailConfigProviderPage * page,const gchar * name)824 e_mail_config_provider_page_get_placeholder (EMailConfigProviderPage *page,
825 					     const gchar *name)
826 {
827 	FindPlaceholderData fpd;
828 	GtkWidget *widget;
829 
830 	g_return_val_if_fail (E_IS_MAIL_CONFIG_PROVIDER_PAGE (page), NULL);
831 	g_return_val_if_fail (name && *name, NULL);
832 
833 	fpd.name = name;
834 	fpd.box = NULL;
835 
836 	widget = gtk_bin_get_child (GTK_BIN (page));
837 	if (GTK_IS_VIEWPORT (widget))
838 		widget = gtk_bin_get_child (GTK_BIN (widget));
839 
840 	if (!GTK_IS_CONTAINER (widget))
841 		return NULL;
842 
843 	gtk_container_foreach (GTK_CONTAINER (widget), mail_config_provider_page_find_placeholder, &fpd);
844 
845 	return fpd.box;
846 }
847