[gthumb] location chooser: added ability to browse and select a location
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] location chooser: added ability to browse and select a location
- Date: Sun, 24 Nov 2019 12:26:44 +0000 (UTC)
commit 17023e99ea9e39fb91a34106751096f977cbe21b
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sat Nov 2 08:04:11 2019 +0100
location chooser: added ability to browse and select a location
gthumb/gth-location-chooser-dialog.c | 241 ++++++++++++
gthumb/gth-location-chooser-dialog.h | 59 +++
gthumb/gth-location-chooser.c | 192 ++++++---
gthumb/gth-vfs-tree.c | 727 +++++++++++++++++++++++++++++++++++
gthumb/gth-vfs-tree.h | 67 ++++
gthumb/meson.build | 4 +
6 files changed, 1241 insertions(+), 49 deletions(-)
---
diff --git a/gthumb/gth-location-chooser-dialog.c b/gthumb/gth-location-chooser-dialog.c
new file mode 100644
index 00000000..7dd7b4ff
--- /dev/null
+++ b/gthumb/gth-location-chooser-dialog.c
@@ -0,0 +1,241 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2019 The Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include "glib-utils.h"
+#include "gtk-utils.h"
+#include "gth-file-data.h"
+#include "gth-vfs-tree.h"
+#include "gth-location-chooser.h"
+#include "gth-location-chooser-dialog.h"
+#include "gth-main.h"
+
+
+#define MIN_WIDTH 600
+#define MIN_HEIGHT 600
+
+
+struct _GthLocationChooserDialogPrivate {
+ GFile *folder;
+ GtkWidget *folder_tree;
+ GtkWidget *entry;
+ gulong entry_changed_id;
+};
+
+
+G_DEFINE_TYPE_WITH_CODE (GthLocationChooserDialog,
+ gth_location_chooser_dialog,
+ GTK_TYPE_DIALOG,
+ G_ADD_PRIVATE (GthLocationChooserDialog))
+
+
+static void
+gth_location_chooser_dialog_finalize (GObject *object)
+{
+ GthLocationChooserDialog *self;
+
+ self = GTH_LOCATION_CHOOSER_DIALOG (object);
+
+ _g_object_unref (self->priv->folder);
+
+ G_OBJECT_CLASS (gth_location_chooser_dialog_parent_class)->finalize (object);
+}
+
+
+static void
+gth_location_chooser_dialog_class_init (GthLocationChooserDialogClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = (GObjectClass*) class;
+ object_class->finalize = gth_location_chooser_dialog_finalize;
+}
+
+
+static void
+gth_location_chooser_dialog_init (GthLocationChooserDialog *self)
+{
+ self->priv = gth_location_chooser_dialog_get_instance_private (self);
+ self->priv->folder = NULL;
+ self->priv->entry_changed_id = 0;
+}
+
+
+static void
+_set_folder (GthLocationChooserDialog *self,
+ GFile *folder)
+{
+ if (self->priv->folder != folder) {
+ _g_object_unref (self->priv->folder);
+ self->priv->folder = _g_object_ref (folder);
+ }
+
+ if (self->priv->folder != NULL) {
+ g_signal_handler_block (self->priv->entry, self->priv->entry_changed_id);
+ gth_location_chooser_set_current (GTH_LOCATION_CHOOSER (self->priv->entry),
self->priv->folder);
+ g_signal_handler_unblock (self->priv->entry, self->priv->entry_changed_id);
+ }
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (self), GTK_RESPONSE_OK, (self->priv->folder != NULL));
+}
+
+
+static void
+folder_tree_changed_cb (GthVfsTree *tree,
+ gpointer user_data)
+{
+ GthLocationChooserDialog *self = user_data;
+ _set_folder (self, gth_vfs_tree_get_folder (tree));
+}
+
+
+static void
+location_entry_changed_cb (GthLocationChooser *entry,
+ gpointer user_data)
+{
+ GthLocationChooserDialog *self = user_data;
+ GFile *folder;
+
+ folder = gth_location_chooser_get_current (entry);
+ if (_g_file_equal_uris (folder, gth_folder_tree_get_root (GTH_FOLDER_TREE
(self->priv->folder_tree)))) {
+ gtk_tree_view_collapse_all (GTK_TREE_VIEW (self->priv->folder_tree));
+ _set_folder (self, NULL);
+ }
+ else
+ gth_location_chooser_dialog_set_folder (self, folder);
+}
+
+
+static void
+hidden_files_toggled_cb (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ GthLocationChooserDialog *self = user_data;
+
+ gth_vfs_tree_set_show_hidden (GTH_VFS_TREE (self->priv->folder_tree), gtk_toggle_button_get_active
(togglebutton));
+}
+
+
+static void
+_gth_location_chooser_dialog_construct (GthLocationChooserDialog *self)
+{
+ GtkWidget *vbox;
+ GtkWidget *scrolled_window;
+ GtkWidget *check_button;
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ gtk_widget_show (vbox);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), vbox, TRUE, TRUE, 0);
+
+ self->priv->entry = g_object_new (GTH_TYPE_LOCATION_CHOOSER,
+ "show-entry-points", FALSE,
+ "show-root", TRUE,
+ NULL);
+ self->priv->entry_changed_id =
+ g_signal_connect (self->priv->entry,
+ "changed",
+ G_CALLBACK (location_entry_changed_cb),
+ self);
+
+ gtk_widget_show (self->priv->entry);
+ gtk_box_pack_start (GTK_BOX (vbox), self->priv->entry, FALSE, FALSE, 0);
+
+ gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), 5);
+ gtk_container_set_border_width (GTK_CONTAINER (self), 5);
+
+ _gtk_dialog_add_to_window_group (GTK_DIALOG (self));
+
+ gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_OK, GTK_RESPONSE_OK);
+ gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+ _gtk_dialog_add_class_to_response (GTK_DIALOG (self), GTK_RESPONSE_OK,
GTK_STYLE_CLASS_SUGGESTED_ACTION);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (self), GTK_RESPONSE_OK, FALSE);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_SHADOW_IN);
+ gtk_widget_set_size_request (scrolled_window, MIN_WIDTH, MIN_HEIGHT);
+ gtk_widget_show (scrolled_window);
+
+ self->priv->folder_tree = gth_vfs_tree_new (NULL);
+ g_signal_connect (self->priv->folder_tree,
+ "changed",
+ G_CALLBACK (folder_tree_changed_cb),
+ self);
+ gtk_widget_show (self->priv->folder_tree);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), self->priv->folder_tree);
+ gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
+
+ check_button = gtk_check_button_new_with_label (_("Hidden Files"));
+ g_signal_connect (check_button,
+ "toggled",
+ G_CALLBACK (hidden_files_toggled_cb),
+ self);
+ gtk_widget_show (check_button);
+ gtk_box_pack_start (GTK_BOX (vbox), check_button, TRUE, TRUE, 0);
+
+ _set_folder (self, NULL);
+}
+
+
+GtkWidget *
+gth_location_chooser_dialog_new (const char *title,
+ GtkWindow *parent)
+{
+ GthLocationChooserDialog *self;
+
+ self = g_object_new (GTH_TYPE_LOCATION_CHOOSER_DIALOG,
+ "title", title,
+ "transient-for", parent,
+ "modal", TRUE,
+ "resizable", TRUE,
+ "use-header-bar", _gtk_settings_get_dialogs_use_header (),
+ NULL);
+ _gth_location_chooser_dialog_construct (self);
+
+ return (GtkWidget *) self;
+}
+
+
+void
+gth_location_chooser_dialog_set_folder (GthLocationChooserDialog *self,
+ GFile *folder)
+{
+ g_return_if_fail (GTH_IS_LOCATION_CHOOSER_DIALOG (self));
+ g_return_if_fail (folder != NULL);
+
+ gth_vfs_tree_set_folder (GTH_VFS_TREE (self->priv->folder_tree), folder);
+}
+
+
+GFile *
+gth_location_chooser_dialog_get_folder (GthLocationChooserDialog *self)
+{
+ g_return_val_if_fail (GTH_IS_LOCATION_CHOOSER_DIALOG (self), NULL);
+
+ return self->priv->folder;
+}
diff --git a/gthumb/gth-location-chooser-dialog.h b/gthumb/gth-location-chooser-dialog.h
new file mode 100644
index 00000000..b06cc296
--- /dev/null
+++ b/gthumb/gth-location-chooser-dialog.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2019 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_LOCATION_CHOOSER_DIALOG_H
+#define GTH_LOCATION_CHOOSER_DIALOG_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_LOCATION_CHOOSER_DIALOG (gth_location_chooser_dialog_get_type ())
+#define GTH_LOCATION_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o),
GTH_TYPE_LOCATION_CHOOSER_DIALOG, GthLocationChooserDialog))
+#define GTH_LOCATION_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k),
GTH_TYPE_LOCATION_CHOOSER_DIALOG, GthLocationChooserDialogClass))
+#define GTH_IS_LOCATION_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o),
GTH_TYPE_LOCATION_CHOOSER_DIALOG))
+#define GTH_IS_LOCATION_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k),
GTH_TYPE_LOCATION_CHOOSER_DIALOG))
+#define GTH_LOCATION_CHOOSER_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o),
GTH_TYPE_LOCATION_CHOOSER_DIALOG, GthLocationChooserDialogClass))
+
+typedef struct _GthLocationChooserDialog GthLocationChooserDialog;
+typedef struct _GthLocationChooserDialogPrivate GthLocationChooserDialogPrivate;
+typedef struct _GthLocationChooserDialogClass GthLocationChooserDialogClass;
+
+struct _GthLocationChooserDialog {
+ GtkDialog __parent;
+ GthLocationChooserDialogPrivate *priv;
+};
+
+struct _GthLocationChooserDialogClass {
+ GtkDialogClass __parent_class;
+};
+
+GType gth_location_chooser_dialog_get_type (void) G_GNUC_CONST;
+GtkWidget * gth_location_chooser_dialog_new (const char *title,
+ GtkWindow *parent);
+void gth_location_chooser_dialog_set_folder (GthLocationChooserDialog *self,
+ GFile *folder);
+GFile * gth_location_chooser_dialog_get_folder (GthLocationChooserDialog *self);
+
+G_END_DECLS
+
+#endif /* GTH_LOCATION_CHOOSER_DIALOG_H */
diff --git a/gthumb/gth-location-chooser.c b/gthumb/gth-location-chooser.c
index 2a8dd412..fa470a18 100644
--- a/gthumb/gth-location-chooser.c
+++ b/gthumb/gth-location-chooser.c
@@ -28,6 +28,7 @@
#include "glib-utils.h"
#include "gth-file-source.h"
#include "gth-location-chooser.h"
+#include "gth-location-chooser-dialog.h"
#include "gth-main.h"
#include "gtk-utils.h"
#include "pixbuf-utils.h"
@@ -40,7 +41,8 @@ enum {
ITEM_TYPE_NONE,
ITEM_TYPE_SEPARATOR,
ITEM_TYPE_LOCATION,
- ITEM_TYPE_ENTRY_POINT
+ ITEM_TYPE_ENTRY_POINT,
+ ITEM_TYPE_CHOOSE_LOCATION
};
enum {
@@ -55,6 +57,7 @@ enum {
enum {
PROP_0,
PROP_SHOW_ENTRY_POINTS,
+ PROP_SHOW_ROOT,
PROP_RELIEF
};
@@ -73,6 +76,7 @@ struct _GthLocationChooserPrivate {
guint update_entry_list_id;
guint update_location_list_id;
gboolean show_entry_points;
+ gboolean show_root;
GtkReliefStyle relief;
gboolean reload;
};
@@ -101,6 +105,9 @@ gth_location_chooser_set_property (GObject *object,
case PROP_SHOW_ENTRY_POINTS:
gth_location_chooser_set_show_entry_points (self, g_value_get_boolean (value));
break;
+ case PROP_SHOW_ROOT:
+ self->priv->show_root = g_value_get_boolean (value);
+ break;
case PROP_RELIEF:
gth_location_chooser_set_relief (self, g_value_get_enum (value));
break;
@@ -124,6 +131,9 @@ gth_location_chooser_get_property (GObject *object,
case PROP_SHOW_ENTRY_POINTS:
g_value_set_boolean (value, self->priv->show_entry_points);
break;
+ case PROP_SHOW_ROOT:
+ g_value_set_boolean (value, self->priv->show_root);
+ break;
case PROP_RELIEF:
g_value_set_enum (value, self->priv->relief);
break;
@@ -193,6 +203,44 @@ get_nth_separator_pos (GthLocationChooser *self,
}
+static gboolean
+get_iter_from_current_file_entries (GthLocationChooser *self,
+ GFile *file,
+ GtkTreeIter *iter)
+{
+ gboolean found = FALSE;
+ char *uri;
+
+ if (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->model), iter))
+ return FALSE;
+
+ uri = g_file_get_uri (file);
+ do {
+ int item_type = ITEM_TYPE_NONE;
+ char *list_uri;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->priv->model),
+ iter,
+ TYPE_COLUMN, &item_type,
+ URI_COLUMN, &list_uri,
+ -1);
+ if (item_type == ITEM_TYPE_SEPARATOR)
+ break;
+ if (same_uri (uri, list_uri)) {
+ found = TRUE;
+ g_free (list_uri);
+ break;
+ }
+ g_free (list_uri);
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->model), iter));
+
+ g_free (uri);
+
+ return found;
+}
+
+
static void
combo_changed_cb (GtkComboBox *widget,
gpointer user_data)
@@ -211,7 +259,27 @@ combo_changed_cb (GtkComboBox *widget,
URI_COLUMN, &uri,
-1);
- if (uri != NULL) {
+ if (item_type == ITEM_TYPE_CHOOSE_LOCATION) {
+ GtkWidget *dialog;
+
+ dialog = gth_location_chooser_dialog_new (_("Location"), _gtk_widget_get_toplevel_if_window
(GTK_WIDGET (widget)));
+ if (self->priv->location != NULL)
+ gth_location_chooser_dialog_set_folder (GTH_LOCATION_CHOOSER_DIALOG (dialog),
self->priv->location);
+
+ switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
+ case GTK_RESPONSE_OK:
+ gth_location_chooser_set_current (self, gth_location_chooser_dialog_get_folder
(GTH_LOCATION_CHOOSER_DIALOG (dialog)));
+ break;
+
+ default:
+ /* reset the previous value. */
+ gth_location_chooser_set_current (self, self->priv->location);
+ break;
+ }
+
+ gtk_widget_destroy (dialog);
+ }
+ else if (uri != NULL) {
GFile *file;
file = g_file_new_for_uri (uri);
@@ -256,12 +324,14 @@ add_file_source_entries (GthLocationChooser *self,
static void
-clear_entry_point_list (GthLocationChooser *self)
+clear_items_from_separator (GthLocationChooser *self,
+ int nth_separator,
+ gboolean stop_at_next_separator)
{
int first_position;
int i;
- if (! get_nth_separator_pos (self, 1, &first_position))
+ if (! get_nth_separator_pos (self, nth_separator, &first_position))
return;
for (i = first_position + 1; TRUE; i++) {
@@ -269,8 +339,19 @@ clear_entry_point_list (GthLocationChooser *self)
GtkTreeIter iter;
path = gtk_tree_path_new_from_indices (first_position + 1, -1);
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (self->priv->model), &iter, path))
+ if (gtk_tree_model_get_iter (GTK_TREE_MODEL (self->priv->model), &iter, path)) {
+ if (stop_at_next_separator) {
+ int item_type = ITEM_TYPE_NONE;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->priv->model),
+ &iter,
+ TYPE_COLUMN, &item_type,
+ -1);
+ if (item_type == ITEM_TYPE_SEPARATOR)
+ break;
+ }
gtk_tree_store_remove (self->priv->model, &iter);
+ }
else
break;
@@ -279,6 +360,13 @@ clear_entry_point_list (GthLocationChooser *self)
}
+static void
+clear_entry_point_list (GthLocationChooser *self)
+{
+ clear_items_from_separator (self, 1, TRUE);
+}
+
+
static void
update_entry_point_list (GthLocationChooser *self)
{
@@ -322,6 +410,22 @@ update_entry_point_list (GthLocationChooser *self)
ITEM_TYPE_ENTRY_POINT);
}
+ if (! get_nth_separator_pos (self, 2, &first_position)) {
+ GtkTreeIter iter;
+
+ gtk_tree_store_append (self->priv->model, &iter, NULL);
+ gtk_tree_store_set (self->priv->model, &iter,
+ TYPE_COLUMN, ITEM_TYPE_SEPARATOR,
+ -1);
+
+ gtk_tree_store_append (self->priv->model, &iter, NULL);
+ gtk_tree_store_set (self->priv->model, &iter,
+ TYPE_COLUMN, ITEM_TYPE_CHOOSE_LOCATION,
+ NAME_COLUMN, _("Other…"),
+ ELLIPSIZE_COLUMN, FALSE,
+ -1);
+ }
+
_g_object_list_unref (entry_points);
}
@@ -379,44 +483,6 @@ delete_current_file_entries (GthLocationChooser *self)
}
-static gboolean
-get_iter_from_current_file_entries (GthLocationChooser *self,
- GFile *file,
- GtkTreeIter *iter)
-{
- gboolean found = FALSE;
- char *uri;
-
- if (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->model), iter))
- return FALSE;
-
- uri = g_file_get_uri (file);
- do {
- int item_type = ITEM_TYPE_NONE;
- char *list_uri;
-
- gtk_tree_model_get (GTK_TREE_MODEL (self->priv->model),
- iter,
- TYPE_COLUMN, &item_type,
- URI_COLUMN, &list_uri,
- -1);
- if (item_type == ITEM_TYPE_SEPARATOR)
- break;
- if (same_uri (uri, list_uri)) {
- found = TRUE;
- g_free (list_uri);
- break;
- }
- g_free (list_uri);
- }
- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->model), iter));
-
- g_free (uri);
-
- return found;
-}
-
-
static void
update_location_list (gpointer user_data)
{
@@ -459,6 +525,24 @@ update_location_list (gpointer user_data)
g_object_unref (info);
}
+ if (self->priv->show_root) {
+ GIcon *icon;
+
+ icon = g_themed_icon_new ("computer-symbolic");
+ gtk_tree_store_insert (self->priv->model,
+ &iter,
+ NULL,
+ position++);
+ gtk_tree_store_set (self->priv->model, &iter,
+ TYPE_COLUMN, ITEM_TYPE_LOCATION,
+ ICON_COLUMN, icon,
+ NAME_COLUMN, _("Locations"),
+ URI_COLUMN, "gthumb-vfs:///",
+ -1);
+
+ _g_object_unref (icon);
+ }
+
_g_object_list_unref (list);
}
@@ -505,11 +589,17 @@ gth_location_chooser_class_init (GthLocationChooserClass *klass)
g_object_class_install_property (object_class,
PROP_SHOW_ENTRY_POINTS,
g_param_spec_boolean ("show-entry-points",
- "Show entry points",
- "Whether to show the entry points in the
list",
- TRUE,
- G_PARAM_READWRITE));
-
+ "Show entry points",
+ "Whether to show the entry points in the list",
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_SHOW_ROOT,
+ g_param_spec_boolean ("show-root",
+ "Show the VFS root",
+ "Whether to show the VFS root in the list",
+ FALSE,
+ G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_RELIEF,
g_param_spec_enum ("relief",
@@ -544,6 +634,7 @@ gth_location_chooser_init (GthLocationChooser *self)
self->priv = gth_location_chooser_get_instance_private (self);
self->priv->entry_points_changed_id = 0;
self->priv->show_entry_points = TRUE;
+ self->priv->show_root = FALSE;
self->priv->relief = GTK_RELIEF_NORMAL;
self->priv->reload = FALSE;
@@ -647,7 +738,7 @@ gth_location_chooser_set_show_entry_points (GthLocationChooser *self,
g_source_remove (self->priv->entry_points_changed_id);
self->priv->entry_points_changed_id = 0;
}
- clear_entry_point_list (self);
+ clear_items_from_separator (self, 1, FALSE);
}
g_object_notify (G_OBJECT (self), "show-entry-points");
@@ -665,6 +756,9 @@ void
gth_location_chooser_set_current (GthLocationChooser *self,
GFile *file)
{
+ if (file == NULL)
+ return;
+
if (file != self->priv->location) {
if (self->priv->file_source != NULL)
g_object_unref (self->priv->file_source);
diff --git a/gthumb/gth-vfs-tree.c b/gthumb/gth-vfs-tree.c
new file mode 100644
index 00000000..b545da75
--- /dev/null
+++ b/gthumb/gth-vfs-tree.c
@@ -0,0 +1,727 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2019 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include "glib-utils.h"
+#include "gtk-utils.h"
+#include "gth-main.h"
+#include "gth-vfs-tree.h"
+
+
+enum {
+ PROP_0,
+ PROP_SHOW_HIDDEN
+};
+
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+
+struct _GthVfsTreePrivate {
+ GFile *folder;
+ gulong monitor_folder_changed_id;
+ gulong monitor_file_renamed_id;
+ gboolean show_hidden;
+};
+
+
+static guint gth_vfs_tree_signals[LAST_SIGNAL] = { 0 };
+
+
+G_DEFINE_TYPE_WITH_CODE (GthVfsTree,
+ gth_vfs_tree,
+ GTH_TYPE_FOLDER_TREE,
+ G_ADD_PRIVATE (GthVfsTree))
+
+
+static void
+_gth_vfs_tree_update_entry_points (GthVfsTree *self)
+{
+ GList *entry_points;
+ GFile *root;
+
+ entry_points = gth_main_get_all_entry_points ();
+ root = g_file_new_for_uri ("gthumb-vfs:///");
+ gth_folder_tree_set_children (GTH_FOLDER_TREE (self), root, entry_points);
+
+ g_object_unref (root);
+ _g_object_list_unref (entry_points);
+}
+
+
+/* -- load_data-- */
+
+
+typedef enum {
+ LOAD_ACTION_LOAD,
+ LOAD_ACTION_LIST_CHILDREN
+} LoadAction;
+
+
+typedef struct {
+ GthVfsTree *vfs_tree;
+ LoadAction action;
+ GthFileData *requested_folder;
+ GFile *entry_point;
+ GthFileSource *file_source;
+ GCancellable *cancellable;
+ GList *list;
+ GList *current;
+ guint destroy_id;
+} LoadData;
+
+
+static void
+load_data_vfs_tree_destroy_cb (GtkWidget *widget,
+ gpointer user_data)
+{
+ LoadData *load_data = user_data;
+
+ gth_file_source_cancel (load_data->file_source);
+ g_cancellable_cancel (load_data->cancellable);
+}
+
+
+static LoadData *
+load_data_new (GthVfsTree *vfs_tree,
+ LoadAction action,
+ GFile *location)
+{
+ LoadData *load_data;
+ GFile *file;
+
+ load_data = g_new0 (LoadData, 1);
+ load_data->vfs_tree = g_object_ref (vfs_tree);
+ load_data->action = action;
+ load_data->requested_folder = gth_file_data_new (location, NULL);
+ load_data->entry_point = gth_main_get_nearest_entry_point (location);
+ load_data->file_source = gth_main_get_file_source (load_data->requested_folder->file);
+ load_data->cancellable = g_cancellable_new ();
+ load_data->list = NULL;
+ load_data->current = NULL;
+ load_data->destroy_id =
+ g_signal_connect (load_data->vfs_tree,
+ "destroy",
+ G_CALLBACK (load_data_vfs_tree_destroy_cb),
+ load_data);
+
+ if (load_data->entry_point == NULL)
+ return load_data;
+
+ file = g_object_ref (load_data->requested_folder->file);
+ load_data->list = g_list_prepend (NULL, g_object_ref (file));
+ while (! g_file_equal (load_data->entry_point, file)) {
+ GFile *parent;
+
+ parent = g_file_get_parent (file);
+ g_object_unref (file);
+ file = parent;
+
+ load_data->list = g_list_prepend (load_data->list, g_object_ref (file));
+ }
+ g_object_unref (file);
+ load_data->current = NULL;
+
+ return load_data;
+}
+
+
+static void
+load_data_free (LoadData *data)
+{
+ g_signal_handler_disconnect (data->vfs_tree, data->destroy_id);
+ _g_object_list_unref (data->list);
+ g_object_unref (data->cancellable);
+ _g_object_unref (data->file_source);
+ _g_object_unref (data->entry_point);
+ g_object_unref (data->requested_folder);
+ _g_object_unref (data->vfs_tree);
+ g_free (data);
+}
+
+
+static void load_data_load_next_folder (LoadData *load_data);
+
+
+static GList *
+_get_visible_files (GthVfsTree *self,
+ GList *list)
+{
+ GList *visible_list = NULL;
+ GList *scan;
+
+ for (scan = list; scan; scan = scan->next) {
+ GthFileData *file_data = scan->data;
+
+ if (self->priv->show_hidden || ! g_file_info_get_is_hidden (file_data->info))
+ visible_list = g_list_prepend (visible_list, g_object_ref (file_data));
+ }
+
+ return g_list_reverse (visible_list);
+}
+
+
+static void
+load_data_ready_cb (GthFileSource *file_source,
+ GList *files,
+ GError *error,
+ gpointer user_data)
+{
+ LoadData *load_data = user_data;
+ GthVfsTree *self = load_data->vfs_tree;
+ GFile *loaded_folder;
+ GtkTreePath *path;
+ GList *visible_files;
+
+ if (error != NULL) {
+ /* TODO */
+ load_data_free (load_data);
+ return;
+ }
+
+ loaded_folder = (GFile *) load_data->current->data;
+ path = gth_folder_tree_get_path (GTH_FOLDER_TREE (self), loaded_folder);
+ if (path == NULL) {
+ load_data_free (load_data);
+ return;
+ }
+
+ visible_files = _get_visible_files (self, files);
+ gth_folder_tree_set_children (GTH_FOLDER_TREE (self),
+ loaded_folder,
+ visible_files);
+ gth_folder_tree_expand_row (GTH_FOLDER_TREE (self), path, FALSE);
+
+ if (! g_file_equal (loaded_folder, load_data->requested_folder->file)) {
+ load_data_load_next_folder (load_data);
+ }
+ else {
+ gth_folder_tree_select_path (GTH_FOLDER_TREE (self), path);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (self),
+ path,
+ NULL,
+ g_file_equal (load_data->entry_point,
load_data->requested_folder->file),
+ 0,
+ 0);
+
+ if (load_data->action == LOAD_ACTION_LOAD) {
+ _g_object_unref (self->priv->folder);
+ self->priv->folder = g_object_ref (loaded_folder);
+
+ g_signal_emit (self, gth_vfs_tree_signals[CHANGED], 0);
+ }
+
+ load_data_free (load_data);
+ }
+
+ _g_object_list_unref (visible_files);
+ gtk_tree_path_free (path);
+}
+
+
+static void
+load_data_load_next_folder (LoadData *load_data)
+{
+ GthFolderTree *folder_tree = GTH_FOLDER_TREE (load_data->vfs_tree);
+ GFile *folder_to_load = NULL;
+
+ do {
+ GtkTreePath *path;
+
+ if (load_data->current == NULL)
+ load_data->current = load_data->list;
+ else
+ load_data->current = load_data->current->next;
+ folder_to_load = (GFile *) load_data->current->data;
+
+ if (g_file_equal (folder_to_load, load_data->requested_folder->file))
+ break;
+
+ path = gth_folder_tree_get_path (folder_tree, folder_to_load);
+ if (path == NULL)
+ break;
+
+ if (! gth_folder_tree_is_loaded (folder_tree, path)) {
+ gtk_tree_path_free (path);
+ break;
+ }
+
+ gth_folder_tree_expand_row (folder_tree, path, FALSE);
+
+ gtk_tree_path_free (path);
+ }
+ while (TRUE);
+
+ if (folder_to_load == NULL) {
+ load_data_free (load_data);
+ return;
+ }
+
+ gth_folder_tree_loading_children (folder_tree, folder_to_load);
+ gth_file_source_list (load_data->file_source,
+ folder_to_load,
+ GFILE_STANDARD_ATTRIBUTES_WITH_FAST_CONTENT_TYPE,
+ load_data_ready_cb,
+ load_data);
+}
+
+
+static void
+_gth_vfs_tree_load_folder (GthVfsTree *self,
+ LoadAction action,
+ GFile *folder);
+
+
+static void
+mount_volume_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ LoadData *load_data = user_data;
+ GError *error = NULL;
+
+ if (! g_file_mount_enclosing_volume_finish (G_FILE (source_object), result, &error)) {
+ /*char *title;
+
+ title = file_format (_("Could not load the position “%s”"),
load_data->requested_folder->file);
+ _gth_browser_show_error (load_data->browser, title, error);
+ g_clear_error (&error);
+
+ g_free (title);*/
+ /* TODO: emit signal ? */
+ load_data_free (load_data);
+ return;
+ }
+
+ /* update the entry points list */
+
+ gth_monitor_entry_points_changed (gth_main_get_default_monitor());
+ _gth_vfs_tree_update_entry_points (load_data->vfs_tree);
+
+ /* try to load again */
+
+ _gth_vfs_tree_load_folder (load_data->vfs_tree,
+ load_data->action,
+ load_data->requested_folder->file);
+
+ load_data_free (load_data);
+}
+
+
+static void
+_gth_vfs_tree_load_folder (GthVfsTree *self,
+ LoadAction action,
+ GFile *folder)
+{
+ LoadData *load_data;
+
+ load_data = load_data_new (self, action, folder);
+
+ if (load_data->entry_point == NULL) {
+ GMountOperation *mount_op;
+
+ /* try to mount the enclosing volume */
+
+ mount_op = gtk_mount_operation_new (_gtk_widget_get_toplevel_if_window (GTK_WIDGET (self)));
+ g_file_mount_enclosing_volume (folder,
+ 0,
+ mount_op,
+ load_data->cancellable,
+ mount_volume_ready_cb,
+ load_data);
+
+ g_object_unref (mount_op);
+
+ return;
+ }
+
+ load_data_load_next_folder (load_data);
+}
+
+
+static void
+vfs_tree_list_children_cb (GthFolderTree *folder_tree,
+ GFile *file,
+ gpointer user_data)
+{
+ GthVfsTree *self = user_data;
+ GtkTreePath *path;
+
+ path = gth_folder_tree_get_path (GTH_FOLDER_TREE (self), file);
+ if (path == NULL)
+ return;
+
+ _gth_vfs_tree_load_folder (self, LOAD_ACTION_LIST_CHILDREN, file);
+
+ gtk_tree_path_free (path);
+}
+
+
+static void
+vfs_tree_open_cb (GthFolderTree *folder_tree,
+ GFile *file,
+ gpointer user_data)
+{
+ GthVfsTree *self = user_data;
+ GtkTreePath *path;
+
+ path = gth_folder_tree_get_path (GTH_FOLDER_TREE (self), file);
+ if (path == NULL)
+ return;
+
+ _gth_vfs_tree_load_folder (self, LOAD_ACTION_LOAD, file);
+
+ gtk_tree_path_free (path);
+}
+
+
+/* -- monitor_event_data -- */
+
+
+typedef struct {
+ int ref;
+ GthVfsTree *vfs_tree;
+ GFile *parent;
+ GthMonitorEvent event;
+ GthFileSource *file_source;
+ guint destroy_id;
+} MonitorEventData;
+
+
+static void
+monitor_data_vfs_tree_destroy_cb (GtkWidget *widget,
+ gpointer user_data)
+{
+ MonitorEventData *monitor_data = user_data;
+
+ gth_file_source_cancel (monitor_data->file_source);
+}
+
+
+static MonitorEventData *
+monitor_event_data_new (GthVfsTree *vfs_tree)
+{
+ MonitorEventData *monitor_data;
+
+ monitor_data = g_new0 (MonitorEventData, 1);
+ monitor_data->ref = 1;
+ monitor_data->vfs_tree = _g_object_ref (vfs_tree);
+ monitor_data->parent = NULL;
+ monitor_data->file_source = NULL;
+ monitor_data->destroy_id =
+ g_signal_connect (monitor_data->vfs_tree,
+ "destroy",
+ G_CALLBACK (monitor_data_vfs_tree_destroy_cb),
+ monitor_data);
+
+ return monitor_data;
+}
+
+
+G_GNUC_UNUSED
+static MonitorEventData *
+monitor_event_data_ref (MonitorEventData *monitor_data)
+{
+ monitor_data->ref++;
+ return monitor_data;
+}
+
+
+static void
+monitor_event_data_unref (MonitorEventData *monitor_data)
+{
+ monitor_data->ref--;
+
+ if (monitor_data->ref > 0)
+ return;
+
+ g_signal_handler_disconnect (monitor_data->vfs_tree, monitor_data->destroy_id);
+ _g_object_unref (monitor_data->vfs_tree);
+ _g_object_unref (monitor_data->parent);
+ _g_object_unref (monitor_data->file_source);
+ g_free (monitor_data);
+}
+
+
+static void
+file_attributes_ready_cb (GthFileSource *file_source,
+ GList *files,
+ GError *error,
+ gpointer user_data)
+{
+ MonitorEventData *monitor_data = user_data;
+ GthVfsTree *self = monitor_data->vfs_tree;
+
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_clear_error (&error);
+ monitor_event_data_unref (monitor_data);
+ return;
+ }
+
+ if (monitor_data->event == GTH_MONITOR_EVENT_CREATED)
+ gth_folder_tree_add_children (GTH_FOLDER_TREE (self), monitor_data->parent, files);
+ else if (monitor_data->event == GTH_MONITOR_EVENT_CHANGED)
+ gth_folder_tree_update_children (GTH_FOLDER_TREE (self), monitor_data->parent, files);
+
+ monitor_event_data_unref (monitor_data);
+}
+
+
+static void
+monitor_folder_changed_cb (GthMonitor *monitor,
+ GFile *parent,
+ GList *list,
+ int position,
+ GthMonitorEvent event,
+ GthVfsTree *self)
+{
+ GtkTreePath *path;
+
+ path = gth_folder_tree_get_path (GTH_FOLDER_TREE (self), parent);
+ if (g_file_equal (parent, gth_folder_tree_get_root (GTH_FOLDER_TREE (self)))
+ || ((path != NULL) && gtk_tree_view_row_expanded (GTK_TREE_VIEW (self), path)))
+ {
+ MonitorEventData *monitor_data;
+
+ switch (event) {
+ case GTH_MONITOR_EVENT_CREATED:
+ case GTH_MONITOR_EVENT_CHANGED:
+ monitor_data = monitor_event_data_new (self);
+ monitor_data->parent = g_file_dup (parent);
+ monitor_data->event = event;
+ monitor_data->file_source = gth_main_get_file_source (monitor_data->parent);
+ gth_file_source_read_attributes (monitor_data->file_source,
+ list,
+ GFILE_STANDARD_ATTRIBUTES_WITH_FAST_CONTENT_TYPE,
+ file_attributes_ready_cb,
+ monitor_data);
+ break;
+
+ case GTH_MONITOR_EVENT_DELETED:
+ case GTH_MONITOR_EVENT_REMOVED:
+ gth_folder_tree_delete_children (GTH_FOLDER_TREE (self), parent, list);
+ break;
+ }
+ }
+
+ gtk_tree_path_free (path);
+}
+
+
+static void
+monitor_file_renamed_cb (GthMonitor *monitor,
+ GFile *file,
+ GFile *new_file,
+ GthVfsTree *self)
+{
+ GthFileSource *file_source;
+
+ file_source = gth_main_get_file_source (new_file);
+ if (file_source != NULL) {
+ GFileInfo *info;
+
+ info = gth_file_source_get_file_info (file_source, new_file, GFILE_BASIC_ATTRIBUTES);
+ if (info != NULL) {
+ GthFileData *file_data;
+
+ file_data = gth_file_data_new (new_file, info);
+ gth_folder_tree_update_child (GTH_FOLDER_TREE (self), file, file_data);
+
+ g_object_unref (file_data);
+ }
+
+ _g_object_unref (info);
+ }
+
+ _g_object_unref (file_source);
+}
+
+
+static void
+gth_vfs_tree_init (GthVfsTree *self)
+{
+ self->priv = gth_vfs_tree_get_instance_private (self);
+ self->priv->folder = NULL;
+
+ g_signal_connect (self,
+ "list_children",
+ G_CALLBACK (vfs_tree_list_children_cb),
+ self);
+ g_signal_connect (self,
+ "open",
+ G_CALLBACK (vfs_tree_open_cb),
+ self);
+
+ self->priv->monitor_folder_changed_id =
+ g_signal_connect (gth_main_get_default_monitor (),
+ "folder-changed",
+ G_CALLBACK (monitor_folder_changed_cb),
+ self);
+ self->priv->monitor_file_renamed_id =
+ g_signal_connect (gth_main_get_default_monitor (),
+ "file-renamed",
+ G_CALLBACK (monitor_file_renamed_cb),
+ self);
+
+ _gth_vfs_tree_update_entry_points (self);
+}
+
+
+static void
+gth_vfs_tree_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GthVfsTree *self;
+
+ self = GTH_VFS_TREE (object);
+
+ switch (property_id) {
+ case PROP_SHOW_HIDDEN:
+ self->priv->show_hidden = g_value_get_boolean (value);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+static void
+gth_vfs_tree_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GthVfsTree *self;
+
+ self = GTH_VFS_TREE (object);
+
+ switch (property_id) {
+ case PROP_SHOW_HIDDEN:
+ g_value_set_boolean (value, self->priv->show_hidden);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void
+gth_vfs_tree_finalize (GObject *object)
+{
+ GthVfsTree *self = GTH_VFS_TREE (object);
+
+ g_signal_handler_disconnect (gth_main_get_default_monitor (), self->priv->monitor_folder_changed_id);
+ g_signal_handler_disconnect (gth_main_get_default_monitor (), self->priv->monitor_file_renamed_id);
+ _g_object_unref (self->priv->folder);
+
+ G_OBJECT_CLASS (gth_vfs_tree_parent_class)->finalize (object);
+}
+
+
+static void
+gth_vfs_tree_class_init (GthVfsTreeClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->set_property = gth_vfs_tree_set_property;
+ gobject_class->get_property = gth_vfs_tree_get_property;
+ gobject_class->finalize = gth_vfs_tree_finalize;
+
+ /* signals */
+
+ gth_vfs_tree_signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GthVfsTreeClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /* properties */
+
+ g_object_class_install_property (gobject_class,
+ PROP_SHOW_HIDDEN,
+ g_param_spec_boolean ("show-hidden",
+ "Show Hidden",
+ "Show hidden folders",
+ FALSE,
+ G_PARAM_READWRITE));
+}
+
+
+GtkWidget *
+gth_vfs_tree_new (const char *root)
+{
+ return g_object_new (GTH_TYPE_VFS_TREE, "root-uri", root, NULL);
+}
+
+
+void
+gth_vfs_tree_set_folder (GthVfsTree *self,
+ GFile *folder)
+{
+ g_return_if_fail (GTH_IS_VFS_TREE (self));
+ g_return_if_fail (folder != NULL);
+
+ _gth_vfs_tree_load_folder (self, LOAD_ACTION_LOAD, folder);
+}
+
+
+GFile *
+gth_vfs_tree_get_folder (GthVfsTree *self)
+{
+ g_return_val_if_fail (GTH_IS_VFS_TREE (self), NULL);
+ return self->priv->folder;
+}
+
+
+void
+gth_vfs_tree_set_show_hidden (GthVfsTree *self,
+ gboolean show_hidden)
+{
+ g_return_if_fail (GTH_IS_VFS_TREE (self));
+
+ g_object_set (self, "show-hidden", show_hidden, FALSE, NULL);
+ gth_vfs_tree_set_folder (self, self->priv->folder);
+}
+
+
+gboolean
+gth_vfs_tree_get_show_hidden (GthVfsTree *self)
+{
+ g_return_val_if_fail (GTH_IS_VFS_TREE (self), FALSE);
+
+ return self->priv->show_hidden;
+}
diff --git a/gthumb/gth-vfs-tree.h b/gthumb/gth-vfs-tree.h
new file mode 100644
index 00000000..a592f705
--- /dev/null
+++ b/gthumb/gth-vfs-tree.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2019 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_VFS_TREE_H
+#define GTH_VFS_TREE_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "gth-folder-tree.h"
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_VFS_TREE (gth_vfs_tree_get_type ())
+#define GTH_VFS_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_VFS_TREE, GthVfsTree))
+#define GTH_VFS_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_VFS_TREE, GthVfsTreeClass))
+#define GTH_IS_VFS_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_VFS_TREE))
+#define GTH_IS_VFS_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_VFS_TREE))
+#define GTH_VFS_TREE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTH_TYPE_VFS_TREE, GthVfsTreeClass))
+
+typedef struct _GthVfsTree GthVfsTree;
+typedef struct _GthVfsTreeClass GthVfsTreeClass;
+typedef struct _GthVfsTreePrivate GthVfsTreePrivate;
+
+struct _GthVfsTree {
+ GthFolderTree parent_instance;
+ GthVfsTreePrivate *priv;
+};
+
+struct _GthVfsTreeClass {
+ GthFolderTreeClass parent_class;
+
+ /* -- signals -- */
+
+ void (*changed) (GthVfsTree *vfs_tree);
+};
+
+GType gth_vfs_tree_get_type (void);
+GtkWidget * gth_vfs_tree_new (const char *root);
+void gth_vfs_tree_set_folder (GthVfsTree *vfs_tree,
+ GFile *folder);
+GFile * gth_vfs_tree_get_folder (GthVfsTree *vfs_tree);
+void gth_vfs_tree_set_show_hidden (GthVfsTree *self,
+ gboolean show_hidden);
+gboolean gth_vfs_tree_get_show_hidden (GthVfsTree *self);
+
+G_END_DECLS
+
+#endif /* GTH_VFS_TREE_H */
diff --git a/gthumb/meson.build b/gthumb/meson.build
index 5dff6b58..a14db474 100644
--- a/gthumb/meson.build
+++ b/gthumb/meson.build
@@ -64,6 +64,7 @@ public_header_files = [
'gth-load-file-data-task.h',
'gth-location-bar.h',
'gth-location-chooser.h',
+ 'gth-location-chooser-dialog.h',
'gth-main.h',
'gth-menu-manager.h',
'gth-metadata.h',
@@ -99,6 +100,7 @@ public_header_files = [
'gth-toolbox.h',
'gth-uri-list.h',
'gth-user-dir.h',
+ 'gth-vfs-tree.h',
'gth-viewer-page.h',
'gth-window.h',
'gtk-utils.h',
@@ -221,6 +223,7 @@ source_files = files(
'gth-load-file-data-task.c',
'gth-location-bar.c',
'gth-location-chooser.c',
+ 'gth-location-chooser-dialog.c',
'gth-main.c',
'gth-main-default-hooks.c',
'gth-main-default-metadata.c',
@@ -263,6 +266,7 @@ source_files = files(
'gth-trash-task.c',
'gth-uri-list.c',
'gth-user-dir.c',
+ 'gth-vfs-tree.c',
'gth-viewer-page.c',
'gth-window.c',
'gth-window-title.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]