1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 
3 /*
4  *  GThumb
5  *
6  *  Copyright (C) 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 <glib/gi18n.h>
24 #include "dlg-favorite-properties.h"
25 #include "glib-utils.h"
26 #include "gth-file-properties.h"
27 #include "gth-main.h"
28 #include "gth-preferences.h"
29 #include "gth-property-view.h"
30 #include "gth-string-list.h"
31 #include "gth-time.h"
32 #include "gtk-utils.h"
33 
34 
35 #define FONT_SCALE (0.85)
36 #define MIN_HEIGHT 100
37 #define COMMENT_DEFAULT_HEIGHT 100
38 #define CATEGORY_SIZE 1000
39 #define MAX_ATTRIBUTE_LENGTH 128
40 
41 /* Properties */
42 enum {
43 	PROP_0,
44 	PROP_SHOW_DETAILS
45 };
46 
47 enum {
48 	SCALE_SET_COLUMN,
49 	WEIGHT_COLUMN,
50 	ID_COLUMN,
51 	DISPLAY_NAME_COLUMN,
52 	VALUE_COLUMN,
53 	TOOLTIP_COLUMN,
54 	RAW_COLUMN,
55 	POS_COLUMN,
56 	WRITEABLE_COLUMN,
57 	NUM_COLUMNS
58 };
59 
60 
61 struct _GthFilePropertiesPrivate {
62 	GSettings     *settings;
63 	GtkWidget     *main_container;
64 	GtkWidget     *tree_view;
65 	GtkListStore  *tree_model;
66 	GtkWidget     *popup_menu;
67 	GtkWidget     *copy_menu_item;
68 	GtkWidget     *edit_favorites_menu_item;
69 	GtkWidget     *context_menu_sep;
70 	gboolean       show_details;
71 	GthFileData   *last_file_data;
72 	GHashTable    *favorites;
73 	gboolean       default_favorites;
74 };
75 
76 
77 static void gth_file_properties_gth_property_view_interface_init (GthPropertyViewInterface *iface);
78 
79 
G_DEFINE_TYPE_WITH_CODE(GthFileProperties,gth_file_properties,GTK_TYPE_BOX,G_ADD_PRIVATE (GthFileProperties)G_IMPLEMENT_INTERFACE (GTH_TYPE_PROPERTY_VIEW,gth_file_properties_gth_property_view_interface_init))80 G_DEFINE_TYPE_WITH_CODE (GthFileProperties,
81 			 gth_file_properties,
82 			 GTK_TYPE_BOX,
83 			 G_ADD_PRIVATE (GthFileProperties)
84 			 G_IMPLEMENT_INTERFACE (GTH_TYPE_PROPERTY_VIEW,
85 						gth_file_properties_gth_property_view_interface_init))
86 
87 
88 static gboolean
89 gth_file_properties_real_can_view (GthPropertyView *base,
90 				   GthFileData     *file_data)
91 {
92 	GthFileProperties *self = GTH_FILE_PROPERTIES (base);
93 	gboolean           data_available;
94 	GList             *metadata_info;
95 	GList             *scan;
96 
97 	if (file_data == NULL)
98 		return FALSE;
99 
100 	if (! self->priv->show_details)
101 		return TRUE;
102 
103 	data_available = FALSE;
104 	metadata_info = gth_main_get_all_metadata_info ();
105 	for (scan = metadata_info; scan; scan = scan->next) {
106 		GthMetadataInfo *info = scan->data;
107 		char            *value;
108 
109 		if ((info->flags & GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW) != GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW)
110 			continue;
111 
112 		value = gth_file_data_get_attribute_as_string (file_data, info->id);
113 		if ((value == NULL) || (*value == '\0')) {
114 			g_free (value);
115 			continue;
116 		}
117 
118 		if (info->id != NULL) {
119 			if (g_str_has_prefix (info->id, "Exif")) {
120 				data_available = TRUE;
121 				break;
122 			}
123 			else if (g_str_has_prefix (info->id, "Iptc")) {
124 				data_available = TRUE;
125 				break;
126 			}
127 			else if (g_str_has_prefix (info->id, "Xmp")) {
128 				data_available = TRUE;
129 				break;
130 			}
131 		}
132 	}
133 
134 	return data_available;
135 }
136 
137 
138 static void
gth_file_properties_real_set_file(GthPropertyView * base,GthFileData * file_data)139 gth_file_properties_real_set_file (GthPropertyView *base,
140 		 		   GthFileData     *file_data)
141 {
142 	GthFileProperties *self;
143 	GHashTable        *category_hash;
144 	GList             *metadata_info;
145 	GList             *scan;
146 
147 	self = GTH_FILE_PROPERTIES (base);
148 
149 	if (file_data != self->priv->last_file_data) {
150 		_g_object_unref (self->priv->last_file_data);
151 		self->priv->last_file_data = gth_file_data_dup (file_data);
152 	}
153 
154 	gtk_list_store_clear (self->priv->tree_model);
155 
156 	if (file_data == NULL)
157 		return;
158 
159 	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->priv->tree_model), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, 0);
160 
161 	category_hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
162 	metadata_info = gth_main_get_all_metadata_info ();
163 	for (scan = metadata_info; scan; scan = scan->next) {
164 		GthMetadataInfo     *info = scan->data;
165 		char                *value;
166 		char                *tooltip;
167 		GthMetadataCategory *category;
168 		GtkTreeIter          iter;
169 
170 		if ((info->flags & GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW) != GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW)
171 			continue;
172 
173 		if (info->id == NULL)
174 			continue;
175 
176 		value = gth_file_data_get_attribute_as_string (file_data, info->id);
177 		if ((value == NULL) || (*value == '\0')) {
178 			g_free (value);
179 			continue;
180 		}
181 
182 		if (! self->priv->show_details && ! self->priv->default_favorites) {
183 			if (! g_hash_table_contains (self->priv->favorites, info->id))
184 				continue;
185 		}
186 		else if (g_str_has_prefix (info->id, "Exif")) {
187 			if (! self->priv->show_details)
188 				continue;
189 		}
190 		else if (g_str_has_prefix (info->id, "Iptc")) {
191 			if (! self->priv->show_details)
192 				continue;
193 		}
194 		else if (g_str_has_prefix (info->id, "Xmp")) {
195 			if (! self->priv->show_details)
196 				continue;
197 		}
198 		else
199 			if (self->priv->show_details)
200 				continue;
201 
202 		if (value != NULL) {
203 			char *utf8_value;
204 			char *tmp_value;
205 
206 			utf8_value = _g_utf8_from_any (value);
207 			if (g_utf8_strlen (utf8_value, -1) > MAX_ATTRIBUTE_LENGTH)
208 				g_utf8_strncpy (g_utf8_offset_to_pointer (utf8_value, MAX_ATTRIBUTE_LENGTH - 1), "…", 1);
209 			tmp_value = _g_utf8_replace_pattern (utf8_value, "[\r\n]", " ");
210 			g_free (value);
211 			value = tmp_value;
212 
213 			g_free (utf8_value);
214 		}
215 		tooltip = g_markup_printf_escaped ("%s: %s", _(info->display_name), value);
216 
217 		category = g_hash_table_lookup (category_hash, info->category);
218 		if (category == NULL) {
219 			category = gth_main_get_metadata_category (info->category);
220 			gtk_list_store_append (self->priv->tree_model, &iter);
221 			gtk_list_store_set (self->priv->tree_model, &iter,
222 					    SCALE_SET_COLUMN, FALSE,
223 					    WEIGHT_COLUMN, PANGO_WEIGHT_BOLD,
224 					    ID_COLUMN, category->id,
225 					    DISPLAY_NAME_COLUMN, _(category->display_name),
226 					    POS_COLUMN, category->sort_order * CATEGORY_SIZE,
227 					    -1);
228 			g_hash_table_insert (category_hash, g_strdup (info->category), category);
229 		}
230 
231 		gtk_list_store_append (self->priv->tree_model, &iter);
232 		gtk_list_store_set (self->priv->tree_model,
233 				    &iter,
234 				    SCALE_SET_COLUMN, TRUE,
235 				    WEIGHT_COLUMN, PANGO_WEIGHT_NORMAL,
236 				    ID_COLUMN, info->id,
237 				    DISPLAY_NAME_COLUMN, _(info->display_name),
238 				    VALUE_COLUMN, value,
239 				    TOOLTIP_COLUMN, tooltip,
240 				    POS_COLUMN, (category->sort_order * CATEGORY_SIZE) + info->sort_order,
241 				    -1);
242 
243 		g_free (tooltip);
244 		g_free (value);
245 	}
246 	g_list_free (metadata_info);
247 
248 	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->priv->tree_model), POS_COLUMN, GTK_SORT_ASCENDING);
249 	gtk_tree_view_expand_all (GTK_TREE_VIEW (self->priv->tree_view));
250 
251 	g_hash_table_destroy (category_hash);
252 }
253 
254 
255 static const char *
gth_file_properties_real_get_name(GthPropertyView * self)256 gth_file_properties_real_get_name (GthPropertyView *self)
257 {
258 	return _("Properties");
259 }
260 
261 
262 static const char *
gth_file_properties_real_get_icon(GthPropertyView * self)263 gth_file_properties_real_get_icon (GthPropertyView *self)
264 {
265 	return "document-properties-symbolic";
266 }
267 
268 
269 static void
gth_file_properties_finalize(GObject * base)270 gth_file_properties_finalize (GObject *base)
271 {
272 	GthFileProperties *self;
273 
274 	self = (GthFileProperties *) base;
275 
276 	if (self->priv->popup_menu != NULL)
277 		gtk_widget_destroy (self->priv->popup_menu);
278 	_g_object_unref (self->priv->last_file_data);
279 	_g_object_unref (self->priv->settings);
280 	if (self->priv->favorites != NULL)
281 		g_hash_table_unref (self->priv->favorites);
282 
283 	G_OBJECT_CLASS (gth_file_properties_parent_class)->finalize (base);
284 }
285 
286 
287 static void
update_favorites(GthFileProperties * self)288 update_favorites (GthFileProperties *self)
289 {
290 	char *favorites;
291 
292 	if (self->priv->show_details)
293 		return;
294 
295 	favorites = g_settings_get_string (self->priv->settings, PREF_BROWSER_FAVORITE_PROPERTIES);
296 
297 	if (self->priv->favorites != NULL)
298 		g_hash_table_unref (self->priv->favorites);
299 	self->priv->favorites = _g_str_split_as_hash_table (favorites);
300 	self->priv->default_favorites = _g_str_equal (favorites, "default");
301 
302 	g_free (favorites);
303 }
304 
305 
306 static void
update_context_menu_separator_visibility(GthFileProperties * self)307 update_context_menu_separator_visibility (GthFileProperties *self)
308 {
309 	int n_visible;
310 
311 	n_visible = 0;
312 	if (gtk_widget_get_visible (self->priv->copy_menu_item))
313 		n_visible++;
314 	if (gtk_widget_get_visible (self->priv->edit_favorites_menu_item))
315 		n_visible++;
316 	gtk_widget_set_visible (self->priv->context_menu_sep, n_visible > 1);
317 }
318 
319 
320 static void
gth_file_properties_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)321 gth_file_properties_set_property (GObject      *object,
322 				  guint         property_id,
323 				  const GValue *value,
324 				  GParamSpec   *pspec)
325 {
326 	GthFileProperties *self;
327 
328 	self = GTH_FILE_PROPERTIES (object);
329 
330 	switch (property_id) {
331 	case PROP_SHOW_DETAILS:
332 		self->priv->show_details = g_value_get_boolean (value);
333 		update_favorites (self);
334 		if (self->priv->edit_favorites_menu_item != NULL) {
335 			gtk_widget_set_visible (self->priv->edit_favorites_menu_item, ! self->priv->show_details);
336 			update_context_menu_separator_visibility (self);
337 		}
338 		break;
339 	default:
340 		break;
341 	}
342 }
343 
344 
345 static void
gth_file_properties_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)346 gth_file_properties_get_property (GObject    *object,
347 				  guint       property_id,
348 				  GValue     *value,
349 				  GParamSpec *pspec)
350 {
351 	GthFileProperties *self;
352 
353 	self = GTH_FILE_PROPERTIES (object);
354 
355 	switch (property_id) {
356 	case PROP_SHOW_DETAILS:
357 		g_value_set_boolean (value, self->priv->show_details);
358 		break;
359 	default:
360 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
361 		break;
362 	}
363 }
364 
365 
366 static void
gth_file_properties_class_init(GthFilePropertiesClass * klass)367 gth_file_properties_class_init (GthFilePropertiesClass *klass)
368 {
369 	GObjectClass *object_class;
370 
371 	object_class = G_OBJECT_CLASS (klass);
372 	object_class->set_property = gth_file_properties_set_property;
373 	object_class->get_property = gth_file_properties_get_property;
374 	object_class->finalize = gth_file_properties_finalize;
375 
376 	/* properties */
377 
378 	g_object_class_install_property (object_class,
379 					 PROP_SHOW_DETAILS,
380 					 g_param_spec_boolean ("show-details",
381 							       "Show details",
382 							       "Whether to show all the file properties",
383 							       FALSE,
384 							       G_PARAM_READWRITE));
385 }
386 
387 
388 static void
copy_menu_item_activate_cb(GtkMenuItem * menuitem,gpointer user_data)389 copy_menu_item_activate_cb (GtkMenuItem *menuitem,
390 			    gpointer     user_data)
391 {
392 	GthFileProperties *self = user_data;
393 	GtkTreeModel      *model;
394 	GtkTreeIter        iter;
395 	char              *value;
396 
397 	if (! gtk_tree_selection_get_selected (GTK_TREE_SELECTION (gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->tree_view))), &model, &iter))
398 		return;
399 
400 	gtk_tree_model_get (model, &iter, VALUE_COLUMN, &value, -1);
401 	if (value != NULL)
402 		gtk_clipboard_set_text (gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (menuitem)), GDK_SELECTION_CLIPBOARD),
403 					value,
404 					-1);
405 
406 	g_free (value);
407 }
408 
409 
410 static void
edit_favorites_menu_item_activate_cb(GtkMenuItem * menuitem,gpointer user_data)411 edit_favorites_menu_item_activate_cb (GtkMenuItem *menuitem,
412 				      gpointer     user_data)
413 {
414 	GthFileProperties *self = user_data;
415 	dlg_favorite_properties (GTH_BROWSER (_gtk_widget_get_toplevel_if_window (GTK_WIDGET (self))));
416 }
417 
418 
419 static gboolean
tree_view_button_press_event_cb(GtkWidget * widget,GdkEventButton * event,gpointer user_data)420 tree_view_button_press_event_cb (GtkWidget      *widget,
421 				 GdkEventButton *event,
422 				 gpointer        user_data)
423 {
424 	GthFileProperties *self = user_data;
425 
426 	if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
427 		GtkTreePath *path;
428 		gboolean     path_selected;
429 
430 		path_selected = gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (self->priv->tree_view),
431 			event->x,
432 			event->y,
433 			&path,
434 			NULL,
435 			NULL,
436 			NULL);
437 
438 		gtk_widget_set_visible (self->priv->copy_menu_item, path_selected);
439 		update_context_menu_separator_visibility (self);
440 
441 		if (path != NULL) {
442 			gtk_tree_selection_select_path (GTK_TREE_SELECTION (gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->tree_view))), path);
443 			gtk_tree_path_free (path);
444 		}
445 
446 		gtk_menu_popup_at_pointer (GTK_MENU (self->priv->popup_menu), (GdkEvent *) event);
447 
448 		return TRUE;
449 	}
450 
451 	return FALSE;
452 }
453 
454 
455 static gboolean
tree_view_popup_menu_cb(GtkWidget * widget,gpointer user_data)456 tree_view_popup_menu_cb (GtkWidget *widget,
457 			 gpointer   user_data)
458 {
459 	GthFileProperties *self = user_data;
460 
461 	gtk_widget_set_visible (self->priv->copy_menu_item, TRUE);
462 	update_context_menu_separator_visibility (self);
463 
464 	gtk_menu_popup_at_pointer (GTK_MENU (self->priv->popup_menu), NULL);
465 
466 	return TRUE;
467 }
468 
469 
470 static void
pref_favorite_properties_changed(GSettings * settings,const char * key,gpointer user_data)471 pref_favorite_properties_changed (GSettings  *settings,
472 				  const char *key,
473 				  gpointer    user_data)
474 {
475 	GthFileProperties *self = user_data;
476 
477 	update_favorites (self);
478 	gth_property_view_set_file (GTH_PROPERTY_VIEW (self), self->priv->last_file_data);
479 }
480 
481 
482 static void
gth_file_properties_init(GthFileProperties * self)483 gth_file_properties_init (GthFileProperties *self)
484 {
485 	GtkWidget         *scrolled_win;
486 	GtkWidget         *menu_item;
487 	GtkCellRenderer   *renderer;
488 	GtkTreeViewColumn *column;
489 
490 	self->priv = gth_file_properties_get_instance_private (self);
491 	self->priv->show_details = FALSE;
492 	self->priv->last_file_data = NULL;
493 	self->priv->settings = g_settings_new (GTHUMB_BROWSER_SCHEMA);
494 	self->priv->favorites = NULL;
495 
496 	update_favorites (self);
497 
498 	g_signal_connect (self->priv->settings,
499 			  "changed::" PREF_BROWSER_FAVORITE_PROPERTIES,
500 			  G_CALLBACK (pref_favorite_properties_changed),
501 			  self);
502 
503 	gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL);
504 	gtk_box_set_spacing (GTK_BOX (self), 6);
505 
506 	self->priv->main_container = scrolled_win = gtk_scrolled_window_new (NULL, NULL);
507 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
508 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
509 	gtk_widget_show (scrolled_win);
510 	gtk_widget_set_size_request (scrolled_win, -1, MIN_HEIGHT);
511 	gtk_box_pack_start (GTK_BOX (self), scrolled_win, TRUE, TRUE, 0);
512 
513 	self->priv->tree_view = gtk_tree_view_new ();
514 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (self->priv->tree_view), FALSE);
515 	gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (self->priv->tree_view), TOOLTIP_COLUMN);
516 	self->priv->tree_model = gtk_list_store_new (NUM_COLUMNS,
517 						     G_TYPE_BOOLEAN,
518 						     PANGO_TYPE_WEIGHT,
519 						     G_TYPE_STRING,
520 						     G_TYPE_STRING,
521 						     G_TYPE_STRING,
522 						     G_TYPE_STRING,
523 						     G_TYPE_STRING,
524 						     G_TYPE_INT,
525 						     G_TYPE_BOOLEAN);
526 	gtk_tree_view_set_model (GTK_TREE_VIEW (self->priv->tree_view),
527 				 GTK_TREE_MODEL (self->priv->tree_model));
528 	g_object_unref (self->priv->tree_model);
529 	gtk_widget_show (self->priv->tree_view);
530 	gtk_container_add (GTK_CONTAINER (scrolled_win), self->priv->tree_view);
531 
532 	/* popup menu */
533 
534 	self->priv->popup_menu = gtk_menu_new ();
535 
536 	self->priv->copy_menu_item = menu_item = gtk_menu_item_new_with_label (_GTK_LABEL_COPY);
537 	gtk_widget_show (menu_item);
538 	gtk_menu_shell_append (GTK_MENU_SHELL (self->priv->popup_menu), menu_item);
539 	g_signal_connect (menu_item,
540 			  "activate",
541 			  G_CALLBACK (copy_menu_item_activate_cb),
542 			  self);
543 
544 	self->priv->context_menu_sep = menu_item = gtk_separator_menu_item_new ();
545 	gtk_widget_show (menu_item);
546 	gtk_menu_shell_append (GTK_MENU_SHELL (self->priv->popup_menu), menu_item);
547 
548 	self->priv->edit_favorites_menu_item = menu_item = gtk_menu_item_new_with_label (_("Preferences"));
549 	gtk_widget_set_visible (menu_item, ! self->priv->show_details);
550 	gtk_menu_shell_append (GTK_MENU_SHELL (self->priv->popup_menu), menu_item);
551 	g_signal_connect (menu_item,
552 			  "activate",
553 			  G_CALLBACK (edit_favorites_menu_item_activate_cb),
554 			  self);
555 
556 	update_context_menu_separator_visibility (self);
557 
558 	g_signal_connect (self->priv->tree_view,
559 			  "button-press-event",
560 			  G_CALLBACK (tree_view_button_press_event_cb),
561 			  self);
562 	g_signal_connect (self->priv->tree_view,
563 			  "popup-menu",
564 			  G_CALLBACK (tree_view_popup_menu_cb),
565 			  self);
566 
567 	/**/
568 
569 	renderer = gtk_cell_renderer_text_new ();
570 	column = gtk_tree_view_column_new_with_attributes ("",
571 							   renderer,
572 							   "text", DISPLAY_NAME_COLUMN,
573 							   "scale-set", SCALE_SET_COLUMN,
574 							   "weight", WEIGHT_COLUMN,
575 							   NULL);
576 	g_object_set (renderer,
577 		      "ellipsize", PANGO_ELLIPSIZE_END,
578 		      "scale", FONT_SCALE,
579 		      NULL);
580 
581 	gtk_tree_view_column_set_expand (column, TRUE);
582 	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
583 	gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->tree_view),
584 				     column);
585 
586 	/**/
587 
588 	renderer = gtk_cell_renderer_text_new ();
589 	column = gtk_tree_view_column_new_with_attributes ("",
590 							   renderer,
591 							   "text", VALUE_COLUMN,
592 							   NULL);
593 	g_object_set (renderer,
594 		      "ellipsize", PANGO_ELLIPSIZE_END,
595 		      "scale", FONT_SCALE,
596 		      NULL);
597 
598 	gtk_tree_view_column_set_expand (column, TRUE);
599 	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
600 	gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->tree_view),
601 				     column);
602 
603 	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->priv->tree_model), POS_COLUMN, GTK_SORT_ASCENDING);
604 }
605 
606 
607 static void
gth_file_properties_gth_property_view_interface_init(GthPropertyViewInterface * iface)608 gth_file_properties_gth_property_view_interface_init (GthPropertyViewInterface *iface)
609 {
610 	iface->get_name = gth_file_properties_real_get_name;
611 	iface->get_icon = gth_file_properties_real_get_icon;
612 	iface->can_view = gth_file_properties_real_can_view;
613 	iface->set_file = gth_file_properties_real_set_file;
614 }
615