1 /* gdict-source-chooser.h - display widget for dictionary sources
2 *
3 * Copyright (C) 2007 Emmanuele Bassi <ebassi@gnome.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20 * SECTION:gdict-source-chooser
21 * @short_description: Display the list of available sources
22 *
23 * #GdictSourceChooser is a widget that shows the list of available
24 * dictionary sources using a #GdictSourceLoader instance as a model.
25 * It can be used to allow choosing the current dictionary source.
26 *
27 * #GdictSourceChooser is available since Gdict 0.12.
28 */
29
30 #include "config.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <glib/gi18n-lib.h>
36
37 #include <gdk/gdk.h>
38
39 #include <gtk/gtk.h>
40
41 #include "gdict-source-chooser.h"
42 #include "gdict-utils.h"
43 #include "gdict-private.h"
44 #include "gdict-enum-types.h"
45 #include "gdict-marshal.h"
46
47 struct _GdictSourceChooserPrivate
48 {
49 GtkListStore *store;
50
51 GtkWidget *treeview;
52 GtkWidget *refresh_button;
53 GtkWidget *buttons_box;
54
55 GdictSourceLoader *loader;
56 gint n_sources;
57
58 gchar *current_source;
59 };
60
61 enum
62 {
63 SOURCE_TRANSPORT,
64 SOURCE_NAME,
65 SOURCE_DESCRIPTION,
66 SOURCE_CURRENT,
67
68 SOURCE_N_COLUMNS
69 };
70
71 enum
72 {
73 PROP_0,
74
75 PROP_LOADER,
76 PROP_COUNT
77 };
78
79 enum
80 {
81 SOURCE_ACTIVATED,
82 SELECTION_CHANGED,
83
84 LAST_SIGNAL
85 };
86
87 static guint source_chooser_signals[LAST_SIGNAL] = { 0, };
88
G_DEFINE_TYPE_WITH_PRIVATE(GdictSourceChooser,gdict_source_chooser,GTK_TYPE_BOX)89 G_DEFINE_TYPE_WITH_PRIVATE (GdictSourceChooser, gdict_source_chooser, GTK_TYPE_BOX)
90
91 static void
92 gdict_source_chooser_finalize (GObject *gobject)
93 {
94 GdictSourceChooser *chooser = GDICT_SOURCE_CHOOSER (gobject);
95 GdictSourceChooserPrivate *priv = chooser->priv;
96
97 g_free (priv->current_source);
98
99 G_OBJECT_CLASS (gdict_source_chooser_parent_class)->finalize (gobject);
100 }
101
102 static void
gdict_source_chooser_dispose(GObject * gobject)103 gdict_source_chooser_dispose (GObject *gobject)
104 {
105 GdictSourceChooser *chooser = GDICT_SOURCE_CHOOSER (gobject);
106 GdictSourceChooserPrivate *priv = chooser->priv;
107
108 if (priv->store)
109 {
110 g_object_unref (priv->store);
111 priv->store = NULL;
112 }
113
114 if (priv->loader)
115 {
116 g_object_unref (priv->loader);
117 priv->loader = NULL;
118 }
119
120 G_OBJECT_CLASS (gdict_source_chooser_parent_class)->dispose (gobject);
121 }
122
123 static void
gdict_source_chooser_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * pspec)124 gdict_source_chooser_set_property (GObject *gobject,
125 guint prop_id,
126 const GValue *value,
127 GParamSpec *pspec)
128 {
129 switch (prop_id)
130 {
131 case PROP_LOADER:
132 gdict_source_chooser_set_loader (GDICT_SOURCE_CHOOSER (gobject),
133 g_value_get_object (value));
134 break;
135 default:
136 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
137 break;
138 }
139 }
140
141 static void
gdict_source_chooser_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * pspec)142 gdict_source_chooser_get_property (GObject *gobject,
143 guint prop_id,
144 GValue *value,
145 GParamSpec *pspec)
146 {
147 GdictSourceChooserPrivate *priv;
148
149 priv = GDICT_SOURCE_CHOOSER (gobject)->priv;
150
151 switch (prop_id)
152 {
153 case PROP_LOADER:
154 g_value_set_object (value, priv->loader);
155 break;
156 case PROP_COUNT:
157 g_value_set_int (value, priv->n_sources);
158 break;
159 default:
160 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
161 break;
162 }
163 }
164
165 static void
row_activated_cb(GtkTreeView * treeview,GtkTreePath * path,GtkTreeViewColumn * column,gpointer data)166 row_activated_cb (GtkTreeView *treeview,
167 GtkTreePath *path,
168 GtkTreeViewColumn *column,
169 gpointer data)
170 {
171 GdictSourceChooser *chooser = GDICT_SOURCE_CHOOSER (data);
172 GdictSourceChooserPrivate *priv = chooser->priv;
173 GtkTreeIter iter;
174 gchar *name;
175 GdictSource *source;
176
177 if (!priv->loader)
178 return;
179
180 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->store), &iter, path))
181 return;
182
183 gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
184 SOURCE_NAME, &name,
185 -1);
186 if (!name)
187 return;
188
189 source = gdict_source_loader_get_source (priv->loader, name);
190 if (!source)
191 {
192 g_free (name);
193 return;
194 }
195
196 g_signal_emit (chooser, source_chooser_signals[SOURCE_ACTIVATED], 0,
197 name, source);
198
199 g_free (name);
200 g_object_unref (source);
201 }
202
203 static void
refresh_button_clicked_cb(GtkButton * button,gpointer data)204 refresh_button_clicked_cb (GtkButton *button,
205 gpointer data)
206 {
207 gdict_source_chooser_refresh (GDICT_SOURCE_CHOOSER (data));
208 }
209
210 static void
selection_changed_cb(GtkTreeSelection * selection,gpointer data)211 selection_changed_cb (GtkTreeSelection *selection,
212 gpointer data)
213 {
214 g_signal_emit (data, source_chooser_signals[SELECTION_CHANGED], 0);
215 }
216
217 static GObject *
gdict_source_chooser_constructor(GType gtype,guint n_params,GObjectConstructParam * params)218 gdict_source_chooser_constructor (GType gtype,
219 guint n_params,
220 GObjectConstructParam *params)
221 {
222 GdictSourceChooser *chooser;
223 GdictSourceChooserPrivate *priv;
224 GObjectClass *parent_class;
225 GObject *retval;
226 GtkWidget *sw;
227 GtkCellRenderer *renderer;
228 GtkTreeViewColumn *column;
229 GtkWidget *hbox;
230
231 parent_class = G_OBJECT_CLASS (gdict_source_chooser_parent_class);
232 retval = parent_class->constructor (gtype, n_params, params);
233
234 chooser = GDICT_SOURCE_CHOOSER (retval);
235 priv = chooser->priv;
236
237 sw = gtk_scrolled_window_new (NULL, NULL);
238 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
239 GTK_POLICY_AUTOMATIC,
240 GTK_POLICY_AUTOMATIC);
241 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
242 GTK_SHADOW_IN);
243 gtk_box_pack_start (GTK_BOX (chooser), sw, TRUE, TRUE, 0);
244 gtk_widget_show (sw);
245
246 renderer = gtk_cell_renderer_text_new ();
247 column = gtk_tree_view_column_new_with_attributes ("sources",
248 renderer,
249 "text", SOURCE_DESCRIPTION,
250 "weight", SOURCE_CURRENT,
251 NULL);
252 priv->treeview = gtk_tree_view_new ();
253 gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
254 GTK_TREE_MODEL (priv->store));
255 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->treeview), FALSE);
256 gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column);
257 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)),
258 "changed", G_CALLBACK (selection_changed_cb),
259 chooser);
260 g_signal_connect (priv->treeview,
261 "row-activated", G_CALLBACK (row_activated_cb),
262 chooser);
263 gtk_container_add (GTK_CONTAINER (sw), priv->treeview);
264 gtk_widget_show (priv->treeview);
265
266 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
267 priv->buttons_box = hbox;
268
269 priv->refresh_button = gtk_button_new ();
270 gtk_button_set_image (GTK_BUTTON (priv->refresh_button),
271 gtk_image_new_from_icon_name ("view-refresh-symbolic", GTK_ICON_SIZE_BUTTON));
272 g_signal_connect (priv->refresh_button,
273 "clicked", G_CALLBACK (refresh_button_clicked_cb),
274 chooser);
275 gtk_box_pack_start (GTK_BOX (hbox), priv->refresh_button, FALSE, FALSE, 0);
276 gtk_widget_show (priv->refresh_button);
277 gtk_widget_set_tooltip_text (priv->refresh_button,
278 _("Reload the list of available sources"));
279
280 gtk_box_pack_end (GTK_BOX (chooser), hbox, FALSE, FALSE, 0);
281 gtk_widget_show (hbox);
282
283 return retval;
284 }
285
286 static void
gdict_source_chooser_class_init(GdictSourceChooserClass * klass)287 gdict_source_chooser_class_init (GdictSourceChooserClass *klass)
288 {
289 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
290
291 gobject_class->finalize = gdict_source_chooser_finalize;
292 gobject_class->dispose = gdict_source_chooser_dispose;
293 gobject_class->set_property = gdict_source_chooser_set_property;
294 gobject_class->get_property = gdict_source_chooser_get_property;
295 gobject_class->constructor = gdict_source_chooser_constructor;
296
297 /**
298 * GdictSourceChooser:loader:
299 *
300 * The #GdictSourceLoader used to retrieve the list of available
301 * dictionary sources.
302 *
303 * Since: 0.12
304 */
305 g_object_class_install_property (gobject_class,
306 PROP_LOADER,
307 g_param_spec_object ("loader",
308 "Loader",
309 "The GdictSourceLoader used to get the list of sources",
310 GDICT_TYPE_SOURCE_LOADER,
311 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
312 /**
313 * GdictSourceChooser:count:
314 *
315 * The number of available dictionary sources, or -1 if no
316 * #GdictSourceLoader is set.
317 *
318 * Since: 0.12
319 */
320 g_object_class_install_property (gobject_class,
321 PROP_COUNT,
322 g_param_spec_int ("count",
323 "Count",
324 "The number of available dictionary sources",
325 -1, G_MAXINT, -1,
326 G_PARAM_READABLE));
327
328 /**
329 * GdictSourceChooser::source-activated:
330 * @chooser: the #GdictSourceChooser that received the signal
331 * @source_name: the name of the activated source
332 * @source: the activated #GdictSource
333 *
334 * The ::source-activated signal is emitted each time the user
335 * activates a row in the source chooser widget, either by double
336 * clicking on it or by a keyboard event.
337 *
338 * Since: 0.12
339 */
340 source_chooser_signals[SOURCE_ACTIVATED] =
341 g_signal_new ("source-activated",
342 G_OBJECT_CLASS_TYPE (gobject_class),
343 G_SIGNAL_RUN_LAST,
344 G_STRUCT_OFFSET (GdictSourceChooserClass, source_activated),
345 NULL, NULL,
346 gdict_marshal_VOID__STRING_OBJECT,
347 G_TYPE_NONE, 2,
348 G_TYPE_STRING,
349 GDICT_TYPE_SOURCE);
350 /**
351 * GdictSourceChooser::selection-changed:
352 * @chooser: the #GdictSourceChooser that received the signal
353 *
354 * The ::selection-changed signal is emitted each time the
355 * selection inside the source chooser widget has been changed.
356 *
357 * Since: 0.12
358 */
359 source_chooser_signals[SELECTION_CHANGED] =
360 g_signal_new ("selection-changed",
361 G_OBJECT_CLASS_TYPE (gobject_class),
362 G_SIGNAL_RUN_LAST,
363 G_STRUCT_OFFSET (GdictSourceChooserClass, selection_changed),
364 NULL, NULL,
365 gdict_marshal_VOID__VOID,
366 G_TYPE_NONE, 0);
367 }
368
369 static void
gdict_source_chooser_init(GdictSourceChooser * chooser)370 gdict_source_chooser_init (GdictSourceChooser *chooser)
371 {
372 GdictSourceChooserPrivate *priv;
373
374 chooser->priv = priv = gdict_source_chooser_get_instance_private (chooser);
375
376 gtk_orientable_set_orientation (GTK_ORIENTABLE (chooser), GTK_ORIENTATION_VERTICAL);
377
378 priv->store = gtk_list_store_new (SOURCE_N_COLUMNS,
379 G_TYPE_INT, /* TRANSPORT */
380 G_TYPE_STRING, /* NAME */
381 G_TYPE_STRING, /* DESCRIPTION */
382 G_TYPE_INT /* CURRENT */);
383
384 priv->loader = NULL;
385 priv->n_sources = -1;
386 }
387
388 /**
389 * gdict_source_chooser_new:
390 *
391 * Creates a new #GdictSourceChooser widget. This widget can be used to
392 * display the list of available dictionary sources.
393 *
394 * Return value: the newly created #GdictSourceChooser widget.
395 *
396 * Since: 0.12
397 */
398 GtkWidget *
gdict_source_chooser_new(void)399 gdict_source_chooser_new (void)
400 {
401 return g_object_new (GDICT_TYPE_SOURCE_CHOOSER, NULL);
402 }
403
404 /**
405 * gdict_source_chooser_new_with_loader:
406 * @loader: a #GdictSourceLoader
407 *
408 * Creates a new #GdictSourceChooser widget and sets @loader as the
409 * #GdictSourceLoader object to be used to retrieve the list of
410 * available dictionary sources.
411 *
412 * Return value: the newly created #GdictSourceChooser widget.
413 *
414 * Since: 0.12
415 */
416 GtkWidget *
gdict_source_chooser_new_with_loader(GdictSourceLoader * loader)417 gdict_source_chooser_new_with_loader (GdictSourceLoader *loader)
418 {
419 g_return_val_if_fail (GDICT_IS_SOURCE_LOADER (loader), NULL);
420
421 return g_object_new (GDICT_TYPE_SOURCE_CHOOSER, "loader", loader, NULL);
422 }
423
424 /**
425 * gdict_source_chooser_set_loader:
426 * @chooser: a #GdictSourceChooser
427 * @loader: (nullable): a #GdictSourceLoader or %NULL to unset it
428 *
429 * Sets the #GdictSourceLoader to be used by the source chooser
430 * widget.
431 *
432 * Since: 0.12
433 */
434 void
gdict_source_chooser_set_loader(GdictSourceChooser * chooser,GdictSourceLoader * loader)435 gdict_source_chooser_set_loader (GdictSourceChooser *chooser,
436 GdictSourceLoader *loader)
437 {
438 GdictSourceChooserPrivate *priv;
439
440 g_return_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser));
441 g_return_if_fail (loader == NULL || GDICT_IS_SOURCE_LOADER (loader));
442
443 priv = chooser->priv;
444
445 if (priv->loader != loader)
446 {
447 if (priv->loader)
448 g_object_unref (priv->loader);
449
450 if (loader)
451 {
452 priv->loader = g_object_ref (loader);
453 gdict_source_chooser_refresh (chooser);
454 }
455
456 g_object_notify (G_OBJECT (chooser), "loader");
457 }
458 }
459
460 /**
461 * gdict_source_chooser_get_loader:
462 * @chooser: a #GdictSourceChooser
463 *
464 * Retrieves the #GdictSourceLoader used by @chooser.
465 *
466 * Return value: (transfer none): a #GdictSourceLoader or %NULL is none is set
467 *
468 * Since: 0.12
469 */
470 GdictSourceLoader *
gdict_source_chooser_get_loader(GdictSourceChooser * chooser)471 gdict_source_chooser_get_loader (GdictSourceChooser *chooser)
472 {
473 g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), NULL);
474
475 return chooser->priv->loader;
476 }
477
478 typedef struct
479 {
480 gchar *source_name;
481 GdictSourceChooser *chooser;
482
483 guint found : 1;
484 guint do_select : 1;
485 guint do_activate : 1;
486 } SelectData;
487
488 static gboolean
scan_for_source_name(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer user_data)489 scan_for_source_name (GtkTreeModel *model,
490 GtkTreePath *path,
491 GtkTreeIter *iter,
492 gpointer user_data)
493 {
494 SelectData *select_data = user_data;
495 gchar *source_name = NULL;
496
497 if (!select_data)
498 return TRUE;
499
500 gtk_tree_model_get (model, iter, SOURCE_NAME, &source_name, -1);
501 if (!source_name)
502 return FALSE;
503
504 if (strcmp (source_name, select_data->source_name) == 0)
505 {
506 GtkTreeView *tree_view;
507 GtkTreeSelection *selection;
508
509 select_data->found = TRUE;
510
511 tree_view = GTK_TREE_VIEW (select_data->chooser->priv->treeview);
512
513 if (select_data->do_activate)
514 {
515 GtkTreeViewColumn *column;
516
517 column = gtk_tree_view_get_column (tree_view, 2);
518
519 gtk_list_store_set (GTK_LIST_STORE (model), iter,
520 SOURCE_CURRENT, PANGO_WEIGHT_BOLD,
521 -1);
522
523 gtk_tree_view_row_activated (tree_view, path, column);
524 }
525
526 selection = gtk_tree_view_get_selection (tree_view);
527 if (select_data->do_select)
528 gtk_tree_selection_select_path (selection, path);
529 else
530 gtk_tree_selection_unselect_path (selection, path);
531 }
532 else
533 {
534 gtk_list_store_set (GTK_LIST_STORE (model), iter,
535 SOURCE_CURRENT, PANGO_WEIGHT_NORMAL,
536 -1);
537 }
538
539 g_free (source_name);
540
541 return FALSE;
542 }
543
544 /**
545 * gdict_source_chooser_select_source:
546 * @chooser: a #GdictSourceChooser
547 * @source_name: the name of a dictionary source
548 *
549 * Selects the dictionary source named @source_name inside @chooser.
550 * The selection is moved but the row containing the dictionary source
551 * is not activated.
552 *
553 * Return value: %TRUE if the source was found and selected
554 *
555 * Since: 0.12
556 */
557 gboolean
gdict_source_chooser_select_source(GdictSourceChooser * chooser,const gchar * source_name)558 gdict_source_chooser_select_source (GdictSourceChooser *chooser,
559 const gchar *source_name)
560 {
561 GdictSourceChooserPrivate *priv;
562 SelectData data;
563 gboolean retval;
564
565 g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), FALSE);
566 g_return_val_if_fail (source_name != NULL, FALSE);
567
568 priv = chooser->priv;
569
570 data.source_name = g_strdup (source_name);
571 data.chooser = chooser;
572 data.found = FALSE;
573 data.do_select = TRUE;
574 data.do_activate = FALSE;
575
576 gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
577 scan_for_source_name,
578 &data);
579
580 retval = data.found;
581
582 g_free (data.source_name);
583
584 return retval;
585 }
586
587 /**
588 * gdict_source_chooser_unselect_source:
589 * @chooser: a #GdictSourceChooser
590 * @source_name: the name of a dictionary source
591 *
592 * Unselects @source_name inside @chooser.
593 *
594 * Return value: %TRUE if the source was found and unselected
595 *
596 * Since: 0.12
597 */
598 gboolean
gdict_source_chooser_unselect_source(GdictSourceChooser * chooser,const gchar * source_name)599 gdict_source_chooser_unselect_source (GdictSourceChooser *chooser,
600 const gchar *source_name)
601 {
602 GdictSourceChooserPrivate *priv;
603 SelectData data;
604 gboolean retval;
605
606 g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), FALSE);
607 g_return_val_if_fail (source_name != NULL, FALSE);
608
609 priv = chooser->priv;
610
611 data.source_name = g_strdup (source_name);
612 data.chooser = chooser;
613 data.found = FALSE;
614 data.do_select = FALSE;
615 data.do_activate = FALSE;
616
617 gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
618 scan_for_source_name,
619 &data);
620
621 retval = data.found;
622
623 g_free (data.source_name);
624
625 return retval;
626 }
627
628 /**
629 * gdict_source_chooser_set_current_source:
630 * @chooser: a #GdictSourceChooser
631 * @source_name: the name of a dictionary source
632 *
633 * Sets the current dictionary source named @source_name. The row
634 * of the source, if found, will be selected and activated.
635 *
636 * Return value: %TRUE if the source was found
637 *
638 * Since: 0.12
639 */
640 gboolean
gdict_source_chooser_set_current_source(GdictSourceChooser * chooser,const gchar * source_name)641 gdict_source_chooser_set_current_source (GdictSourceChooser *chooser,
642 const gchar *source_name)
643 {
644 GdictSourceChooserPrivate *priv;
645 SelectData data;
646 gboolean retval;
647
648 g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), FALSE);
649 g_return_val_if_fail (source_name != NULL, FALSE);
650
651 priv = chooser->priv;
652
653 if (priv->current_source && !strcmp (priv->current_source, source_name))
654 return TRUE;
655
656 data.source_name = g_strdup (source_name);
657 data.chooser = chooser;
658 data.found = FALSE;
659 data.do_select = TRUE;
660 data.do_activate = TRUE;
661
662 gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
663 scan_for_source_name,
664 &data);
665
666 retval = data.found;
667
668 GDICT_NOTE (CHOOSER, "%s current source: %s",
669 data.found ? "set" : "not set",
670 data.source_name);
671
672 if (data.found)
673 {
674 g_free (priv->current_source);
675 priv->current_source = data.source_name;
676 }
677 else
678 g_free (data.source_name);
679
680 return retval;
681 }
682
683 /**
684 * gdict_source_chooser_get_current_source:
685 * @chooser: a #GdictSourceChooser
686 *
687 * Retrieves the currently selected source.
688 *
689 * Return value: a newly allocated string containing the name of
690 * the currently selected source. Use g_free() when done using it
691 *
692 * Since: 0.12
693 */
694 gchar *
gdict_source_chooser_get_current_source(GdictSourceChooser * chooser)695 gdict_source_chooser_get_current_source (GdictSourceChooser *chooser)
696 {
697 GdictSourceChooserPrivate *priv;
698 GtkTreeSelection *selection;
699 GtkTreeModel *model;
700 GtkTreeIter iter;
701 gchar *retval = NULL;
702
703 g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), NULL);
704
705 priv = chooser->priv;
706
707 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
708 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
709 return NULL;
710
711 gtk_tree_model_get (model, &iter, SOURCE_NAME, &retval, -1);
712
713 g_free (priv->current_source);
714 priv->current_source = g_strdup (retval);
715
716 return retval;
717 }
718
719 /**
720 * gdict_source_chooser_get_sources:
721 * @chooser: a #GdictSouceChooser
722 * @length: return location for the length of the returned vector
723 *
724 * Retrieves the names of the available dictionary sources.
725 *
726 * Return value: (transfer full): a newly allocated, %NULL terminated
727 * string vector containing the names of the available sources.
728 * Use g_strfreev() when done using it.
729 *
730 * Since: 0.12
731 */
732 gchar **
gdict_source_chooser_get_sources(GdictSourceChooser * chooser,gsize * length)733 gdict_source_chooser_get_sources (GdictSourceChooser *chooser,
734 gsize *length)
735 {
736 GdictSourceChooserPrivate *priv;
737 gchar **retval;
738 gsize retval_len;
739
740 g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), NULL);
741
742 priv = chooser->priv;
743
744 if (!priv->loader)
745 return NULL;
746
747 retval = gdict_source_loader_get_names (priv->loader, &retval_len);
748 if (length)
749 *length = retval_len;
750
751 return retval;
752 }
753
754 /**
755 * gdict_source_chooser_count_sources:
756 * @chooser: a #GdictSourceChooser
757 *
758 * Retrieve the number of available dictionary sources.
759 *
760 * Return value: the number of available sources, or -1 if no
761 * #GdictSourceLoader has been set
762 *
763 * Since: 0.12
764 */
765 gint
gdict_source_chooser_count_sources(GdictSourceChooser * chooser)766 gdict_source_chooser_count_sources (GdictSourceChooser *chooser)
767 {
768 g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), -1);
769
770 return chooser->priv->n_sources;
771 }
772
773 /**
774 * gdict_source_chooser_has_source:
775 * @chooser: a #GdictSourceChooser
776 * @source_name: the name of a dictionary source
777 *
778 * Checks whether @chooser has a dictionary source named @source_name.
779 *
780 * Return value: %TRUE if the dictionary source was found
781 *
782 * Since: 0.12
783 */
784 gboolean
gdict_source_chooser_has_source(GdictSourceChooser * chooser,const gchar * source_name)785 gdict_source_chooser_has_source (GdictSourceChooser *chooser,
786 const gchar *source_name)
787 {
788 GdictSourceChooserPrivate *priv;
789
790 g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), FALSE);
791 g_return_val_if_fail (source_name != NULL, FALSE);
792
793 priv = chooser->priv;
794
795 if (!priv->loader)
796 return FALSE;
797
798 return gdict_source_loader_has_source (priv->loader, source_name);
799 }
800
801 /**
802 * gdict_source_chooser_refresh:
803 * @chooser: a #GdictSourceChooser
804 *
805 * Forces a refresh on the contents of the source chooser widget
806 *
807 * Since: 0.12
808 */
809 void
gdict_source_chooser_refresh(GdictSourceChooser * chooser)810 gdict_source_chooser_refresh (GdictSourceChooser *chooser)
811 {
812 GdictSourceChooserPrivate *priv;
813
814 g_return_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser));
815
816 priv = chooser->priv;
817
818 if (priv->loader)
819 {
820 const GSList *sources, *l;
821
822 if (priv->treeview)
823 gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), NULL);
824
825 gtk_list_store_clear (priv->store);
826
827 sources = gdict_source_loader_get_sources (priv->loader);
828 for (l = sources; l != NULL; l = l->next)
829 {
830 GdictSource *source = l->data;
831 const gchar *name, *description;
832 GdictSourceTransport transport;
833 gint weight;
834
835 transport = gdict_source_get_transport (source);
836 name = gdict_source_get_name (source);
837 description = gdict_source_get_description (source);
838 weight = PANGO_WEIGHT_NORMAL;
839
840 if (priv->current_source && !strcmp (priv->current_source, name))
841 weight = PANGO_WEIGHT_BOLD;
842
843 gtk_list_store_insert_with_values (priv->store, NULL, -1,
844 SOURCE_TRANSPORT, transport,
845 SOURCE_NAME, name,
846 SOURCE_DESCRIPTION, description,
847 SOURCE_CURRENT, weight,
848 -1);
849 }
850
851 if (priv->treeview)
852 gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
853 GTK_TREE_MODEL (priv->store));
854 }
855 }
856
857 /**
858 * gdict_source_chooser_add_button:
859 * @chooser: a #GdictSourceChooser
860 * @button_text: text of the button
861 *
862 * Adds a #GtkButton with @button_text to the button area on
863 * the bottom of @chooser.
864 *
865 * Return value: (transfer none): the newly packed button.
866 *
867 * Since: 0.12
868 */
869 GtkWidget *
gdict_source_chooser_add_button(GdictSourceChooser * chooser,const gchar * button_text)870 gdict_source_chooser_add_button (GdictSourceChooser *chooser,
871 const gchar *button_text)
872 {
873 GdictSourceChooserPrivate *priv;
874 GtkWidget *button;
875
876 g_return_val_if_fail (GDICT_IS_SOURCE_CHOOSER (chooser), NULL);
877 g_return_val_if_fail (button_text != NULL, NULL);
878
879 priv = chooser->priv;
880
881 button = gtk_button_new_with_label (button_text);
882
883 gtk_widget_set_can_default (button, TRUE);
884
885 gtk_widget_show (button);
886
887 gtk_box_pack_end (GTK_BOX (priv->buttons_box), button, FALSE, TRUE, 0);
888
889 return button;
890 }
891
892