1 /*
2  * e-mail-config-service-notebook.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 "e-mail-config-service-notebook.h"
19 
20 #define E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE(obj) \
21 	(G_TYPE_INSTANCE_GET_PRIVATE \
22 	((obj), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, EMailConfigServiceNotebookPrivate))
23 
24 #define CHILD_BACKEND_KEY_FORMAT \
25 	"__e_mail_config_service_notebook_%p_child_backend__"
26 
27 struct _EMailConfigServiceNotebookPrivate {
28 	EMailConfigServiceBackend *active_backend;
29 	gchar *child_backend_key;
30 };
31 
32 enum {
33 	PROP_0,
34 	PROP_ACTIVE_BACKEND
35 };
36 
37 enum {
38 	PROP_CHILD_0,
39 	PROP_CHILD_BACKEND
40 };
41 
G_DEFINE_TYPE(EMailConfigServiceNotebook,e_mail_config_service_notebook,GTK_TYPE_NOTEBOOK)42 G_DEFINE_TYPE (
43 	EMailConfigServiceNotebook,
44 	e_mail_config_service_notebook,
45 	GTK_TYPE_NOTEBOOK)
46 
47 static void
48 mail_config_service_notebook_set_child_backend (EMailConfigServiceNotebook *notebook,
49                                                 GtkWidget *child,
50                                                 EMailConfigServiceBackend *backend)
51 {
52 	const gchar *key;
53 
54 	key = notebook->priv->child_backend_key;
55 
56 	if (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend))
57 		g_object_set_data_full (
58 			G_OBJECT (child), key,
59 			g_object_ref (backend),
60 			(GDestroyNotify) g_object_unref);
61 }
62 
63 static EMailConfigServiceBackend *
mail_config_service_notebook_get_child_backend(EMailConfigServiceNotebook * notebook,GtkWidget * child)64 mail_config_service_notebook_get_child_backend (EMailConfigServiceNotebook *notebook,
65                                                 GtkWidget *child)
66 {
67 	const gchar *key;
68 
69 	key = notebook->priv->child_backend_key;
70 
71 	return g_object_get_data (G_OBJECT (child), key);
72 }
73 
74 static gboolean
mail_config_service_notebook_page_num_to_backend(GBinding * binding,const GValue * source_value,GValue * target_value,gpointer user_data)75 mail_config_service_notebook_page_num_to_backend (GBinding *binding,
76                                                   const GValue *source_value,
77                                                   GValue *target_value,
78                                                   gpointer user_data)
79 {
80 	EMailConfigServiceBackend *backend;
81 	GtkNotebook *notebook;
82 	GtkWidget *child;
83 	gint page_num;
84 
85 	/* The binding's source and target are the same instance. */
86 	notebook = GTK_NOTEBOOK (g_binding_get_source (binding));
87 
88 	page_num = g_value_get_int (source_value);
89 	child = gtk_notebook_get_nth_page (notebook, page_num);
90 
91 	if (child != NULL)
92 		backend = mail_config_service_notebook_get_child_backend (
93 			E_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), child);
94 	else
95 		backend = NULL;
96 
97 	g_value_set_object (target_value, backend);
98 
99 	return TRUE;
100 }
101 
102 static gboolean
mail_config_service_notebook_backend_to_page_num(GBinding * binding,const GValue * source_value,GValue * target_value,gpointer user_data)103 mail_config_service_notebook_backend_to_page_num (GBinding *binding,
104                                                   const GValue *source_value,
105                                                   GValue *target_value,
106                                                   gpointer user_data)
107 {
108 	EMailConfigServiceBackend *backend;
109 	GtkNotebook *notebook;
110 	gint n_pages, ii;
111 
112 	/* The binding's source and target are the same instance. */
113 	notebook = GTK_NOTEBOOK (g_binding_get_source (binding));
114 
115 	backend = g_value_get_object (source_value);
116 	n_pages = gtk_notebook_get_n_pages (notebook);
117 
118 	for (ii = 0; ii < n_pages; ii++) {
119 		GtkWidget *child;
120 		EMailConfigServiceBackend *candidate;
121 
122 		child = gtk_notebook_get_nth_page (notebook, ii);
123 		candidate = mail_config_service_notebook_get_child_backend (
124 			E_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), child);
125 
126 		if (backend == candidate) {
127 			g_value_set_int (target_value, ii);
128 			return TRUE;
129 		}
130 	}
131 
132 	return FALSE;
133 }
134 
135 static void
mail_config_service_notebook_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)136 mail_config_service_notebook_set_property (GObject *object,
137                                            guint property_id,
138                                            const GValue *value,
139                                            GParamSpec *pspec)
140 {
141 	switch (property_id) {
142 		case PROP_ACTIVE_BACKEND:
143 			e_mail_config_service_notebook_set_active_backend (
144 				E_MAIL_CONFIG_SERVICE_NOTEBOOK (object),
145 				g_value_get_object (value));
146 			return;
147 	}
148 
149 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
150 }
151 
152 static void
mail_config_service_notebook_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)153 mail_config_service_notebook_get_property (GObject *object,
154                                            guint property_id,
155                                            GValue *value,
156                                            GParamSpec *pspec)
157 {
158 	switch (property_id) {
159 		case PROP_ACTIVE_BACKEND:
160 			g_value_set_object (
161 				value,
162 				e_mail_config_service_notebook_get_active_backend (
163 				E_MAIL_CONFIG_SERVICE_NOTEBOOK (object)));
164 			return;
165 	}
166 
167 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
168 }
169 
170 static void
mail_config_service_notebook_dispose(GObject * object)171 mail_config_service_notebook_dispose (GObject *object)
172 {
173 	EMailConfigServiceNotebookPrivate *priv;
174 
175 	priv = E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE (object);
176 	g_clear_object (&priv->active_backend);
177 
178 	/* Chain up to parent's dispose() method. */
179 	G_OBJECT_CLASS (e_mail_config_service_notebook_parent_class)->
180 		dispose (object);
181 }
182 
183 static void
mail_config_service_notebook_finalize(GObject * object)184 mail_config_service_notebook_finalize (GObject *object)
185 {
186 	EMailConfigServiceNotebookPrivate *priv;
187 
188 	priv = E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE (object);
189 
190 	g_free (priv->child_backend_key);
191 
192 	/* Chain up to parent's finalize() method. */
193 	G_OBJECT_CLASS (e_mail_config_service_notebook_parent_class)->
194 		finalize (object);
195 }
196 
197 static void
mail_config_service_notebook_constructed(GObject * object)198 mail_config_service_notebook_constructed (GObject *object)
199 {
200 	/* Chain up to parent's constructed() method. */
201 	G_OBJECT_CLASS (e_mail_config_service_notebook_parent_class)->constructed (object);
202 
203 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (object), FALSE);
204 	gtk_notebook_set_show_border (GTK_NOTEBOOK (object), FALSE);
205 
206 	/* Current page is still -1 so skip G_BINDING_SYNC_CREATE. */
207 	e_binding_bind_property_full (
208 		object, "page",
209 		object, "active-backend",
210 		G_BINDING_BIDIRECTIONAL,
211 		mail_config_service_notebook_page_num_to_backend,
212 		mail_config_service_notebook_backend_to_page_num,
213 		NULL, (GDestroyNotify) NULL);
214 }
215 
216 static void
mail_config_service_notebook_set_child_property(GtkContainer * container,GtkWidget * child,guint property_id,const GValue * value,GParamSpec * pspec)217 mail_config_service_notebook_set_child_property (GtkContainer *container,
218                                                  GtkWidget *child,
219                                                  guint property_id,
220                                                  const GValue *value,
221                                                  GParamSpec *pspec)
222 {
223 	switch (property_id) {
224 		case PROP_CHILD_BACKEND:
225 			mail_config_service_notebook_set_child_backend (
226 				E_MAIL_CONFIG_SERVICE_NOTEBOOK (container),
227 				child, g_value_get_object (value));
228 			return;
229 	}
230 
231 	GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (
232 		container, property_id, pspec);
233 }
234 
235 static void
mail_config_service_notebook_get_child_property(GtkContainer * container,GtkWidget * child,guint property_id,GValue * value,GParamSpec * pspec)236 mail_config_service_notebook_get_child_property (GtkContainer *container,
237                                                  GtkWidget *child,
238                                                  guint property_id,
239                                                  GValue *value,
240                                                  GParamSpec *pspec)
241 {
242 	switch (property_id) {
243 		case PROP_CHILD_BACKEND:
244 			g_value_set_object (
245 				value,
246 				mail_config_service_notebook_get_child_backend (
247 				E_MAIL_CONFIG_SERVICE_NOTEBOOK (container), child));
248 			return;
249 	}
250 
251 	GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (
252 		container, property_id, pspec);
253 }
254 
255 static void
e_mail_config_service_notebook_class_init(EMailConfigServiceNotebookClass * class)256 e_mail_config_service_notebook_class_init (EMailConfigServiceNotebookClass *class)
257 {
258 	GObjectClass *object_class;
259 	GtkContainerClass *container_class;
260 
261 	g_type_class_add_private (
262 		class, sizeof (EMailConfigServiceNotebookPrivate));
263 
264 	object_class = G_OBJECT_CLASS (class);
265 	object_class->set_property = mail_config_service_notebook_set_property;
266 	object_class->get_property = mail_config_service_notebook_get_property;
267 	object_class->dispose = mail_config_service_notebook_dispose;
268 	object_class->finalize = mail_config_service_notebook_finalize;
269 	object_class->constructed = mail_config_service_notebook_constructed;
270 
271 	container_class = GTK_CONTAINER_CLASS (class);
272 	container_class->set_child_property = mail_config_service_notebook_set_child_property;
273 	container_class->get_child_property = mail_config_service_notebook_get_child_property;
274 
275 	g_object_class_install_property (
276 		object_class,
277 		PROP_ACTIVE_BACKEND,
278 		g_param_spec_object (
279 			"active-backend",
280 			"Active Backend",
281 			"The service backend for the current page",
282 			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
283 			G_PARAM_READWRITE |
284 			G_PARAM_STATIC_STRINGS));
285 
286 	/* Child property for notebook pages. */
287 	gtk_container_class_install_child_property (
288 		container_class,
289 		PROP_CHILD_BACKEND,
290 		g_param_spec_object (
291 			"backend",
292 			"Backend",
293 			"The service backend for this page",
294 			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
295 			G_PARAM_READWRITE |
296 			G_PARAM_STATIC_STRINGS));
297 }
298 
299 static void
e_mail_config_service_notebook_init(EMailConfigServiceNotebook * notebook)300 e_mail_config_service_notebook_init (EMailConfigServiceNotebook *notebook)
301 {
302 	gchar *key;
303 
304 	notebook->priv = E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE (notebook);
305 
306 	key = g_strdup_printf (CHILD_BACKEND_KEY_FORMAT, notebook);
307 	notebook->priv->child_backend_key = key;
308 }
309 
310 GtkWidget *
e_mail_config_service_notebook_new(void)311 e_mail_config_service_notebook_new (void)
312 {
313 	return g_object_new (E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, NULL);
314 }
315 
316 gint
e_mail_config_service_notebook_add_page(EMailConfigServiceNotebook * notebook,EMailConfigServiceBackend * backend,GtkWidget * child)317 e_mail_config_service_notebook_add_page (EMailConfigServiceNotebook *notebook,
318                                          EMailConfigServiceBackend *backend,
319                                          GtkWidget *child)
320 {
321 	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), -1);
322 	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), -1);
323 	g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
324 
325 	gtk_widget_show (child);
326 
327 	mail_config_service_notebook_set_child_backend (
328 		notebook, child, backend);
329 
330 	return gtk_notebook_append_page (GTK_NOTEBOOK (notebook), child, NULL);
331 }
332 
333 EMailConfigServiceBackend *
e_mail_config_service_notebook_get_active_backend(EMailConfigServiceNotebook * notebook)334 e_mail_config_service_notebook_get_active_backend (EMailConfigServiceNotebook *notebook)
335 {
336 	g_return_val_if_fail (
337 		E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), NULL);
338 
339 	return notebook->priv->active_backend;
340 }
341 
342 void
e_mail_config_service_notebook_set_active_backend(EMailConfigServiceNotebook * notebook,EMailConfigServiceBackend * backend)343 e_mail_config_service_notebook_set_active_backend (EMailConfigServiceNotebook *notebook,
344                                                    EMailConfigServiceBackend *backend)
345 {
346 	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook));
347 
348 	if (notebook->priv->active_backend == backend)
349 		return;
350 
351 	if (backend != NULL) {
352 		g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
353 		g_object_ref (backend);
354 	}
355 
356 	if (notebook->priv->active_backend != NULL)
357 		g_object_unref (notebook->priv->active_backend);
358 
359 	notebook->priv->active_backend = backend;
360 
361 	g_object_notify (G_OBJECT (notebook), "active-backend");
362 }
363 
364