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