1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /*
4 * GThumb
5 *
6 * Copyright (C) 2005-2009 Free Software Foundation, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23 #include <string.h>
24 #include <glib/gi18n.h>
25 #include <glib.h>
26 #include <glib/gprintf.h>
27 #include <gtk/gtk.h>
28 #include "gio-utils.h"
29 #include "glib-utils.h"
30 #include "gth-file-source.h"
31 #include "gth-location-chooser.h"
32 #include "gth-location-chooser-dialog.h"
33 #include "gth-main.h"
34 #include "gtk-utils.h"
35 #include "pixbuf-utils.h"
36
37
38 #define MIN_WIDTH 200
39
40
41 typedef enum {
42 ITEM_TYPE_NONE,
43 ITEM_TYPE_SEPARATOR,
44 ITEM_TYPE_LOCATION,
45 ITEM_TYPE_ENTRY_POINT,
46 ITEM_TYPE_CHOOSE_LOCATION
47 } ItemType;
48
49 enum {
50 ICON_COLUMN,
51 NAME_COLUMN,
52 URI_COLUMN,
53 TYPE_COLUMN,
54 ELLIPSIZE_COLUMN,
55 N_COLUMNS
56 };
57
58 enum {
59 PROP_0,
60 PROP_SHOW_ENTRY_POINTS,
61 PROP_SHOW_OTHER,
62 PROP_SHOW_ROOT,
63 PROP_RELIEF
64 };
65
66 enum {
67 CHANGED,
68 LAST_SIGNAL
69 };
70
71
72 struct _GthLocationChooserPrivate {
73 GtkWidget *combo;
74 GtkTreeStore *model;
75 GFile *location;
76 GthFileSource *file_source;
77 gulong entry_points_changed_id;
78 guint update_entry_list_id;
79 guint update_location_list_id;
80 gboolean show_entry_points;
81 gboolean show_root;
82 gboolean show_other;
83 GtkReliefStyle relief;
84 gboolean reload;
85 };
86
87
88 static guint gth_location_chooser_signals[LAST_SIGNAL] = { 0 };
89
90
G_DEFINE_TYPE_WITH_CODE(GthLocationChooser,gth_location_chooser,GTK_TYPE_BOX,G_ADD_PRIVATE (GthLocationChooser))91 G_DEFINE_TYPE_WITH_CODE (GthLocationChooser,
92 gth_location_chooser,
93 GTK_TYPE_BOX,
94 G_ADD_PRIVATE (GthLocationChooser))
95
96
97 static void
98 gth_location_chooser_set_property (GObject *object,
99 guint property_id,
100 const GValue *value,
101 GParamSpec *pspec)
102 {
103 GthLocationChooser *self;
104
105 self = GTH_LOCATION_CHOOSER (object);
106
107 switch (property_id) {
108 case PROP_SHOW_ENTRY_POINTS:
109 gth_location_chooser_set_show_entry_points (self, g_value_get_boolean (value));
110 break;
111 case PROP_SHOW_ROOT:
112 self->priv->show_root = g_value_get_boolean (value);
113 break;
114 case PROP_SHOW_OTHER:
115 self->priv->show_other = g_value_get_boolean (value);
116 break;
117 case PROP_RELIEF:
118 gth_location_chooser_set_relief (self, g_value_get_enum (value));
119 break;
120 default:
121 break;
122 }
123 }
124
125
126 static void
gth_location_chooser_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)127 gth_location_chooser_get_property (GObject *object,
128 guint property_id,
129 GValue *value,
130 GParamSpec *pspec)
131 {
132 GthLocationChooser *self;
133
134 self = GTH_LOCATION_CHOOSER (object);
135
136 switch (property_id) {
137 case PROP_SHOW_ENTRY_POINTS:
138 g_value_set_boolean (value, self->priv->show_entry_points);
139 break;
140 case PROP_SHOW_ROOT:
141 g_value_set_boolean (value, self->priv->show_root);
142 break;
143 case PROP_SHOW_OTHER:
144 g_value_set_boolean (value, self->priv->show_other);
145 break;
146 case PROP_RELIEF:
147 g_value_set_enum (value, self->priv->relief);
148 break;
149 default:
150 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
151 break;
152 }
153 }
154
155
156 static void
gth_location_chooser_finalize(GObject * object)157 gth_location_chooser_finalize (GObject *object)
158 {
159 GthLocationChooser *self;
160
161 self = GTH_LOCATION_CHOOSER (object);
162
163 if (self->priv->update_location_list_id != 0)
164 g_source_remove (self->priv->update_location_list_id);
165 if (self->priv->update_entry_list_id != 0)
166 g_source_remove (self->priv->update_entry_list_id);
167 if (self->priv->entry_points_changed_id != 0)
168 g_signal_handler_disconnect (gth_main_get_default_monitor (),
169 self->priv->entry_points_changed_id);
170 if (self->priv->file_source != NULL)
171 g_object_unref (self->priv->file_source);
172 if (self->priv->location != NULL)
173 g_object_unref (self->priv->location);
174
175 G_OBJECT_CLASS (gth_location_chooser_parent_class)->finalize (object);
176 }
177
178
179 static gboolean
get_nth_separator_pos(GthLocationChooser * self,int pos,int * idx)180 get_nth_separator_pos (GthLocationChooser *self,
181 int pos,
182 int *idx)
183 {
184 GtkTreeIter iter;
185 gboolean n_found = 0;
186
187 if (idx != NULL)
188 *idx = 0;
189
190 if (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->model), &iter))
191 return FALSE;
192
193 do {
194 int item_type = ITEM_TYPE_NONE;
195
196 gtk_tree_model_get (GTK_TREE_MODEL (self->priv->model),
197 &iter,
198 TYPE_COLUMN, &item_type,
199 -1);
200 if (item_type == ITEM_TYPE_SEPARATOR) {
201 n_found++;
202 if (n_found == pos)
203 break;
204 }
205
206 if (idx != NULL)
207 *idx = *idx + 1;
208 }
209 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->model), &iter));
210
211 return n_found == pos;
212 }
213
214
215 static gboolean
get_iter_from_current_file_entries(GthLocationChooser * self,GFile * file,GtkTreeIter * iter)216 get_iter_from_current_file_entries (GthLocationChooser *self,
217 GFile *file,
218 GtkTreeIter *iter)
219 {
220 gboolean found = FALSE;
221 char *uri;
222
223 if (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->model), iter))
224 return FALSE;
225
226 uri = g_file_get_uri (file);
227 do {
228 int item_type = ITEM_TYPE_NONE;
229 char *list_uri;
230
231 gtk_tree_model_get (GTK_TREE_MODEL (self->priv->model),
232 iter,
233 TYPE_COLUMN, &item_type,
234 URI_COLUMN, &list_uri,
235 -1);
236 if (item_type == ITEM_TYPE_SEPARATOR)
237 break;
238 if (_g_str_equal (uri, list_uri)) {
239 found = TRUE;
240 g_free (list_uri);
241 break;
242 }
243 g_free (list_uri);
244 }
245 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->model), iter));
246
247 g_free (uri);
248
249 return found;
250 }
251
252
253 static void
combo_changed_cb(GtkComboBox * widget,gpointer user_data)254 combo_changed_cb (GtkComboBox *widget,
255 gpointer user_data)
256 {
257 GthLocationChooser *self = user_data;
258 GtkTreeIter iter;
259 char *uri = NULL;
260 int item_type = ITEM_TYPE_NONE;
261
262 if (! gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->priv->combo), &iter))
263 return;
264
265 gtk_tree_model_get (GTK_TREE_MODEL (self->priv->model),
266 &iter,
267 TYPE_COLUMN, &item_type,
268 URI_COLUMN, &uri,
269 -1);
270
271 if (item_type == ITEM_TYPE_CHOOSE_LOCATION) {
272 GtkWidget *dialog;
273
274 dialog = gth_location_chooser_dialog_new (_("Location"), _gtk_widget_get_toplevel_if_window (GTK_WIDGET (widget)));
275 if (self->priv->location != NULL)
276 gth_location_chooser_dialog_set_folder (GTH_LOCATION_CHOOSER_DIALOG (dialog), self->priv->location);
277
278 switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
279 case GTK_RESPONSE_OK:
280 gth_location_chooser_set_current (self, gth_location_chooser_dialog_get_folder (GTH_LOCATION_CHOOSER_DIALOG (dialog)));
281 break;
282
283 default:
284 /* reset the previous value. */
285 gth_location_chooser_set_current (self, self->priv->location);
286 break;
287 }
288
289 gtk_widget_destroy (dialog);
290 }
291 else if (uri != NULL) {
292 GFile *file;
293
294 file = g_file_new_for_uri (uri);
295 gth_location_chooser_set_current (self, file);
296
297 g_object_unref (file);
298 }
299 }
300
301
302 static void
add_file_source_entries(GthLocationChooser * self,GFile * file,const char * name,GIcon * icon,int position,gboolean update_active_iter,int iter_type)303 add_file_source_entries (GthLocationChooser *self,
304 GFile *file,
305 const char *name,
306 GIcon *icon,
307 int position,
308 gboolean update_active_iter,
309 int iter_type)
310 {
311 GtkTreeIter iter;
312 char *uri;
313
314 uri = g_file_get_uri (file);
315
316 gtk_tree_store_insert (self->priv->model, &iter, NULL, position);
317 gtk_tree_store_set (self->priv->model, &iter,
318 TYPE_COLUMN, iter_type,
319 ICON_COLUMN, icon,
320 NAME_COLUMN, name,
321 URI_COLUMN, uri,
322 ELLIPSIZE_COLUMN, PANGO_ELLIPSIZE_END,
323 -1);
324
325 g_free (uri);
326
327 if (update_active_iter && g_file_equal (self->priv->location, file)) {
328 g_signal_handlers_block_by_func (self->priv->combo, combo_changed_cb, self);
329 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self->priv->combo), &iter);
330 g_signal_handlers_unblock_by_func (self->priv->combo, combo_changed_cb, self);
331 }
332 }
333
334
335 static void
clear_items_from_separator(GthLocationChooser * self,int nth_separator,gboolean stop_at_next_separator)336 clear_items_from_separator (GthLocationChooser *self,
337 int nth_separator,
338 gboolean stop_at_next_separator)
339 {
340 int first_position;
341 int i;
342
343 if (! get_nth_separator_pos (self, nth_separator, &first_position))
344 return;
345
346 for (i = first_position + 1; TRUE; i++) {
347 GtkTreePath *path;
348 GtkTreeIter iter;
349
350 path = gtk_tree_path_new_from_indices (first_position + 1, -1);
351 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (self->priv->model), &iter, path)) {
352 if (stop_at_next_separator) {
353 int item_type = ITEM_TYPE_NONE;
354
355 gtk_tree_model_get (GTK_TREE_MODEL (self->priv->model),
356 &iter,
357 TYPE_COLUMN, &item_type,
358 -1);
359 if (item_type == ITEM_TYPE_SEPARATOR)
360 break;
361 }
362 gtk_tree_store_remove (self->priv->model, &iter);
363 }
364 else
365 break;
366
367 gtk_tree_path_free (path);
368 }
369 }
370
371
372 static void
delete_section_by_type(GthLocationChooser * self,ItemType type_to_delete)373 delete_section_by_type (GthLocationChooser *self,
374 ItemType type_to_delete)
375 {
376 GtkTreeIter iter;
377 gboolean valid;
378 gboolean prev_matched;
379
380 if (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->model), &iter))
381 return;
382
383 prev_matched = FALSE;
384 do {
385 int item_type = ITEM_TYPE_NONE;
386
387 gtk_tree_model_get (GTK_TREE_MODEL (self->priv->model),
388 &iter,
389 TYPE_COLUMN, &item_type,
390 -1);
391
392 if (item_type == type_to_delete) {
393 valid = gtk_tree_store_remove (self->priv->model, &iter);
394 prev_matched = TRUE;
395 }
396 else {
397 if (prev_matched && (item_type == ITEM_TYPE_SEPARATOR))
398 valid = gtk_tree_store_remove (self->priv->model, &iter);
399 else
400 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->model), &iter);
401 prev_matched = FALSE;
402 }
403 }
404 while (valid);
405 }
406
407
408 static gboolean
get_section_end_by_type(GthLocationChooser * self,ItemType item_to_search,int * p_pos)409 get_section_end_by_type (GthLocationChooser *self,
410 ItemType item_to_search,
411 int *p_pos)
412 {
413 GtkTreeIter iter;
414 int pos;
415 gboolean valid;
416 gboolean prev_matched;
417
418 if (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->model), &iter))
419 return FALSE;
420
421 pos = 0;
422 valid = FALSE;
423 prev_matched = FALSE;
424 do {
425 int item_type = ITEM_TYPE_NONE;
426
427 gtk_tree_model_get (GTK_TREE_MODEL (self->priv->model),
428 &iter,
429 TYPE_COLUMN, &item_type,
430 -1);
431
432 if (item_type == item_to_search) {
433 *p_pos = pos;
434 valid = TRUE;
435 prev_matched = TRUE;
436 }
437 else {
438 if ((item_type == ITEM_TYPE_SEPARATOR) && prev_matched)
439 *p_pos = pos;
440 prev_matched = FALSE;
441 }
442
443 pos++;
444 }
445 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->model), &iter));
446
447 return valid;
448 }
449
450
451 static void
update_entry_point_list(GthLocationChooser * self)452 update_entry_point_list (GthLocationChooser *self)
453 {
454 int position;
455 GList *entry_points;
456 GList *scan;
457
458 self->priv->update_entry_list_id = 0;
459
460 delete_section_by_type (self, ITEM_TYPE_ENTRY_POINT);
461
462 if (get_section_end_by_type (self, ITEM_TYPE_LOCATION, &position))
463 position = position + 1;
464 else
465 position = 0;
466
467 entry_points = gth_main_get_all_entry_points ();
468 for (scan = entry_points; scan; scan = scan->next) {
469 GthFileData *file_data = scan->data;
470
471 add_file_source_entries (self,
472 file_data->file,
473 g_file_info_get_display_name (file_data->info),
474 g_file_info_get_symbolic_icon (file_data->info),
475 position++,
476 FALSE,
477 ITEM_TYPE_ENTRY_POINT);
478 }
479
480 if (self->priv->show_other) {
481 GtkTreeIter iter;
482
483 gtk_tree_store_insert (self->priv->model, &iter, NULL, position);
484 gtk_tree_store_set (self->priv->model, &iter,
485 TYPE_COLUMN, ITEM_TYPE_SEPARATOR,
486 -1);
487 }
488
489 _g_object_list_unref (entry_points);
490 }
491
492
493 static gboolean
row_separator_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)494 row_separator_func (GtkTreeModel *model,
495 GtkTreeIter *iter,
496 gpointer data)
497 {
498 int item_type = ITEM_TYPE_NONE;
499
500 gtk_tree_model_get (model,
501 iter,
502 TYPE_COLUMN, &item_type,
503 -1);
504
505 return (item_type == ITEM_TYPE_SEPARATOR);
506 }
507
508
509 static void
entry_points_changed_cb(GthMonitor * monitor,GthLocationChooser * self)510 entry_points_changed_cb (GthMonitor *monitor,
511 GthLocationChooser *self)
512 {
513 if (! self->priv->show_entry_points)
514 return;
515 if (self->priv->update_entry_list_id != 0)
516 return;
517 self->priv->update_entry_list_id = call_when_idle ((DataFunc) update_entry_point_list, self);
518 }
519
520
521 static void
update_location_list(gpointer user_data)522 update_location_list (gpointer user_data)
523 {
524 GthLocationChooser *self = user_data;
525 GtkTreeIter iter;
526
527 self->priv->update_location_list_id = 0;
528
529 if (self->priv->location == NULL)
530 return;
531
532 if (! self->priv->reload && get_iter_from_current_file_entries (self, self->priv->location, &iter)) {
533 g_signal_handlers_block_by_func (self->priv->combo, combo_changed_cb, self);
534 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self->priv->combo), &iter);
535 g_signal_handlers_unblock_by_func (self->priv->combo, combo_changed_cb, self);
536 }
537 else {
538 GList *list;
539 GList *scan;
540 int position = 0;
541
542 delete_section_by_type (self, ITEM_TYPE_LOCATION);
543
544 list = gth_file_source_get_current_list (self->priv->file_source, self->priv->location);
545 for (scan = list; scan; scan = scan->next) {
546 GFile *file = scan->data;
547 GFileInfo *info;
548
549 info = _g_file_get_info_for_display (file);
550 if (info == NULL)
551 continue;
552
553 add_file_source_entries (self,
554 file,
555 g_file_info_get_display_name (info),
556 g_file_info_get_symbolic_icon (info),
557 position++,
558 TRUE,
559 ITEM_TYPE_LOCATION);
560
561 g_object_unref (info);
562 }
563
564 if (self->priv->show_root) {
565 GIcon *icon;
566
567 icon = g_themed_icon_new ("computer-symbolic");
568 gtk_tree_store_insert (self->priv->model, &iter, NULL, position++);
569 gtk_tree_store_set (self->priv->model, &iter,
570 TYPE_COLUMN, ITEM_TYPE_LOCATION,
571 ICON_COLUMN, icon,
572 NAME_COLUMN, _("Locations"),
573 URI_COLUMN, "gthumb-vfs:///",
574 -1);
575
576 _g_object_unref (icon);
577 }
578
579 if (self->priv->show_other || self->priv->show_entry_points) {
580 GtkTreeIter iter;
581
582 gtk_tree_store_insert (self->priv->model, &iter, NULL, position);
583 gtk_tree_store_set (self->priv->model, &iter,
584 TYPE_COLUMN, ITEM_TYPE_SEPARATOR,
585 -1);
586 }
587
588 _g_object_list_unref (list);
589 }
590
591 self->priv->reload = FALSE;
592 }
593
594
595 static void
current_location_changed(GthLocationChooser * self)596 current_location_changed (GthLocationChooser *self)
597 {
598 if (self->priv->update_location_list_id != 0)
599 g_source_remove (self->priv->update_location_list_id);
600 self->priv->update_location_list_id = call_when_idle ((DataFunc) update_location_list, self);
601 }
602
603
604 static void
gth_location_chooser_realize(GtkWidget * widget)605 gth_location_chooser_realize (GtkWidget *widget)
606 {
607 GthLocationChooser *self = GTH_LOCATION_CHOOSER (widget);
608
609 GTK_WIDGET_CLASS (gth_location_chooser_parent_class)->realize (widget);
610
611 if (self->priv->show_other) {
612 GtkTreeIter iter;
613
614 gtk_tree_store_append (self->priv->model, &iter, NULL);
615 gtk_tree_store_set (self->priv->model, &iter,
616 TYPE_COLUMN, ITEM_TYPE_CHOOSE_LOCATION,
617 NAME_COLUMN, _("Other…"),
618 ELLIPSIZE_COLUMN, FALSE,
619 -1);
620 }
621 entry_points_changed_cb (NULL, self);
622 current_location_changed (self);
623 }
624
625
626 static void
gth_location_chooser_class_init(GthLocationChooserClass * klass)627 gth_location_chooser_class_init (GthLocationChooserClass *klass)
628 {
629 GObjectClass *object_class;
630 GtkWidgetClass *widget_class;
631
632 object_class = (GObjectClass*) klass;
633 object_class->set_property = gth_location_chooser_set_property;
634 object_class->get_property = gth_location_chooser_get_property;
635 object_class->finalize = gth_location_chooser_finalize;
636
637 widget_class = (GtkWidgetClass *) klass;
638 widget_class->realize = gth_location_chooser_realize;
639
640 /* properties */
641
642 g_object_class_install_property (object_class,
643 PROP_SHOW_ENTRY_POINTS,
644 g_param_spec_boolean ("show-entry-points",
645 "Show entry points",
646 "Whether to show the entry points in the list",
647 TRUE,
648 G_PARAM_READWRITE));
649 g_object_class_install_property (object_class,
650 PROP_SHOW_ROOT,
651 g_param_spec_boolean ("show-root",
652 "Show the VFS root",
653 "Whether to show the VFS root in the list",
654 FALSE,
655 G_PARAM_READWRITE));
656 g_object_class_install_property (object_class,
657 PROP_SHOW_OTHER,
658 g_param_spec_boolean ("show-other",
659 "Show the Other... entry",
660 "Whether to show a special entry to choose a location from a dialog",
661 FALSE,
662 G_PARAM_READWRITE));
663 g_object_class_install_property (object_class,
664 PROP_RELIEF,
665 g_param_spec_enum ("relief",
666 "Border relief",
667 "The border relief style",
668 GTK_TYPE_RELIEF_STYLE,
669 GTK_RELIEF_NORMAL,
670 G_PARAM_READWRITE));
671
672 /* signals */
673
674 gth_location_chooser_signals[CHANGED] =
675 g_signal_new ("changed",
676 G_TYPE_FROM_CLASS (klass),
677 G_SIGNAL_RUN_LAST,
678 G_STRUCT_OFFSET (GthLocationChooserClass, changed),
679 NULL, NULL,
680 g_cclosure_marshal_VOID__VOID,
681 G_TYPE_NONE,
682 0);
683 }
684
685
686 static void
gth_location_chooser_init(GthLocationChooser * self)687 gth_location_chooser_init (GthLocationChooser *self)
688 {
689 GtkCellRenderer *renderer;
690
691 gtk_widget_set_can_focus (GTK_WIDGET (self), FALSE);
692 gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_HORIZONTAL);
693
694 self->priv = gth_location_chooser_get_instance_private (self);
695 self->priv->entry_points_changed_id = 0;
696 self->priv->show_entry_points = TRUE;
697 self->priv->show_root = FALSE;
698 self->priv->show_other = TRUE;
699 self->priv->relief = GTK_RELIEF_NORMAL;
700 self->priv->reload = FALSE;
701
702 self->priv->model = gtk_tree_store_new (N_COLUMNS,
703 G_TYPE_ICON,
704 G_TYPE_STRING,
705 G_TYPE_STRING,
706 G_TYPE_INT,
707 PANGO_TYPE_ELLIPSIZE_MODE);
708 self->priv->combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (self->priv->model));
709 g_object_unref (self->priv->model);
710 g_signal_connect (self->priv->combo,
711 "changed",
712 G_CALLBACK (combo_changed_cb),
713 self);
714 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (self->priv->combo),
715 row_separator_func,
716 self,
717 NULL);
718 gtk_widget_set_size_request (self->priv->combo, MIN_WIDTH, -1);
719
720 /* icon column */
721
722 renderer = gtk_cell_renderer_pixbuf_new ();
723 g_object_set (renderer,
724 "follow-state", TRUE,
725 NULL);
726 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->priv->combo),
727 renderer,
728 FALSE);
729 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self->priv->combo),
730 renderer,
731 "gicon", ICON_COLUMN,
732 NULL);
733
734 /* path column */
735
736 renderer = gtk_cell_renderer_text_new ();
737 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->priv->combo),
738 renderer,
739 TRUE);
740 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self->priv->combo),
741 renderer,
742 "text", NAME_COLUMN,
743 "ellipsize", ELLIPSIZE_COLUMN,
744 NULL);
745
746 /**/
747
748 gtk_widget_show (self->priv->combo);
749 gtk_box_pack_start (GTK_BOX (self), self->priv->combo, TRUE, TRUE, 0);
750 }
751
752
753 GtkWidget *
gth_location_chooser_new(void)754 gth_location_chooser_new (void)
755 {
756 return GTK_WIDGET (g_object_new (GTH_TYPE_LOCATION_CHOOSER, NULL));
757 }
758
759
760 /* -- gth_location_chooser_set_relief -- */
761
762
763 void
gth_location_chooser_set_relief(GthLocationChooser * self,GtkReliefStyle value)764 gth_location_chooser_set_relief (GthLocationChooser *self,
765 GtkReliefStyle value)
766 {
767 if (self->priv->relief == value)
768 return;
769
770 self->priv->relief = value;
771 g_object_notify (G_OBJECT (self), "relief");
772 }
773
774
775 GtkReliefStyle
gth_location_chooser_get_relief(GthLocationChooser * self)776 gth_location_chooser_get_relief (GthLocationChooser *self)
777 {
778 return self->priv->relief;
779 }
780
781
782 void
gth_location_chooser_set_show_entry_points(GthLocationChooser * self,gboolean value)783 gth_location_chooser_set_show_entry_points (GthLocationChooser *self,
784 gboolean value)
785 {
786 self->priv->show_entry_points = value;
787
788 if (self->priv->show_entry_points) {
789 if (self->priv->entry_points_changed_id == 0)
790 self->priv->entry_points_changed_id =
791 g_signal_connect (gth_main_get_default_monitor (),
792 "entry-points-changed",
793 G_CALLBACK (entry_points_changed_cb),
794 self);
795 entry_points_changed_cb (NULL, self);
796 }
797 else {
798 if (self->priv->entry_points_changed_id != 0) {
799 g_source_remove (self->priv->entry_points_changed_id);
800 self->priv->entry_points_changed_id = 0;
801 }
802 clear_items_from_separator (self, 1, TRUE);
803 }
804
805 g_object_notify (G_OBJECT (self), "show-entry-points");
806 }
807
808
809 gboolean
gth_location_chooser_get_show_entry_points(GthLocationChooser * self)810 gth_location_chooser_get_show_entry_points (GthLocationChooser *self)
811 {
812 return self->priv->show_entry_points;
813 }
814
815
816 void
gth_location_chooser_set_current(GthLocationChooser * self,GFile * file)817 gth_location_chooser_set_current (GthLocationChooser *self,
818 GFile *file)
819 {
820 if (file == NULL)
821 return;
822
823 if (file != self->priv->location) {
824 if (self->priv->file_source != NULL)
825 g_object_unref (self->priv->file_source);
826 self->priv->file_source = gth_main_get_file_source (file);
827
828 if (self->priv->file_source == NULL)
829 return;
830
831 if (self->priv->location != NULL) {
832 g_object_unref (self->priv->location);
833 self->priv->location = NULL;
834 }
835
836 if (file != NULL)
837 self->priv->location = g_file_dup (file);
838 }
839
840 if (gtk_widget_get_realized (GTK_WIDGET (self)))
841 current_location_changed (self);
842
843 g_signal_emit (G_OBJECT (self), gth_location_chooser_signals[CHANGED], 0);
844 }
845
846
847 GFile *
gth_location_chooser_get_current(GthLocationChooser * self)848 gth_location_chooser_get_current (GthLocationChooser *self)
849 {
850 return self->priv->location;
851 }
852
853 void
gth_location_chooser_reload(GthLocationChooser * self)854 gth_location_chooser_reload (GthLocationChooser *self)
855 {
856 if (self->priv->location == NULL)
857 return;
858
859 self->priv->reload = TRUE;
860
861 if (gtk_widget_get_realized (GTK_WIDGET (self)))
862 current_location_changed (self);
863 }
864