[file-roller: 7/26] file selector: populate the place list
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [file-roller: 7/26] file selector: populate the place list
- Date: Thu, 9 Aug 2012 20:18:36 +0000 (UTC)
commit b19f2b1da54cefc7926c01ae3fae818aa09104df
Author: Paolo Bacchilega <paobac src gnome org>
Date: Wed Aug 8 18:11:04 2012 +0200
file selector: populate the place list
src/fr-file-selector-dialog.c | 894 +++++++++++++++++++++++++++++++++++++----
src/ui/file-selector.ui | 83 ++--
2 files changed, 863 insertions(+), 114 deletions(-)
---
diff --git a/src/fr-file-selector-dialog.c b/src/fr-file-selector-dialog.c
index de8f0e5..e2548c1 100644
--- a/src/fr-file-selector-dialog.c
+++ b/src/fr-file-selector-dialog.c
@@ -48,14 +48,26 @@ enum {
};
+typedef enum {
+ PLACE_TYPE_NORMAL,
+ PLACE_TYPE_VOLUME,
+ PLACE_TYPE_BOOKMARK
+} PlaceType;
+
+
enum {
PLACE_LIST_COLUMN_ICON,
PLACE_LIST_COLUMN_NAME,
PLACE_LIST_COLUMN_FILE,
- PLACE_LIST_COLUMN_IS_SEPARATOR
+ PLACE_LIST_COLUMN_IS_SEPARATOR,
+ PLACE_LIST_COLUMN_TYPE,
+ PLACE_LIST_COLUMN_SORT_ORDER
};
+/* -- load_data -- */
+
+
typedef struct {
FrFileSelectorDialog *dialog;
GFile *folder;
@@ -64,19 +76,6 @@ typedef struct {
} LoadData;
-struct _FrFileSelectorDialogPrivate {
- GtkBuilder *builder;
- GtkWidget *extra_widget;
- GFile *current_folder;
- LoadData *current_operation;
- GthIconCache *icon_cache;
- GSettings *settings;
-};
-
-
-/* -- load_data -- */
-
-
static LoadData *
load_data_new (FrFileSelectorDialog *dialog,
GFile *folder)
@@ -85,9 +84,9 @@ load_data_new (FrFileSelectorDialog *dialog,
load_data = g_new (LoadData, 1);
load_data->dialog = g_object_ref (dialog);
- load_data->folder = g_object_ref (folder);
+ load_data->folder = _g_object_ref (folder);
load_data->cancellable = g_cancellable_new ();
- file_info_list_free (load_data->files);
+ load_data->files = NULL;
return load_data;
}
@@ -99,19 +98,58 @@ load_data_free (LoadData *load_data)
if (load_data == NULL)
return;
- if (load_data->dialog->priv->current_operation == load_data)
- load_data->dialog->priv->current_operation = NULL;
-
g_object_unref (load_data->dialog);
- g_object_unref (load_data->folder);
+ _g_object_unref (load_data->folder);
g_object_unref (load_data->cancellable);
+ file_info_list_free (load_data->files);
g_free (load_data);
}
+/*-- bookmarks -- */
+
+
+typedef struct {
+ GFile *file;
+ char *name;
+} Bookmark;
+
+
+static void
+bookmark_free (Bookmark *b)
+{
+ if (b == NULL)
+ return;
+ _g_object_unref (b->file);
+ g_free (b->name);
+ g_slice_free (Bookmark, b);
+}
+
+
+static void
+bookmark_list_free (GList *list)
+{
+ g_list_foreach (list, (GFunc) bookmark_free, NULL);
+ g_list_free (list);
+}
+
+
/* -- fr_file_selector_dialog -- */
+struct _FrFileSelectorDialogPrivate {
+ GtkBuilder *builder;
+ GtkWidget *extra_widget;
+ GFile *current_folder;
+ LoadData *current_operation;
+ LoadData *places_operation;
+ GthIconCache *icon_cache;
+ GSettings *settings;
+ GList *special_places;
+ GList *bookmarks;
+};
+
+
static void
fr_file_selector_dialog_finalize (GObject *object)
{
@@ -122,11 +160,431 @@ fr_file_selector_dialog_finalize (GObject *object)
_g_object_unref (self->priv->current_folder);
gth_icon_cache_free (self->priv->icon_cache);
g_object_unref (self->priv->settings);
+ _g_object_list_unref (self->priv->special_places);
+ bookmark_list_free (self->priv->bookmarks);
G_OBJECT_CLASS (fr_file_selector_dialog_parent_class)->finalize (object);
}
+static GList *
+get_system_bookmarks (void)
+{
+ char *filename;
+ GFile *file;
+ GList *list;
+ char *contents;
+
+ filename = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "bookmarks", NULL);
+ file = g_file_new_for_path (filename);
+ if (! g_file_query_exists (file, NULL)) {
+ g_free (filename);
+ g_object_unref (file);
+
+ filename = g_build_filename (g_get_home_dir (), ".gtk-bookmarks", NULL);
+ file = g_file_new_for_path (filename);
+ }
+
+ list = NULL;
+ if (g_file_load_contents (file, NULL, &contents, NULL, NULL, NULL)) {
+ char **lines;
+ int i;
+
+ lines = g_strsplit (contents, "\n", -1);
+ for (i = 0; lines[i] != NULL; i++) {
+ Bookmark *bookmark;
+ char *space;
+
+ if (lines[i][0] == '\0')
+ continue;
+
+ bookmark = g_slice_new0 (Bookmark);
+
+ if ((space = strchr (lines[i], ' ')) != NULL) {
+ space[0] = '\0';
+ bookmark->name = g_strdup (space + 1);
+ }
+ bookmark->file = g_file_new_for_uri (lines[i]);
+
+ list = g_list_prepend (list, bookmark);
+ }
+
+ g_strfreev (lines);
+ g_free (contents);
+ }
+
+ g_object_unref (file);
+ g_free (filename);
+
+ return g_list_reverse (list);
+}
+
+
+static void
+_gtk_list_store_clear_type (GtkListStore *list_store,
+ PlaceType type_to_delete)
+{
+ GtkTreeIter iter;
+ gboolean iter_is_valid;
+
+ iter_is_valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter);
+ return;
+
+ while (iter_is_valid) {
+ PlaceType item_type;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (list_store), &iter,
+ PLACE_LIST_COLUMN_TYPE, &item_type,
+ -1);
+
+ if (item_type == type_to_delete)
+ iter_is_valid = gtk_list_store_remove (list_store, &iter);
+ else
+ iter_is_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (list_store), &iter);
+ }
+}
+
+
+static void
+update_bookmarks (FrFileSelectorDialog *self)
+{
+ GtkListStore *list_store;
+ GList *scan;
+ GtkTreeIter iter;
+ int sort_order = 0;
+
+ bookmark_list_free (self->priv->bookmarks);
+ self->priv->bookmarks = get_system_bookmarks ();
+
+ list_store = GTK_LIST_STORE (GET_WIDGET ("places_liststore"));
+ _gtk_list_store_clear_type (list_store, PLACE_TYPE_BOOKMARK);
+
+ /* separator */
+
+ gtk_list_store_append (list_store, &iter);
+ gtk_list_store_set (list_store, &iter,
+ PLACE_LIST_COLUMN_IS_SEPARATOR, TRUE,
+ PLACE_LIST_COLUMN_TYPE, PLACE_TYPE_BOOKMARK,
+ PLACE_LIST_COLUMN_SORT_ORDER, sort_order++,
+ -1);
+
+
+ for (scan = self->priv->bookmarks; scan; scan = scan->next) {
+ Bookmark *bookmark = scan->data;
+ char *name;
+ GIcon *icon;
+ GdkPixbuf *icon_pixbuf;
+
+ name = g_strdup (bookmark->name);
+
+ if (g_file_is_native (bookmark->file)) {
+ GFileInfo *info;
+
+ info = g_file_query_info (bookmark->file,
+ (G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_ICON),
+ 0,
+ NULL,
+ NULL);
+
+ if (info == NULL) {
+ g_free (name);
+ continue;
+ }
+
+ if (name == NULL)
+ name = g_strdup (g_file_info_get_display_name (info));
+ icon = g_object_ref (g_file_info_get_icon (info));
+
+ g_object_unref (info);
+ }
+ else {
+ if (name == NULL)
+ name = _g_file_get_display_basename (bookmark->file);
+ icon = g_themed_icon_new ("folder-remote");
+ }
+
+ gtk_list_store_append (list_store, &iter);
+
+ icon_pixbuf = gth_icon_cache_get_pixbuf (self->priv->icon_cache, icon);
+ gtk_list_store_set (list_store, &iter,
+ PLACE_LIST_COLUMN_ICON, icon_pixbuf,
+ PLACE_LIST_COLUMN_NAME, name,
+ PLACE_LIST_COLUMN_FILE, bookmark->file,
+ PLACE_LIST_COLUMN_TYPE, PLACE_TYPE_BOOKMARK,
+ PLACE_LIST_COLUMN_SORT_ORDER, sort_order++,
+ -1);
+
+ g_object_unref (icon_pixbuf);
+ g_object_unref (icon);
+ g_free (name);
+ }
+}
+
+
+static void
+update_places_list_ready_cb (GList *files, /* FileInfo list */
+ GError *error,
+ gpointer user_data)
+{
+ LoadData *load_data = user_data;
+ FrFileSelectorDialog *self = load_data->dialog;
+ GtkListStore *list_store;
+ GList *scan;
+ GtkTreeIter iter;
+ int sort_order = 0;
+
+ /* normal places */
+
+ list_store = GTK_LIST_STORE (GET_WIDGET ("places_liststore"));
+ _gtk_list_store_clear_type (list_store, PLACE_TYPE_NORMAL);
+ _gtk_list_store_clear_type (list_store, PLACE_TYPE_VOLUME);
+
+ for (scan = files; scan; scan = scan->next) {
+ FileInfo *file_info = scan->data;
+ GdkPixbuf *icon_pixbuf;
+
+ gtk_list_store_append (list_store, &iter);
+
+ icon_pixbuf = gth_icon_cache_get_pixbuf (self->priv->icon_cache, g_file_info_get_icon (file_info->info));
+ gtk_list_store_set (list_store, &iter,
+ PLACE_LIST_COLUMN_ICON, icon_pixbuf,
+ PLACE_LIST_COLUMN_NAME, g_file_info_get_display_name (file_info->info),
+ PLACE_LIST_COLUMN_FILE, file_info->file,
+ PLACE_LIST_COLUMN_TYPE, PLACE_TYPE_NORMAL,
+ PLACE_LIST_COLUMN_SORT_ORDER, sort_order++,
+ -1);
+
+ g_object_unref (icon_pixbuf);
+ }
+
+ /* root filesystem */
+
+ {
+ GIcon *icon;
+ GdkPixbuf *icon_pixbuf;
+ GFile *file;
+
+ gtk_list_store_append (list_store, &iter);
+
+ icon = g_themed_icon_new ("drive-harddisk");
+ icon_pixbuf = gth_icon_cache_get_pixbuf (self->priv->icon_cache, icon);
+ file = g_file_new_for_path ("file:///");
+ gtk_list_store_set (list_store, &iter,
+ PLACE_LIST_COLUMN_ICON, icon_pixbuf,
+ PLACE_LIST_COLUMN_NAME, N_("File System"),
+ PLACE_LIST_COLUMN_FILE, file,
+ PLACE_LIST_COLUMN_TYPE, PLACE_TYPE_VOLUME,
+ PLACE_LIST_COLUMN_SORT_ORDER, sort_order++,
+ -1);
+
+ g_object_unref (icon_pixbuf);
+ g_object_unref (icon);
+ g_object_unref (file);
+ }
+
+ /* drives / volumes / mounts */
+
+ for (scan = self->priv->special_places; scan; scan = scan->next) {
+ GObject *place = scan->data;
+ GIcon *icon;
+ char *name;
+ GFile *file;
+ GdkPixbuf *icon_pixbuf;
+
+ gtk_list_store_append (list_store, &iter);
+
+ if (G_IS_DRIVE (place)) {
+ icon = g_drive_get_icon (G_DRIVE (place));
+ name = g_drive_get_name (G_DRIVE (place));
+ file = NULL;
+ }
+ else if (G_IS_VOLUME (place)) {
+ icon = g_volume_get_icon (G_VOLUME (place));
+ name = g_volume_get_name (G_VOLUME (place));
+ file = NULL;
+ }
+ else if (G_IS_MOUNT (place)) {
+ icon = g_mount_get_icon (G_MOUNT (place));
+ name = g_mount_get_name (G_MOUNT (place));
+ file = g_mount_get_root (G_MOUNT (place));
+ }
+ else
+ continue;
+
+ icon_pixbuf = gth_icon_cache_get_pixbuf (self->priv->icon_cache, icon);
+ gtk_list_store_set (list_store, &iter,
+ PLACE_LIST_COLUMN_ICON, icon_pixbuf,
+ PLACE_LIST_COLUMN_NAME, name,
+ PLACE_LIST_COLUMN_FILE, file,
+ PLACE_LIST_COLUMN_TYPE, PLACE_TYPE_VOLUME,
+ PLACE_LIST_COLUMN_SORT_ORDER, sort_order++,
+ -1);
+
+ g_object_unref (icon_pixbuf);
+ _g_object_unref (icon);
+ g_free (name);
+ _g_object_unref (file);
+ }
+
+ if (load_data->dialog->priv->places_operation == load_data)
+ load_data->dialog->priv->places_operation = NULL;
+
+ load_data_free (load_data);
+}
+
+
+static gboolean
+mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
+{
+ GList *l;
+ GFile *mount_root;
+ gboolean ret;
+
+ ret = FALSE;
+
+ mount_root = g_mount_get_root (mount);
+
+ for (l = volumes; l != NULL; l = l->next)
+ {
+ GVolume *volume = G_VOLUME (l->data);
+ GFile *volume_activation_root;
+
+ volume_activation_root = g_volume_get_activation_root (volume);
+ if (volume_activation_root != NULL)
+ {
+ if (g_file_has_prefix (volume_activation_root, mount_root))
+ {
+ ret = TRUE;
+ g_object_unref (volume_activation_root);
+ break;
+ }
+ g_object_unref (volume_activation_root);
+ }
+ }
+
+ g_object_unref (mount_root);
+ return ret;
+}
+
+
+static void
+update_places_list (FrFileSelectorDialog *self)
+{
+ GList *places;
+ GList *drives;
+ GList *volumes;
+ GList *mounts;
+ GList *scan;
+
+ if (self->priv->places_operation != NULL)
+ g_cancellable_cancel (self->priv->places_operation->cancellable);
+
+ self->priv->places_operation = load_data_new (self, NULL);
+
+ /* drives / volumes /mounts */
+
+ _g_object_list_unref (self->priv->special_places);
+ self->priv->special_places = NULL;
+
+ /* connected drives */
+
+ drives = g_volume_monitor_get_connected_drives (g_volume_monitor_get ());
+ for (scan = drives; scan; scan = scan->next) {
+ GDrive *drive = scan->data;
+ GList *volumes;
+ GList *scan_volume;
+
+ volumes = g_drive_get_volumes (drive);
+ if (volumes != NULL) {
+ for (scan_volume = volumes; scan_volume; scan_volume = scan_volume->next) {
+ GVolume *volume = scan_volume->data;
+ GMount *mount;
+
+ mount = g_volume_get_mount (volume);
+ if (mount != NULL)
+ self->priv->special_places = g_list_prepend (self->priv->special_places, mount);
+ else
+ self->priv->special_places = g_list_prepend (self->priv->special_places, g_object_ref (volume));
+ }
+ _g_object_list_unref (volumes);
+ }
+ else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive))
+ self->priv->special_places = g_list_prepend (self->priv->special_places, g_object_ref (drive));
+ }
+ _g_object_list_unref (drives);
+
+ /* special_places */
+
+ volumes = g_volume_monitor_get_volumes (g_volume_monitor_get ());
+ for (scan = volumes; scan; scan = scan->next) {
+ GVolume *volume = scan->data;
+ GDrive *drive;
+ GMount *mount;
+
+ drive = g_volume_get_drive (volume);
+ if (drive != NULL) {
+ g_object_unref (drive);
+ continue;
+ }
+
+ mount = g_volume_get_mount (volume);
+ if (mount != NULL)
+ self->priv->special_places = g_list_prepend (self->priv->special_places, mount);
+ else
+ self->priv->special_places = g_list_prepend (self->priv->special_places, g_object_ref (volume));
+ }
+
+ /* mounts */
+
+ mounts = g_volume_monitor_get_mounts (g_volume_monitor_get ());
+ for (scan = mounts; scan; scan = scan->next) {
+ GMount *mount = scan->data;
+ GVolume *volume;
+
+ volume = g_mount_get_volume (mount);
+ if (volume != NULL) {
+ g_object_unref (volume);
+ continue;
+ }
+
+ if (mount_referenced_by_volume_activation_root (volumes, mount)) {
+ g_object_unref (mount);
+ continue;
+ }
+
+ self->priv->special_places = g_list_prepend (self->priv->special_places, g_object_ref (mount));
+ }
+
+ self->priv->special_places = g_list_reverse (self->priv->special_places);
+
+ _g_object_list_unref (mounts);
+ _g_object_list_unref (volumes);
+
+ /* other resourses */
+
+ places = NULL;
+ places = g_list_prepend (places, g_object_ref (_g_file_get_home ()));
+ places = g_list_prepend (places, g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)));
+ places = g_list_reverse (places);
+ _g_file_list_query_info_async (places,
+ FILE_LIST_DEFAULT,
+ (G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_ICON),
+ self->priv->places_operation->cancellable,
+ NULL,
+ NULL,
+ update_places_list_ready_cb,
+ self->priv->places_operation);
+
+ _g_object_list_unref (places);
+}
+
+
/* Taken from the Gtk+ file gtkfilechooserdefault.c
* Copyright (C) 2003, Red Hat, Inc. */
@@ -194,19 +652,28 @@ fr_file_selector_dialog_get_default_size (FrFileSelectorDialog *self,
static void
+_fr_file_selector_dialog_update_size (FrFileSelectorDialog *self)
+{
+ int default_width;
+ int default_height;
+
+ fr_file_selector_dialog_get_default_size (self, &default_width, &default_height);
+ gtk_window_set_default_size (GTK_WINDOW (self), default_width, default_height);
+}
+
+
+static void
fr_file_selector_dialog_realize (GtkWidget *widget)
{
FrFileSelectorDialog *self;
- int default_width;
- int default_height;
GTK_WIDGET_CLASS (fr_file_selector_dialog_parent_class)->realize (widget);
self = FR_FILE_SELECTOR_DIALOG (widget);
+ _fr_file_selector_dialog_update_size (self);
- fr_file_selector_dialog_get_default_size (self, &default_width, &default_height);
- gtk_window_set_default_size (GTK_WINDOW (self), default_width, default_height);
-
+ update_places_list (self);
+ update_bookmarks (self);
}
@@ -247,16 +714,19 @@ fr_file_selector_dialog_class_init (FrFileSelectorDialogClass *klass)
static gint
-compare_name_func (GtkTreeModel *model,
- GtkTreeIter *a,
- GtkTreeIter *b,
- gpointer user_data)
+files_name_column_sort_func (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
{
- char *key_a;
- char *key_b;
- gboolean is_folder_a;
- gboolean is_folder_b;
- gint result;
+ GtkSortType sort_order;
+ char *key_a;
+ char *key_b;
+ gboolean is_folder_a;
+ gboolean is_folder_b;
+ gint result;
+
+ gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), NULL, &sort_order);
gtk_tree_model_get (model, a,
FILE_LIST_COLUMN_NAME_ORDER, &key_a,
@@ -267,12 +737,64 @@ compare_name_func (GtkTreeModel *model,
FILE_LIST_COLUMN_IS_FOLDER, &is_folder_b,
-1);
- if (is_folder_a == is_folder_b)
+ if (is_folder_a == is_folder_b) {
result = strcmp (key_a, key_b);
- else if (is_folder_a)
- return -1;
- else
- return 1;
+ }
+ else {
+ result = is_folder_a ? -1 : 1;
+ if (sort_order == GTK_SORT_DESCENDING)
+ result = -1 * result;
+ }
+
+ g_free (key_a);
+ g_free (key_b);
+
+ return result;
+}
+
+
+static gint
+files_size_column_sort_func (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ GtkSortType sort_order;
+ char *key_a;
+ char *key_b;
+ gint64 size_a;
+ gint64 size_b;
+ gboolean is_folder_a;
+ gboolean is_folder_b;
+ int result;
+
+ gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), NULL, &sort_order);
+
+ gtk_tree_model_get (model, a,
+ FILE_LIST_COLUMN_NAME_ORDER, &key_a,
+ FILE_LIST_COLUMN_SIZE_ORDER, &size_a,
+ FILE_LIST_COLUMN_IS_FOLDER, &is_folder_a,
+ -1);
+ gtk_tree_model_get (model, b,
+ FILE_LIST_COLUMN_NAME_ORDER, &key_b,
+ FILE_LIST_COLUMN_SIZE_ORDER, &size_b,
+ FILE_LIST_COLUMN_IS_FOLDER, &is_folder_b,
+ -1);
+
+ if (is_folder_a == is_folder_b) {
+ if (is_folder_a) {
+ result = strcmp (key_a, key_b);
+ if (sort_order == GTK_SORT_DESCENDING)
+ result = -1 * result;
+ }
+ else
+ result = size_a - size_b;
+ }
+ else {
+ result = is_folder_a ? -1 : 1;
+ if (sort_order == GTK_SORT_DESCENDING)
+ result = -1 * result;
+ }
g_free (key_a);
g_free (key_b);
@@ -281,6 +803,69 @@ compare_name_func (GtkTreeModel *model,
}
+static gint
+files_modified_column_sort_func (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ GtkSortType sort_order;
+ glong modified_a;
+ glong modified_b;
+ gboolean is_folder_a;
+ gboolean is_folder_b;
+ int result;
+
+ gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), NULL, &sort_order);
+
+ gtk_tree_model_get (model, a,
+ FILE_LIST_COLUMN_MODIFIED_ORDER, &modified_a,
+ FILE_LIST_COLUMN_IS_FOLDER, &is_folder_a,
+ -1);
+ gtk_tree_model_get (model, b,
+ FILE_LIST_COLUMN_MODIFIED_ORDER, &modified_b,
+ FILE_LIST_COLUMN_IS_FOLDER, &is_folder_b,
+ -1);
+
+ if (is_folder_a == is_folder_b) {
+ result = modified_a - modified_b;
+ }
+ else {
+ result = is_folder_a ? -1 : 1;
+ if (sort_order == GTK_SORT_DESCENDING)
+ result = -1 * result;
+ }
+
+ return result;
+}
+
+
+static gint
+places_default_sort_func (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ int type_a, type_b;
+ int sort_order_a;
+ int sort_order_b;
+
+ gtk_tree_model_get (model, a,
+ PLACE_LIST_COLUMN_TYPE, &type_a,
+ PLACE_LIST_COLUMN_SORT_ORDER, &sort_order_a,
+ -1);
+ gtk_tree_model_get (model, b,
+ PLACE_LIST_COLUMN_TYPE, &type_b,
+ PLACE_LIST_COLUMN_SORT_ORDER, &sort_order_b,
+ -1);
+
+ if (type_a == type_b)
+ return sort_order_a - sort_order_b;
+ else
+ return type_a - type_b;
+}
+
+
static void
is_selected_cellrenderertoggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
gchar *path,
@@ -312,6 +897,89 @@ is_selected_cellrenderertoggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
static void
+files_treeview_row_activated_cb (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ gpointer user_data)
+{
+ FrFileSelectorDialog *self = user_data;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ GFile *file;
+ gboolean is_folder;
+
+ tree_model = gtk_tree_view_get_model (tree_view);
+ if (! gtk_tree_model_get_iter (tree_model, &iter, path))
+ return;
+
+ gtk_tree_model_get (tree_model, &iter,
+ FILE_LIST_COLUMN_FILE, &file,
+ FILE_LIST_COLUMN_IS_FOLDER, &is_folder,
+ -1);
+ if (is_folder)
+ fr_file_selector_dialog_set_current_folder (self, file);
+
+ g_object_unref (file);
+}
+
+
+static void
+places_treeview_selection_changed_cb (GtkTreeSelection *treeselection,
+ gpointer user_data)
+{
+ FrFileSelectorDialog *self = user_data;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ GFile *file;
+
+ if (! gtk_tree_selection_get_selected (treeselection, &tree_model, &iter))
+ return;
+
+ gtk_tree_model_get (tree_model, &iter,
+ PLACE_LIST_COLUMN_FILE, &file,
+ -1);
+ fr_file_selector_dialog_set_current_folder (self, file);
+
+ g_object_unref (file);
+}
+
+
+static gboolean
+places_treeview_row_separator_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ gboolean is_separator;
+
+ gtk_tree_model_get (model, iter,
+ PLACE_LIST_COLUMN_IS_SEPARATOR, &is_separator,
+ -1);
+
+ return is_separator;
+}
+
+
+static void
+go_up_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ FrFileSelectorDialog *self = user_data;
+ GFile *parent;
+
+ if (self->priv->current_folder == NULL)
+ return;
+
+ parent = g_file_get_parent (self->priv->current_folder);
+ if (parent == NULL)
+ return;
+
+ fr_file_selector_dialog_set_current_folder (self, parent);
+
+ g_object_unref (parent);
+}
+
+
+static void
fr_file_selector_dialog_init (FrFileSelectorDialog *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, FR_TYPE_FILE_SELECTOR_DIALOG, FrFileSelectorDialogPrivate);
@@ -319,17 +987,38 @@ fr_file_selector_dialog_init (FrFileSelectorDialog *self)
self->priv->builder = _gtk_builder_new_from_resource ("file-selector.ui");
self->priv->icon_cache = gth_icon_cache_new_for_widget (GTK_WIDGET (self), GTK_ICON_SIZE_MENU);
self->priv->settings = g_settings_new ("org.gnome.FileRoller.FileSelector");
+ self->priv->special_places = NULL;
gtk_container_set_border_width (GTK_CONTAINER (self), 5);
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (self))), GET_WIDGET ("content"));
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), FILE_LIST_COLUMN_NAME_ORDER, compare_name_func, self, NULL);
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), FILE_LIST_COLUMN_NAME_ORDER, GTK_SORT_ASCENDING);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), FILE_LIST_COLUMN_NAME, files_name_column_sort_func, self, NULL);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), FILE_LIST_COLUMN_SIZE, files_size_column_sort_func, self, NULL);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), FILE_LIST_COLUMN_MODIFIED, files_modified_column_sort_func, self, NULL);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), FILE_LIST_COLUMN_NAME, GTK_SORT_ASCENDING);
+
+ gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (GET_WIDGET ("places_liststore")), places_default_sort_func, self, NULL);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("places_liststore")), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
+ gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (GET_WIDGET ("places_treeview")), places_treeview_row_separator_func, self, NULL);
g_signal_connect (GET_WIDGET ("is_selected_cellrenderertoggle"),
"toggled",
G_CALLBACK (is_selected_cellrenderertoggle_toggled_cb),
self);
+ g_signal_connect (GET_WIDGET ("files_treeview"),
+ "row-activated",
+ G_CALLBACK (files_treeview_row_activated_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("go_up_button"),
+ "clicked",
+ G_CALLBACK (go_up_button_clicked_cb),
+ self);
+ g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (GET_WIDGET ("places_treeview"))),
+ "changed",
+ G_CALLBACK (places_treeview_selection_changed_cb),
+ self);
+
+ _fr_file_selector_dialog_update_size (self);
}
@@ -363,6 +1052,59 @@ fr_file_selector_dialog_get_extra_widget (FrFileSelectorDialog *self)
static gboolean
+_gtk_list_store_get_iter_for_file (GtkListStore *list_store,
+ GtkTreeIter *iter,
+ GFile *file)
+{
+ if (! gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), iter))
+ return FALSE;
+
+ do {
+ GFile *item_file;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (list_store), iter,
+ PLACE_LIST_COLUMN_FILE, &item_file,
+ -1);
+
+ if ((item_file != NULL) && g_file_equal (item_file, file)) {
+ _g_object_unref (item_file);
+ return TRUE;
+ }
+
+ _g_object_unref (item_file);
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (list_store), iter));
+
+ return FALSE;
+}
+
+
+static void
+set_current_folder (FrFileSelectorDialog *self,
+ GFile *folder)
+{
+ char *folder_name;
+ GtkTreeIter iter;
+
+ _g_clear_object (&self->priv->current_folder);
+ self->priv->current_folder = g_object_ref (folder);
+
+ folder_name = g_file_get_parse_name (folder);
+ gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("location_entry")), folder_name);
+
+ if (_gtk_list_store_get_iter_for_file (GTK_LIST_STORE (GET_WIDGET ("places_liststore")), &iter, folder)) {
+ GtkTreeSelection *tree_selection;
+
+ tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (GET_WIDGET ("places_treeview")));
+
+ g_signal_handlers_block_by_func (tree_selection, places_treeview_selection_changed_cb, self);
+ gtk_tree_selection_select_iter (tree_selection, &iter);
+ g_signal_handlers_unblock_by_func (tree_selection, places_treeview_selection_changed_cb, self);
+ }
+}
+
+
+static gboolean
_g_date_time_same_day (GDateTime *dt1,
GDateTime *dt2)
{
@@ -386,10 +1128,17 @@ get_folder_content_done_cb (GError *error,
GList *scan;
GtkTreeIter iter;
GDateTime *today;
+ int sort_column_id;
+ GtkSortType sort_order;
if (error != NULL) {
- g_warning ("%s", error->message);
+ if (! g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ _gtk_error_dialog_run (GTK_WINDOW (self), _("Could not load the location"), "%s", error->message);
+
+ if (load_data->dialog->priv->current_operation == load_data)
+ load_data->dialog->priv->current_operation = NULL;
load_data_free (load_data);
+
return;
}
@@ -397,6 +1146,9 @@ get_folder_content_done_cb (GError *error,
today = g_date_time_new_now_local ();
+ gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), &sort_column_id, &sort_order);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, 0);
+
list_store = GTK_LIST_STORE (GET_WIDGET ("files_liststore"));
gtk_list_store_clear (list_store);
for (scan = load_data->files; scan; scan = scan->next) {
@@ -407,6 +1159,10 @@ get_folder_content_done_cb (GError *error,
GDateTime *datetime;
char *modified;
char *collate_key;
+ gboolean is_folder;
+
+ if (g_file_info_get_is_hidden (file_info->info))
+ continue;
gtk_list_store_append (list_store, &iter);
@@ -416,17 +1172,18 @@ get_folder_content_done_cb (GError *error,
datetime = g_date_time_new_from_timeval_local (&timeval);
modified = g_date_time_format (datetime, _g_date_time_same_day (datetime, today) ? "%X" : "%x");
collate_key = g_utf8_collate_key_for_filename (g_file_info_get_display_name (file_info->info), -1);
+ is_folder = (g_file_info_get_file_type (file_info->info) == G_FILE_TYPE_DIRECTORY);
gtk_list_store_set (list_store, &iter,
FILE_LIST_COLUMN_ICON, icon_pixbuf,
FILE_LIST_COLUMN_NAME, g_file_info_get_display_name (file_info->info),
- FILE_LIST_COLUMN_SIZE, size,
+ FILE_LIST_COLUMN_SIZE, (is_folder ? "" : size),
FILE_LIST_COLUMN_MODIFIED, modified,
FILE_LIST_COLUMN_FILE, file_info->file,
FILE_LIST_COLUMN_NAME_ORDER, collate_key,
FILE_LIST_COLUMN_SIZE_ORDER, g_file_info_get_size (file_info->info),
FILE_LIST_COLUMN_MODIFIED_ORDER, timeval.tv_sec,
- FILE_LIST_COLUMN_IS_FOLDER, (g_file_info_get_file_type (file_info->info) == G_FILE_TYPE_DIRECTORY),
+ FILE_LIST_COLUMN_IS_FOLDER, is_folder,
-1);
g_free (collate_key);
@@ -436,6 +1193,12 @@ get_folder_content_done_cb (GError *error,
g_object_unref (icon_pixbuf);
}
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), sort_column_id, sort_order);
+ set_current_folder (self, load_data->folder);
+
+ if (load_data->dialog->priv->current_operation == load_data)
+ load_data->dialog->priv->current_operation = NULL;
+
g_date_time_unref (today);
load_data_free (load_data);
}
@@ -454,17 +1217,20 @@ get_folder_content_for_each_child_cb (GFile *file,
}
-static void
-get_folder_content (LoadData *load_data)
+void
+fr_file_selector_dialog_set_current_folder (FrFileSelectorDialog *self,
+ GFile *folder)
{
- FrFileSelectorDialog *self = load_data->dialog;
- char *folder_name;
+ g_return_if_fail (folder != NULL);
- folder_name = g_file_get_parse_name (load_data->folder);
- gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("location_entry")), folder_name);
+ if (self->priv->current_operation != NULL)
+ g_cancellable_cancel (self->priv->current_operation->cancellable);
- load_data->files = NULL;
- g_directory_foreach_child (load_data->folder,
+ self->priv->current_operation = load_data_new (self, folder);
+
+ gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("files_liststore")));
+
+ g_directory_foreach_child (self->priv->current_operation->folder,
FALSE,
TRUE,
(G_FILE_ATTRIBUTE_STANDARD_TYPE ","
@@ -473,33 +1239,13 @@ get_folder_content (LoadData *load_data)
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
G_FILE_ATTRIBUTE_STANDARD_ICON ","
G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
- G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER ","
G_FILE_ATTRIBUTE_TIME_MODIFIED ","
G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC),
- load_data->cancellable,
+ self->priv->current_operation->cancellable,
NULL,
get_folder_content_for_each_child_cb,
get_folder_content_done_cb,
- load_data);
-
- g_free (folder_name);
-}
-
-
-void
-fr_file_selector_dialog_set_current_folder (FrFileSelectorDialog *self,
- GFile *folder)
-{
- g_return_if_fail (folder != NULL);
-
- _g_clear_object (&self->priv->current_folder);
- self->priv->current_folder = g_object_ref (folder);
-
- if (self->priv->current_operation != NULL)
- g_cancellable_cancel (self->priv->current_operation->cancellable);
-
- self->priv->current_operation = load_data_new (self, folder);
- get_folder_content (self->priv->current_operation);
+ self->priv->current_operation);
}
diff --git a/src/ui/file-selector.ui b/src/ui/file-selector.ui
index 132711b..d55691b 100644
--- a/src/ui/file-selector.ui
+++ b/src/ui/file-selector.ui
@@ -1,42 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
- <object class="GtkListStore" id="files_liststore">
- <columns>
- <!-- column-name icon -->
- <column type="GdkPixbuf"/>
- <!-- column-name name -->
- <column type="gchararray"/>
- <!-- column-name size -->
- <column type="gchararray"/>
- <!-- column-name modified -->
- <column type="gchararray"/>
- <!-- column-name file -->
- <column type="GObject"/>
- <!-- column-name name_order -->
- <column type="gchararray"/>
- <!-- column-name size_order -->
- <column type="gint64"/>
- <!-- column-name modified_order -->
- <column type="gint64"/>
- <!-- column-name is_folder -->
- <column type="gboolean"/>
- <!-- column-name is_selected -->
- <column type="gboolean"/>
- </columns>
- </object>
- <object class="GtkListStore" id="places_liststore">
- <columns>
- <!-- column-name icon -->
- <column type="GdkPixbuf"/>
- <!-- column-name name -->
- <column type="gchararray"/>
- <!-- column-name file -->
- <column type="GObject"/>
- <!-- column-name is_separator -->
- <column type="gboolean"/>
- </columns>
- </object>
<object class="GtkBox" id="content">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -155,7 +119,6 @@
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
<property name="title" translatable="yes">Places</property>
- <property name="sort_column_id">1</property>
<child>
<object class="GtkCellRendererPixbuf" id="cellrendererpixbuf1"/>
<attributes>
@@ -201,7 +164,7 @@
<property name="title" translatable="yes" context="File">Name</property>
<property name="expand">True</property>
<property name="reorderable">True</property>
- <property name="sort_column_id">5</property>
+ <property name="sort_column_id">1</property>
<child>
<object class="GtkCellRendererToggle" id="is_selected_cellrenderertoggle"/>
<attributes>
@@ -231,7 +194,7 @@
<property name="fixed_width">100</property>
<property name="title" translatable="yes" context="File">Size</property>
<property name="reorderable">True</property>
- <property name="sort_column_id">6</property>
+ <property name="sort_column_id">2</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2"/>
<attributes>
@@ -247,7 +210,7 @@
<property name="fixed_width">100</property>
<property name="title" translatable="yes" context="File">Modified</property>
<property name="reorderable">True</property>
- <property name="sort_column_id">7</property>
+ <property name="sort_column_id">3</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext3"/>
<attributes>
@@ -294,4 +257,44 @@
</packing>
</child>
</object>
+ <object class="GtkListStore" id="files_liststore">
+ <columns>
+ <!-- column-name icon -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ <!-- column-name size -->
+ <column type="gchararray"/>
+ <!-- column-name modified -->
+ <column type="gchararray"/>
+ <!-- column-name file -->
+ <column type="GObject"/>
+ <!-- column-name name_order -->
+ <column type="gchararray"/>
+ <!-- column-name size_order -->
+ <column type="gint64"/>
+ <!-- column-name modified_order -->
+ <column type="gint64"/>
+ <!-- column-name is_folder -->
+ <column type="gboolean"/>
+ <!-- column-name is_selected -->
+ <column type="gboolean"/>
+ </columns>
+ </object>
+ <object class="GtkListStore" id="places_liststore">
+ <columns>
+ <!-- column-name icon -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ <!-- column-name file -->
+ <column type="GObject"/>
+ <!-- column-name is_separator -->
+ <column type="gboolean"/>
+ <!-- column-name type -->
+ <column type="gint"/>
+ <!-- column-name sort_order -->
+ <column type="gint"/>
+ </columns>
+ </object>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]