1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* e-source-selector-dialog.c
3  *
4  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * published by the Free Software Foundation; either the
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Rodrigo Moya <rodrigo@novell.com>
19  */
20 
21 #include "evolution-config.h"
22 
23 #include <glib/gi18n-lib.h>
24 
25 #include "e-tree-view-frame.h"
26 #include "e-source-selector.h"
27 #include "e-source-selector-dialog.h"
28 
29 #define E_SOURCE_SELECTOR_DIALOG_GET_PRIVATE(obj) \
30 	(G_TYPE_INSTANCE_GET_PRIVATE \
31 	((obj), E_TYPE_SOURCE_SELECTOR_DIALOG, ESourceSelectorDialogPrivate))
32 
33 struct _ESourceSelectorDialogPrivate {
34 	GtkWidget *selector;
35 	ESourceRegistry *registry;
36 	ESource *selected_source;
37 	ESource *except_source;
38 	gchar *extension_name;
39 };
40 
41 enum {
42 	PROP_0,
43 	PROP_EXTENSION_NAME,
44 	PROP_REGISTRY,
45 	PROP_SELECTOR,
46 	PROP_EXCEPT_SOURCE
47 };
48 
G_DEFINE_TYPE(ESourceSelectorDialog,e_source_selector_dialog,GTK_TYPE_DIALOG)49 G_DEFINE_TYPE (
50 	ESourceSelectorDialog,
51 	e_source_selector_dialog,
52 	GTK_TYPE_DIALOG)
53 
54 static void
55 source_selector_dialog_row_activated_cb (GtkTreeView *tree_view,
56                                          GtkTreePath *path,
57                                          GtkTreeViewColumn *column,
58                                          GtkWidget *dialog)
59 {
60 	gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
61 }
62 
63 static void
primary_selection_changed_cb(ESourceSelector * selector,ESourceSelectorDialog * dialog)64 primary_selection_changed_cb (ESourceSelector *selector,
65                               ESourceSelectorDialog *dialog)
66 {
67 	ESourceSelectorDialogPrivate *priv = dialog->priv;
68 
69 	if (priv->selected_source != NULL)
70 		g_object_unref (priv->selected_source);
71 	priv->selected_source =
72 		e_source_selector_ref_primary_selection (selector);
73 
74 	if (priv->selected_source != NULL) {
75 		ESource *except_source;
76 
77 		except_source = e_source_selector_dialog_get_except_source (dialog);
78 
79 		if (except_source != NULL)
80 			if (e_source_equal (except_source, priv->selected_source)) {
81 				g_object_unref (priv->selected_source);
82 				priv->selected_source = NULL;
83 			}
84 	}
85 
86 	gtk_dialog_set_response_sensitive (
87 		GTK_DIALOG (dialog), GTK_RESPONSE_OK,
88 		(priv->selected_source != NULL));
89 }
90 
91 static void
source_selector_dialog_set_extension_name(ESourceSelectorDialog * dialog,const gchar * extension_name)92 source_selector_dialog_set_extension_name (ESourceSelectorDialog *dialog,
93                                            const gchar *extension_name)
94 {
95 	g_return_if_fail (extension_name != NULL);
96 	g_return_if_fail (dialog->priv->extension_name == NULL);
97 
98 	dialog->priv->extension_name = g_strdup (extension_name);
99 }
100 
101 static void
source_selector_dialog_set_registry(ESourceSelectorDialog * dialog,ESourceRegistry * registry)102 source_selector_dialog_set_registry (ESourceSelectorDialog *dialog,
103                                      ESourceRegistry *registry)
104 {
105 	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
106 	g_return_if_fail (dialog->priv->registry == NULL);
107 
108 	dialog->priv->registry = g_object_ref (registry);
109 }
110 
111 static void
source_selector_dialog_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)112 source_selector_dialog_set_property (GObject *object,
113                                      guint property_id,
114                                      const GValue *value,
115                                      GParamSpec *pspec)
116 {
117 	switch (property_id) {
118 		case PROP_EXTENSION_NAME:
119 			source_selector_dialog_set_extension_name (
120 				E_SOURCE_SELECTOR_DIALOG (object),
121 				g_value_get_string (value));
122 			return;
123 
124 		case PROP_REGISTRY:
125 			source_selector_dialog_set_registry (
126 				E_SOURCE_SELECTOR_DIALOG (object),
127 				g_value_get_object (value));
128 			return;
129 
130 		case PROP_EXCEPT_SOURCE:
131 			e_source_selector_dialog_set_except_source (
132 				E_SOURCE_SELECTOR_DIALOG (object),
133 				g_value_get_object (value));
134 			return;
135 	}
136 
137 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
138 }
139 
140 static void
source_selector_dialog_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)141 source_selector_dialog_get_property (GObject *object,
142                                      guint property_id,
143                                      GValue *value,
144                                      GParamSpec *pspec)
145 {
146 	switch (property_id) {
147 		case PROP_EXTENSION_NAME:
148 			g_value_set_string (
149 				value,
150 				e_source_selector_dialog_get_extension_name (
151 				E_SOURCE_SELECTOR_DIALOG (object)));
152 			return;
153 
154 		case PROP_REGISTRY:
155 			g_value_set_object (
156 				value,
157 				e_source_selector_dialog_get_registry (
158 				E_SOURCE_SELECTOR_DIALOG (object)));
159 			return;
160 
161 		case PROP_SELECTOR:
162 			g_value_set_object (
163 				value,
164 				e_source_selector_dialog_get_selector (
165 				E_SOURCE_SELECTOR_DIALOG (object)));
166 			return;
167 
168 		case PROP_EXCEPT_SOURCE:
169 			g_value_set_object (
170 				value,
171 				e_source_selector_dialog_get_except_source (
172 				E_SOURCE_SELECTOR_DIALOG (object)));
173 			return;
174 	}
175 
176 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
177 }
178 
179 static void
source_selector_dialog_dispose(GObject * object)180 source_selector_dialog_dispose (GObject *object)
181 {
182 	ESourceSelectorDialogPrivate *priv;
183 
184 	priv = E_SOURCE_SELECTOR_DIALOG_GET_PRIVATE (object);
185 
186 	g_clear_object (&priv->registry);
187 	g_clear_object (&priv->selected_source);
188 	g_clear_object (&priv->except_source);
189 
190 	/* Chain up to parent's dispose() method. */
191 	G_OBJECT_CLASS (e_source_selector_dialog_parent_class)->dispose (object);
192 }
193 
194 static void
source_selector_dialog_finalize(GObject * object)195 source_selector_dialog_finalize (GObject *object)
196 {
197 	ESourceSelectorDialogPrivate *priv;
198 
199 	priv = E_SOURCE_SELECTOR_DIALOG_GET_PRIVATE (object);
200 
201 	g_free (priv->extension_name);
202 
203 	/* Chain up to parent's finalize() method. */
204 	G_OBJECT_CLASS (e_source_selector_dialog_parent_class)->finalize (object);
205 }
206 
207 static void
source_selector_dialog_constructed(GObject * object)208 source_selector_dialog_constructed (GObject *object)
209 {
210 	ESourceSelectorDialog *dialog;
211 	ESource *primary_selection;
212 	GtkWidget *container;
213 	GtkWidget *widget;
214 
215 	/* Chain up to parent's method. */
216 	G_OBJECT_CLASS (e_source_selector_dialog_parent_class)->constructed (object);
217 
218 	dialog = E_SOURCE_SELECTOR_DIALOG (object);
219 
220 	container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
221 
222 	widget = e_tree_view_frame_new ();
223 	e_tree_view_frame_set_toolbar_visible (E_TREE_VIEW_FRAME (widget), FALSE);
224 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
225 	gtk_widget_show (widget);
226 
227 	container = widget;
228 
229 	widget = e_source_selector_new (
230 		dialog->priv->registry,
231 		dialog->priv->extension_name);
232 	e_source_selector_set_show_toggles (E_SOURCE_SELECTOR (widget), FALSE);
233 	e_tree_view_frame_set_tree_view (
234 		E_TREE_VIEW_FRAME (container),
235 		GTK_TREE_VIEW (widget));
236 	dialog->priv->selector = widget;
237 
238 	g_signal_connect (
239 		widget, "row_activated",
240 		G_CALLBACK (source_selector_dialog_row_activated_cb), dialog);
241 	g_signal_connect (
242 		widget, "primary_selection_changed",
243 		G_CALLBACK (primary_selection_changed_cb), dialog);
244 
245 	primary_selection = e_source_selector_ref_primary_selection (E_SOURCE_SELECTOR (widget));
246 	if (primary_selection)
247 		primary_selection_changed_cb (E_SOURCE_SELECTOR (widget), dialog);
248 	g_clear_object (&primary_selection);
249 }
250 
251 static void
e_source_selector_dialog_class_init(ESourceSelectorDialogClass * class)252 e_source_selector_dialog_class_init (ESourceSelectorDialogClass *class)
253 {
254 	GObjectClass *object_class;
255 
256 	g_type_class_add_private (class, sizeof (ESourceSelectorDialogPrivate));
257 
258 	object_class = G_OBJECT_CLASS (class);
259 	object_class->set_property = source_selector_dialog_set_property;
260 	object_class->get_property = source_selector_dialog_get_property;
261 	object_class->dispose = source_selector_dialog_dispose;
262 	object_class->finalize = source_selector_dialog_finalize;
263 	object_class->constructed = source_selector_dialog_constructed;
264 
265 	g_object_class_install_property (
266 		object_class,
267 		PROP_EXTENSION_NAME,
268 		g_param_spec_string (
269 			"extension-name",
270 			NULL,
271 			NULL,
272 			NULL,
273 			G_PARAM_WRITABLE |
274 			G_PARAM_CONSTRUCT_ONLY));
275 
276 	g_object_class_install_property (
277 		object_class,
278 		PROP_REGISTRY,
279 		g_param_spec_object (
280 			"registry",
281 			NULL,
282 			NULL,
283 			E_TYPE_SOURCE_REGISTRY,
284 			G_PARAM_WRITABLE |
285 			G_PARAM_CONSTRUCT_ONLY));
286 
287 	g_object_class_install_property (
288 		object_class,
289 		PROP_SELECTOR,
290 		g_param_spec_object (
291 			"selector",
292 			NULL,
293 			NULL,
294 			E_TYPE_SOURCE_SELECTOR,
295 			G_PARAM_READABLE));
296 
297 	g_object_class_install_property (
298 		object_class,
299 		PROP_EXCEPT_SOURCE,
300 		g_param_spec_object (
301 			"except-source",
302 			NULL,
303 			NULL,
304 			E_TYPE_SOURCE,
305 			G_PARAM_WRITABLE));
306 }
307 
308 static void
e_source_selector_dialog_init(ESourceSelectorDialog * dialog)309 e_source_selector_dialog_init (ESourceSelectorDialog *dialog)
310 {
311 	GtkWidget *action_area;
312 
313 	dialog->priv = E_SOURCE_SELECTOR_DIALOG_GET_PRIVATE (dialog);
314 
315 	action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
316 
317 	gtk_window_set_title (GTK_WINDOW (dialog), _("Select destination"));
318 	gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 500);
319 
320 	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
321 	gtk_widget_set_margin_top (action_area, 5);
322 
323 	gtk_dialog_add_buttons (
324 		GTK_DIALOG (dialog),
325 		_("_Cancel"), GTK_RESPONSE_CANCEL,
326 		_("_OK"), GTK_RESPONSE_OK, NULL);
327 	gtk_dialog_set_default_response (
328 		GTK_DIALOG (dialog), GTK_RESPONSE_OK);
329 	gtk_dialog_set_response_sensitive (
330 		GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
331 }
332 
333 /**
334  * e_source_selector_dialog_new:
335  * @parent: a parent window
336  * @registry: an #ESourceRegistry
337  * @extension_name: the name of an #ESource extension
338  *
339  * Displays a list of sources from @registry having an extension named
340  * @extension_name in a dialog window.  The sources are grouped by backend
341  * or groupware account, which are described by the parent source.
342  *
343  * Returns: a new #ESourceSelectorDialog
344  **/
345 GtkWidget *
e_source_selector_dialog_new(GtkWindow * parent,ESourceRegistry * registry,const gchar * extension_name)346 e_source_selector_dialog_new (GtkWindow *parent,
347                               ESourceRegistry *registry,
348                               const gchar *extension_name)
349 {
350 	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
351 	g_return_val_if_fail (extension_name != NULL, NULL);
352 
353 	return g_object_new (
354 		E_TYPE_SOURCE_SELECTOR_DIALOG,
355 		"transient-for", parent,
356 		"registry", registry,
357 		"extension-name", extension_name,
358 		NULL);
359 }
360 
361 /**
362  * e_source_selector_dialog_get_registry:
363  * @dialog: an #ESourceSelectorDialog
364  *
365  * Returns the #ESourceRegistry passed to e_source_selector_dialog_new().
366  *
367  * Returns: the #ESourceRegistry for @dialog
368  *
369  * Since: 3.6
370  **/
371 ESourceRegistry *
e_source_selector_dialog_get_registry(ESourceSelectorDialog * dialog)372 e_source_selector_dialog_get_registry (ESourceSelectorDialog *dialog)
373 {
374 	g_return_val_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog), NULL);
375 
376 	return dialog->priv->registry;
377 }
378 
379 /**
380  * e_source_selector_dialog_get_extension_name:
381  * @dialog: an #ESourceSelectorDialog
382  *
383  * Returns the extension name passed to e_source_selector_dialog_new().
384  *
385  * Returns: the extension name for @dialog
386  *
387  * Since: 3.6
388  **/
389 const gchar *
e_source_selector_dialog_get_extension_name(ESourceSelectorDialog * dialog)390 e_source_selector_dialog_get_extension_name (ESourceSelectorDialog *dialog)
391 {
392 	g_return_val_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog), NULL);
393 
394 	return dialog->priv->extension_name;
395 }
396 
397 /**
398  * e_source_selector_dialog_get_selector:
399  * @dialog: an #ESourceSelectorDialog
400  *
401  * Returns the #ESourceSelector widget embedded in @dialog.
402  *
403  * Returns: the #ESourceSelector widget
404  *
405  * Since: 3.6
406  **/
407 ESourceSelector *
e_source_selector_dialog_get_selector(ESourceSelectorDialog * dialog)408 e_source_selector_dialog_get_selector (ESourceSelectorDialog *dialog)
409 {
410 	g_return_val_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog), NULL);
411 
412 	return E_SOURCE_SELECTOR (dialog->priv->selector);
413 }
414 
415 /**
416  * e_source_selector_dialog_peek_primary_selection:
417  * @dialog: an #ESourceSelectorDialog
418  *
419  * Peek the currently selected source in the given @dialog.
420  *
421  * Returns: the selected #ESource
422  */
423 ESource *
e_source_selector_dialog_peek_primary_selection(ESourceSelectorDialog * dialog)424 e_source_selector_dialog_peek_primary_selection (ESourceSelectorDialog *dialog)
425 {
426 	g_return_val_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog), NULL);
427 
428 	return dialog->priv->selected_source;
429 }
430 
431 /**
432  * e_source_selector_dialog_get_except_source:
433  * @dialog: an #ESourceSelectorDialog
434  *
435  * Get the currently #ESource, which cannot be selected in the given @dialog.
436  * Use e_source_selector_dialog_set_except_source() to set such.
437  *
438  * Returns: the #ESource, which cannot be selected
439  *
440  * Since: 3.18
441  **/
442 ESource *
e_source_selector_dialog_get_except_source(ESourceSelectorDialog * dialog)443 e_source_selector_dialog_get_except_source (ESourceSelectorDialog *dialog)
444 {
445 	g_return_val_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog), NULL);
446 
447 	return dialog->priv->except_source;
448 }
449 
450 /**
451  * e_source_selector_dialog_set_except_source:
452  * @dialog: an #ESourceSelectorDialog
453  * @except_source: (allow-none): an #ESource, which cannot be selected, or %NULL
454  *
455  * Set the @except_source, the one which cannot be selected in the given @dialog.
456  * Use %NULL to allow to select all sources.
457  *
458  * Since: 3.18
459  **/
460 void
e_source_selector_dialog_set_except_source(ESourceSelectorDialog * dialog,ESource * except_source)461 e_source_selector_dialog_set_except_source (ESourceSelectorDialog *dialog,
462 					    ESource *except_source)
463 {
464 	g_return_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog));
465 	if (except_source)
466 		g_return_if_fail (E_IS_SOURCE (except_source));
467 
468 	if ((dialog->priv->except_source && except_source && e_source_equal (dialog->priv->except_source, except_source)) ||
469 	    dialog->priv->except_source == except_source)
470 		return;
471 
472 	g_clear_object (&dialog->priv->except_source);
473 	dialog->priv->except_source = except_source ? g_object_ref (except_source) : NULL;
474 
475 	primary_selection_changed_cb (E_SOURCE_SELECTOR (dialog->priv->selector), dialog);
476 
477 	g_object_notify (G_OBJECT (dialog), "except-source");
478 }
479