From: Carlos Garnacho Date: Tue, 10 Jun 2008 00:39:35 +0000 (+0000) Subject: Bug 520874 - Should use gio directly. X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;h=640d68778a82ae1c338d1583af49120c7119e3ae;p=~andy%2Fgtk Bug 520874 - Should use gio directly. 2008-06-10 Carlos Garnacho Bug 520874 - Should use gio directly. * gtk/gtkfilesystem.[ch]: Turn into a private object, which mostly provides helper functions for asynchronous calls, folder abstraction and uniform handling of volumes/drives/mounts. * gtk/gtkfilesystemwin32.[ch]: * gtk/gtkfilesystemunix.[ch]: Removed, these are no longer required. * gtk/gtkfilechooser.c: * gtk/gtkfilechooserbutton.c: * gtk/gtkfilechooserdefault.c: * gtk/gtkfilechooserentry.[ch]: * gtk/gtkfilechooserprivate.h: * gtk/gtkfilechooserutils.c: * gtk/gtkfilesystemmodel.[ch]: * gtk/gtkpathbar.[ch]: Use GIO internally. Adapt to GtkFileSystem API. Do not load filesystem implementation modules. * gtk/Makefile.am: * gtk/gtk.symbols: the gtkfilesystem.h private header isn't installed anymore, nor the unix/win32 implementations. * README.in: Add blurb about these changes. svn path=/trunk/; revision=20342 --- diff --git a/ChangeLog b/ChangeLog index b6763582d..f7bf37022 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2008-06-10 Carlos Garnacho + + Bug 520874 - Should use gio directly. + + * gtk/gtkfilesystem.[ch]: Turn into a private object, which mostly + provides helper functions for asynchronous calls, folder abstraction + and uniform handling of volumes/drives/mounts. + + * gtk/gtkfilesystemwin32.[ch]: + * gtk/gtkfilesystemunix.[ch]: Removed, these are no longer required. + + * gtk/gtkfilechooser.c: + * gtk/gtkfilechooserbutton.c: + * gtk/gtkfilechooserdefault.c: + * gtk/gtkfilechooserentry.[ch]: + * gtk/gtkfilechooserprivate.h: + * gtk/gtkfilechooserutils.c: + * gtk/gtkfilesystemmodel.[ch]: + * gtk/gtkpathbar.[ch]: Use GIO internally. Adapt to GtkFileSystem API. + Do not load filesystem implementation modules. + + * gtk/Makefile.am: + * gtk/gtk.symbols: the gtkfilesystem.h private header isn't installed + anymore, nor the unix/win32 implementations. + + * README.in: Add blurb about these changes. + 2008-06-09 Kristian Rietveld Bug 526987 - GtkCellRendererCombo should allow model to be NULL diff --git a/README.in b/README.in index c8261532a..908358f21 100644 --- a/README.in +++ b/README.in @@ -36,6 +36,12 @@ Release notes for 2.14 without including gtkitemfactory.h - even though this behaviour has never been supported in the first place. +* The GtkFileSystem semi-private interface has been removed. + The GTK+ filechooser implementation now uses GIO directly, which has + rendered external filesystem implementations unnecessary. Consequently, + the GtkFileSystem interface is no longer available, nor the filechooser + will load any GtkFileSystem implementation. + Release notes for 2.12 ====================== diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 8a8204ef6..9af44121c 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -344,8 +344,7 @@ endif # Installed header files without compatibility guarantees # that are not included in gtk/gtk.h gtk_semi_private_h_sources = \ - gtktextlayout.h \ - gtkfilesystem.h + gtktextlayout.h # GTK+ header files that don't get installed gtk_private_h_sources = \ @@ -361,8 +360,8 @@ gtk_private_h_sources = \ gtkfilechooserprivate.h \ gtkfilechoosersettings.h \ gtkfilechooserutils.h \ + gtkfilesystem.h \ gtkfilesystemmodel.h \ - gtkfilesystemunix.h \ gtkhsv.h \ gtkiconcache.h \ gtkintl.h \ @@ -654,7 +653,6 @@ gtk_c_sources = $(gtk_base_c_sources) gtk_all_c_sources = $(gtk_base_c_sources) gtk_os_unix_c_sources = \ - gtkfilesystemunix.c \ gtkpagesetupunixdialog.c \ gtkprinter.c \ gtkprinteroption.c \ @@ -669,7 +667,6 @@ gtk_os_unix_c_sources = \ gtk_all_c_sources += $(gtk_os_unix_c_sources) if OS_UNIX gtk_private_h_sources += \ - gtkfilesystemunix.h \ gtkiconcachevalidator.h \ gtkprintbackend.h \ gtkprinter-private.h \ @@ -682,12 +679,11 @@ gtk_c_sources += $(gtk_os_unix_c_sources) endif gtk_os_win32_c_sources = \ - gtkfilesystemwin32.c \ gtkprint-win32.c \ gtkprintoperation-win32.c gtk_all_c_sources += $(gtk_os_win32_c_sources) if OS_WIN32 -gtk_private_h_sources += gtkfilesystemwin32.h gtkprint-win32.h +gtk_private_h_sources += gtkprint-win32.h gtk_c_sources += $(gtk_os_win32_c_sources) endif @@ -1242,8 +1238,6 @@ EXTRA_DIST += \ gtkwin32embed.h \ gtkwin32embedwidget.h \ gtkwin32embedwidget.c \ - gtkfilesystemwin32.h \ - gtkfilesystemwin32.c \ gtkprint-win32.h \ gtkprint-win32.c \ gtksearchenginequartz.h \ diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 70d0add28..b6f8a2fb6 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -1461,87 +1461,6 @@ gtk_file_filter_set_name #endif #endif -#if IN_HEADER(__GTK_FILE_SYSTEM_H__) -#if IN_FILE(__GTK_FILE_SYSTEM_C__) -gtk_file_folder_get_info -gtk_file_folder_get_type G_GNUC_CONST -gtk_file_folder_is_finished_loading -gtk_file_folder_list_children -gtk_file_info_copy -gtk_file_info_free -gtk_file_info_get_display_key -gtk_file_info_get_display_name -gtk_file_info_get_icon_name -gtk_file_info_get_is_folder -gtk_file_info_get_is_hidden -gtk_file_info_get_mime_type -gtk_file_info_get_modification_time -gtk_file_info_get_size -gtk_file_info_get_type G_GNUC_CONST -gtk_file_info_new -gtk_file_info_render_icon -gtk_file_info_set_display_name -gtk_file_info_set_icon_name -gtk_file_info_set_is_folder -gtk_file_info_set_is_hidden -gtk_file_info_set_mime_type -gtk_file_info_set_modification_time -gtk_file_info_set_size -gtk_file_path_get_type G_GNUC_CONST -gtk_file_paths_copy -gtk_file_paths_free -gtk_file_paths_sort -gtk_file_system_cancel_operation -gtk_file_system_create -gtk_file_system_create_folder -gtk_file_system_error_quark -gtk_file_system_filename_to_path -gtk_file_system_get_info -gtk_file_system_get_folder -gtk_file_system_get_parent -gtk_file_system_get_type G_GNUC_CONST -gtk_file_system_get_volume_for_path -gtk_file_system_handle_get_type G_GNUC_CONST -gtk_file_system_insert_bookmark -gtk_file_system_list_bookmarks -gtk_file_system_list_volumes -gtk_file_system_make_path -gtk_file_system_parse -gtk_file_system_path_is_local -gtk_file_system_path_to_filename -gtk_file_system_path_to_uri -gtk_file_system_remove_bookmark -gtk_file_system_uri_to_path -gtk_file_system_volume_free -gtk_file_system_volume_get_base_path -gtk_file_system_volume_get_display_name -gtk_file_system_volume_get_icon_name -gtk_file_system_volume_get_is_mounted -gtk_file_system_volume_mount -gtk_file_system_volume_render_icon -gtk_file_system_get_bookmark_label -gtk_file_system_set_bookmark_label -#endif -#endif - -#if IN_HEADER(__GTK_FILE_SYSTEM_UNIX_H__) -#if IN_FILE(__GTK_FILE_SYSTEM_UNIX_C__) -#ifdef G_OS_UNIX -gtk_file_system_unix_get_type G_GNUC_CONST -gtk_file_system_unix_new -#endif -#endif -#endif - -#if IN_HEADER(__GTK_FILE_SYSTEM_WIN32_H__) -#if IN_FILE(__GTK_FILE_SYSTEM_WIN32_C__) -#ifdef G_OS_WIN32 -gtk_file_system_win32_get_type G_GNUC_CONST -gtk_file_system_win32_new -#endif -#endif -#endif - #if IN_HEADER(__GTK_FILESEL_H__) #if IN_FILE(__GTK_FILESEL_C__) #ifndef GTK_DISABLE_DEPRECATED diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c index e5e225b93..cd513a577 100644 --- a/gtk/gtkfilechooser.c +++ b/gtk/gtkfilechooser.c @@ -21,7 +21,6 @@ #include #include "gtkfilechooser.h" #include "gtkfilechooserprivate.h" -#include "gtkfilesystem.h" #include "gtkintl.h" #include "gtktypebuiltins.h" #include "gtkprivate.h" @@ -30,7 +29,7 @@ static void gtk_file_chooser_class_init (gpointer g_iface); -static GtkFilePath *gtk_file_chooser_get_path (GtkFileChooser *chooser); +static GFile *gtk_file_chooser_get_file (GtkFileChooser *chooser); GType gtk_file_chooser_get_type (void) @@ -446,18 +445,17 @@ gtk_file_chooser_get_select_multiple (GtkFileChooser *chooser) gchar * gtk_file_chooser_get_filename (GtkFileChooser *chooser) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gchar *result = NULL; - + g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - path = gtk_file_chooser_get_path (chooser); - if (path) + file = gtk_file_chooser_get_file (chooser); + + if (file) { - result = gtk_file_system_path_to_filename (file_system, path); - gtk_file_path_free (path); + result = g_file_get_basename (file); + g_object_unref (file); } return result; @@ -535,23 +533,15 @@ gboolean gtk_file_chooser_select_filename (GtkFileChooser *chooser, const gchar *filename) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gboolean result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); g_return_val_if_fail (filename != NULL, FALSE); - file_system = _gtk_file_chooser_get_file_system (chooser); - - path = gtk_file_system_filename_to_path (file_system, filename); - if (path) - { - result = _gtk_file_chooser_select_path (chooser, path, NULL); - gtk_file_path_free (path); - } - else - result = FALSE; + file = g_file_new_for_path (filename); + result = _gtk_file_chooser_select_file (chooser, file, NULL); + g_object_unref (file); return result; } @@ -571,39 +561,32 @@ void gtk_file_chooser_unselect_filename (GtkFileChooser *chooser, const char *filename) { - GtkFileSystem *file_system; - GtkFilePath *path; - + GFile *file; + g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser)); g_return_if_fail (filename != NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - - path = gtk_file_system_filename_to_path (file_system, filename); - if (path) - { - _gtk_file_chooser_unselect_path (chooser, path); - gtk_file_path_free (path); - } + file = g_file_new_for_path (filename); + _gtk_file_chooser_unselect_file (chooser, file); + g_object_unref (file); } -/* Converts a list of GtkFilePath* to a list of strings using the specified function */ +/* Converts a list of GFile* to a list of strings using the specified function */ static GSList * -file_paths_to_strings (GtkFileSystem *fs, - GSList *paths, - gchar * (*convert_func) (GtkFileSystem *fs, const GtkFilePath *path)) +files_to_strings (GSList *files, + gchar * (*convert_func) (GFile *file)) { GSList *strings; strings = NULL; - for (; paths; paths = paths->next) + for (; files; files = files->next) { - GtkFilePath *path; + GFile *file; gchar *string; - path = paths->data; - string = (* convert_func) (fs, path); + file = files->data; + string = (* convert_func) (file); if (string) strings = g_slist_prepend (strings, string); @@ -630,17 +613,16 @@ file_paths_to_strings (GtkFileSystem *fs, GSList * gtk_file_chooser_get_filenames (GtkFileChooser *chooser) { - GtkFileSystem *file_system; - GSList *paths; - GSList *result; + GSList *files, *result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - paths = _gtk_file_chooser_get_paths (chooser); + files = _gtk_file_chooser_get_files (chooser); + + result = files_to_strings (files, g_file_get_path); + g_slist_foreach (files, (GFunc) g_object_unref, NULL); + g_slist_free (files); - result = file_paths_to_strings (file_system, paths, gtk_file_system_path_to_filename); - gtk_file_paths_free (paths); return result; } @@ -662,23 +644,15 @@ gboolean gtk_file_chooser_set_current_folder (GtkFileChooser *chooser, const gchar *filename) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gboolean result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); g_return_val_if_fail (filename != NULL, FALSE); - file_system = _gtk_file_chooser_get_file_system (chooser); - - path = gtk_file_system_filename_to_path (file_system, filename); - if (path) - { - result = _gtk_file_chooser_set_current_folder_path (chooser, path, NULL); - gtk_file_path_free (path); - } - else - result = FALSE; + file = g_file_new_for_path (filename); + result = _gtk_file_chooser_set_current_folder_file (chooser, file, NULL); + g_object_unref (file); return result; } @@ -709,20 +683,17 @@ gtk_file_chooser_set_current_folder (GtkFileChooser *chooser, gchar * gtk_file_chooser_get_current_folder (GtkFileChooser *chooser) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gchar *filename; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - - path = _gtk_file_chooser_get_current_folder_path (chooser); - if (!path) + file = _gtk_file_chooser_get_current_folder_file (chooser); + if (!file) return NULL; - filename = gtk_file_system_path_to_filename (file_system, path); - gtk_file_path_free (path); + filename = g_file_get_path (file); + g_object_unref (file); return filename; } @@ -773,18 +744,16 @@ gtk_file_chooser_set_current_name (GtkFileChooser *chooser, gchar * gtk_file_chooser_get_uri (GtkFileChooser *chooser) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gchar *result = NULL; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - path = gtk_file_chooser_get_path (chooser); - if (path) + file = gtk_file_chooser_get_file (chooser); + if (file) { - result = gtk_file_system_path_to_uri (file_system, path); - gtk_file_path_free (path); + result = g_file_get_uri (file); + g_object_unref (file); } return result; @@ -861,23 +830,15 @@ gboolean gtk_file_chooser_select_uri (GtkFileChooser *chooser, const char *uri) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gboolean result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); g_return_val_if_fail (uri != NULL, FALSE); - file_system = _gtk_file_chooser_get_file_system (chooser); - - path = gtk_file_system_uri_to_path (file_system, uri); - if (path) - { - result = _gtk_file_chooser_select_path (chooser, path, NULL); - gtk_file_path_free (path); - } - else - result = FALSE; + file = g_file_new_for_uri (uri); + result = _gtk_file_chooser_select_file (chooser, file, NULL); + g_object_unref (file); return result; } @@ -897,20 +858,14 @@ void gtk_file_chooser_unselect_uri (GtkFileChooser *chooser, const char *uri) { - GtkFileSystem *file_system; - GtkFilePath *path; - + GFile *file; + g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser)); g_return_if_fail (uri != NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - - path = gtk_file_system_uri_to_path (file_system, uri); - if (path) - { - _gtk_file_chooser_unselect_path (chooser, path); - gtk_file_path_free (path); - } + file = g_file_new_for_uri (uri); + _gtk_file_chooser_unselect_file (chooser, file); + g_object_unref (file); } /** @@ -962,17 +917,16 @@ gtk_file_chooser_unselect_all (GtkFileChooser *chooser) GSList * gtk_file_chooser_get_uris (GtkFileChooser *chooser) { - GtkFileSystem *file_system; - GSList *paths; - GSList *result; + GSList *files, *result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - paths = _gtk_file_chooser_get_paths (chooser); + files = _gtk_file_chooser_get_files (chooser); + + result = files_to_strings (files, g_file_get_uri); + g_slist_foreach (files, (GFunc) g_object_unref, NULL); + g_slist_free (files); - result = file_paths_to_strings (file_system, paths, gtk_file_system_path_to_uri); - gtk_file_paths_free (paths); return result; } @@ -994,23 +948,15 @@ gboolean gtk_file_chooser_set_current_folder_uri (GtkFileChooser *chooser, const gchar *uri) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gboolean result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); g_return_val_if_fail (uri != NULL, FALSE); - file_system = _gtk_file_chooser_get_file_system (chooser); - - path = gtk_file_system_uri_to_path (file_system, uri); - if (path) - { - result = _gtk_file_chooser_set_current_folder_path (chooser, path, NULL); - gtk_file_path_free (path); - } - else - result = FALSE; + file = g_file_new_for_path (uri); + result = _gtk_file_chooser_set_current_folder_file (chooser, file, NULL); + g_object_unref (file); return result; } @@ -1040,31 +986,28 @@ gtk_file_chooser_set_current_folder_uri (GtkFileChooser *chooser, gchar * gtk_file_chooser_get_current_folder_uri (GtkFileChooser *chooser) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gchar *uri; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - - path = _gtk_file_chooser_get_current_folder_path (chooser); - if (!path) + file = _gtk_file_chooser_get_current_folder_file (chooser); + if (!file) return NULL; - uri = gtk_file_system_path_to_uri (file_system, path); - gtk_file_path_free (path); + uri = g_file_get_uri (file); + g_object_unref (file); return uri; } /** - * _gtk_file_chooser_set_current_folder_path: + * _gtk_file_chooser_set_current_folder_file: * @chooser: a #GtkFileChooser - * @path: the #GtkFilePath for the new folder + * @file: the #GFile for the new folder * @error: location to store error, or %NULL. * - * Sets the current folder for @chooser from a #GtkFilePath. + * Sets the current folder for @chooser from a #GFile. * Internal function, see gtk_file_chooser_set_current_folder_uri(). * * Return value: %TRUE if the folder could be changed successfully, %FALSE @@ -1073,31 +1016,30 @@ gtk_file_chooser_get_current_folder_uri (GtkFileChooser *chooser) * Since: 2.4 **/ gboolean -_gtk_file_chooser_set_current_folder_path (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +_gtk_file_chooser_set_current_folder_file (GtkFileChooser *chooser, + GFile *file, + GError **error) { g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); - g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (G_IS_FILE (file), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - return GTK_FILE_CHOOSER_GET_IFACE (chooser)->set_current_folder (chooser, path, error); + return GTK_FILE_CHOOSER_GET_IFACE (chooser)->set_current_folder (chooser, file, error); } /** - * _gtk_file_chooser_get_current_folder_path: + * _gtk_file_chooser_get_current_folder_file: * @chooser: a #GtkFileChooser * - * Gets the current folder of @chooser as #GtkFilePath. + * Gets the current folder of @chooser as #GFile. * See gtk_file_chooser_get_current_folder_uri(). * - * Return value: the #GtkFilePath for the current folder. - * Free with gtk_file_path_free(). + * Return value: the #GFile for the current folder. * * Since: 2.4 */ -GtkFilePath * -_gtk_file_chooser_get_current_folder_path (GtkFileChooser *chooser) +GFile * +_gtk_file_chooser_get_current_folder_file (GtkFileChooser *chooser) { g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); @@ -1105,9 +1047,9 @@ _gtk_file_chooser_get_current_folder_path (GtkFileChooser *chooser) } /** - * _gtk_file_chooser_select_path: + * _gtk_file_chooser_select_file: * @chooser: a #GtkFileChooser - * @path: the path to select + * @file: the file to select * @error: location to store error, or %NULL * * Selects the file referred to by @path. An internal function. See @@ -1119,15 +1061,15 @@ _gtk_file_chooser_get_current_folder_path (GtkFileChooser *chooser) * Since: 2.4 **/ gboolean -_gtk_file_chooser_select_path (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +_gtk_file_chooser_select_file (GtkFileChooser *chooser, + GFile *file, + GError **error) { g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); - g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (G_IS_FILE (file), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - return GTK_FILE_CHOOSER_GET_IFACE (chooser)->select_path (chooser, path, error); + return GTK_FILE_CHOOSER_GET_IFACE (chooser)->select_file (chooser, file, error); } /** @@ -1141,49 +1083,52 @@ _gtk_file_chooser_select_path (GtkFileChooser *chooser, * Since: 2.4 **/ void -_gtk_file_chooser_unselect_path (GtkFileChooser *chooser, - const GtkFilePath *path) +_gtk_file_chooser_unselect_file (GtkFileChooser *chooser, + GFile *file) { g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser)); + g_return_if_fail (G_IS_FILE (file)); - GTK_FILE_CHOOSER_GET_IFACE (chooser)->unselect_path (chooser, path); + GTK_FILE_CHOOSER_GET_IFACE (chooser)->unselect_file (chooser, file); } /** - * _gtk_file_chooser_get_paths: + * _gtk_file_chooser_get_files: * @chooser: a #GtkFileChooser * * Lists all the selected files and subfolders in the current folder of @chooser - * as #GtkFilePath. An internal function, see gtk_file_chooser_get_uris(). + * as #GFile. An internal function, see gtk_file_chooser_get_uris(). * - * Return value: a #GSList containing a #GtkFilePath for each selected + * Return value: a #GSList containing a #GFile for each selected * file and subfolder in the current folder. Free the returned list - * with g_slist_free(), and the paths with gtk_file_path_free(). + * with g_slist_free(), and the files with g_object_unref(). * * Since: 2.4 **/ GSList * -_gtk_file_chooser_get_paths (GtkFileChooser *chooser) +_gtk_file_chooser_get_files (GtkFileChooser *chooser) { g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_paths (chooser); + return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_files (chooser); } -static GtkFilePath * -gtk_file_chooser_get_path (GtkFileChooser *chooser) +static GFile * +gtk_file_chooser_get_file (GtkFileChooser *chooser) { GSList *list; - GtkFilePath *result = NULL; + GFile *result = NULL; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - list = _gtk_file_chooser_get_paths (chooser); + list = _gtk_file_chooser_get_files (chooser); if (list) { result = list->data; list = g_slist_delete_link (list, list); - gtk_file_paths_free (list); + + g_slist_foreach (list, (GFunc) g_object_unref, NULL); + g_slist_free (list); } return result; @@ -1364,29 +1309,29 @@ gtk_file_chooser_get_use_preview_label (GtkFileChooser *chooser) } /** - * gtk_file_chooser_get_preview_filename: + * gtk_file_chooser_get_preview_file: * @chooser: a #GtkFileChooser * * Gets the filename that should be previewed in a custom preview * Internal function, see gtk_file_chooser_get_preview_uri(). * - * Return value: the #GtkFilePath for the file to preview, or %NULL if no file + * Return value: the #GFile for the file to preview, or %NULL if no file * is selected. Free with gtk_file_path_free(). * * Since: 2.4 **/ -GtkFilePath * -_gtk_file_chooser_get_preview_path (GtkFileChooser *chooser) +GFile * +_gtk_file_chooser_get_preview_file (GtkFileChooser *chooser) { g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_preview_path (chooser); + return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_preview_file (chooser); } /** * _gtk_file_chooser_add_shortcut_folder: * @chooser: a #GtkFileChooser - * @path: path of the folder to add + * @file: file for the folder to add * @error: location to store error, or %NULL * * Adds a folder to be displayed with the shortcut folders in a file chooser. @@ -1398,20 +1343,20 @@ _gtk_file_chooser_get_preview_path (GtkFileChooser *chooser) * Since: 2.4 **/ gboolean -_gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +_gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); - g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (G_IS_FILE (file), FALSE); - return GTK_FILE_CHOOSER_GET_IFACE (chooser)->add_shortcut_folder (chooser, path, error); + return GTK_FILE_CHOOSER_GET_IFACE (chooser)->add_shortcut_folder (chooser, file, error); } /** * _gtk_file_chooser_remove_shortcut_folder: * @chooser: a #GtkFileChooser - * @path: path of the folder to remove + * @file: file for the folder to remove * @error: location to store error, or %NULL * * Removes a folder from the shortcut folders in a file chooser. Internal @@ -1423,14 +1368,14 @@ _gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser, * Since: 2.4 **/ gboolean -_gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +_gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); - g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (G_IS_FILE (file), FALSE); - return GTK_FILE_CHOOSER_GET_IFACE (chooser)->remove_shortcut_folder (chooser, path, error); + return GTK_FILE_CHOOSER_GET_IFACE (chooser)->remove_shortcut_folder (chooser, file, error); } /** @@ -1449,18 +1394,16 @@ _gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser, char * gtk_file_chooser_get_preview_filename (GtkFileChooser *chooser) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gchar *result = NULL; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - path = _gtk_file_chooser_get_preview_path (chooser); - if (path) + file =_gtk_file_chooser_get_preview_file (chooser); + if (file) { - result = gtk_file_system_path_to_filename (file_system, path); - gtk_file_path_free (path); + result = g_file_get_path (file); + g_object_unref (file); } return result; @@ -1481,18 +1424,16 @@ gtk_file_chooser_get_preview_filename (GtkFileChooser *chooser) char * gtk_file_chooser_get_preview_uri (GtkFileChooser *chooser) { - GtkFileSystem *file_system; - GtkFilePath *path; + GFile *file; gchar *result = NULL; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - file_system = _gtk_file_chooser_get_file_system (chooser); - path = _gtk_file_chooser_get_preview_path (chooser); - if (path) + file = _gtk_file_chooser_get_preview_file (chooser); + if (file) { - result = gtk_file_system_path_to_uri (file_system, path); - gtk_file_path_free (path); + result = g_file_get_uri (file); + g_object_unref (file); } return result; @@ -1682,26 +1623,15 @@ gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser, const char *folder, GError **error) { - GtkFilePath *path; + GFile *file; gboolean result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); g_return_val_if_fail (folder != NULL, FALSE); - path = gtk_file_system_filename_to_path (_gtk_file_chooser_get_file_system (chooser), folder); - if (!path) - { - g_set_error (error, - GTK_FILE_CHOOSER_ERROR, - GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, - _("Invalid filename: %s"), - folder); - return FALSE; - } - - result = GTK_FILE_CHOOSER_GET_IFACE (chooser)->add_shortcut_folder (chooser, path, error); - - gtk_file_path_free (path); + file = g_file_new_for_path (folder); + result = GTK_FILE_CHOOSER_GET_IFACE (chooser)->add_shortcut_folder (chooser, file, error); + g_object_unref (file); return result; } @@ -1726,26 +1656,15 @@ gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser, const char *folder, GError **error) { - GtkFilePath *path; + GFile *file; gboolean result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); g_return_val_if_fail (folder != NULL, FALSE); - path = gtk_file_system_filename_to_path (_gtk_file_chooser_get_file_system (chooser), folder); - if (!path) - { - g_set_error (error, - GTK_FILE_CHOOSER_ERROR, - GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, - _("Invalid filename: %s"), - folder); - return FALSE; - } - - result = GTK_FILE_CHOOSER_GET_IFACE (chooser)->remove_shortcut_folder (chooser, path, error); - - gtk_file_path_free (path); + file = g_file_new_for_path (folder); + result = GTK_FILE_CHOOSER_GET_IFACE (chooser)->remove_shortcut_folder (chooser, file, error); + g_object_unref (file); return result; } @@ -1773,10 +1692,10 @@ gtk_file_chooser_list_shortcut_folders (GtkFileChooser *chooser) folders = GTK_FILE_CHOOSER_GET_IFACE (chooser)->list_shortcut_folders (chooser); - result = file_paths_to_strings (_gtk_file_chooser_get_file_system (chooser), - folders, - gtk_file_system_path_to_filename); - gtk_file_paths_free (folders); + result = files_to_strings (folders, g_file_get_path); + g_slist_foreach (folders, (GFunc) g_object_unref, NULL); + g_slist_free (folders); + return result; } @@ -1801,26 +1720,15 @@ gtk_file_chooser_add_shortcut_folder_uri (GtkFileChooser *chooser, const char *uri, GError **error) { - GtkFilePath *path; + GFile *file; gboolean result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); g_return_val_if_fail (uri != NULL, FALSE); - path = gtk_file_system_uri_to_path (_gtk_file_chooser_get_file_system (chooser), uri); - if (!path) - { - g_set_error (error, - GTK_FILE_CHOOSER_ERROR, - GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, - _("Invalid filename: %s"), - uri); - return FALSE; - } - - result = GTK_FILE_CHOOSER_GET_IFACE (chooser)->add_shortcut_folder (chooser, path, error); - - gtk_file_path_free (path); + file = g_file_new_for_uri (uri); + result = GTK_FILE_CHOOSER_GET_IFACE (chooser)->add_shortcut_folder (chooser, file, error); + g_object_unref (file); return result; } @@ -1845,26 +1753,15 @@ gtk_file_chooser_remove_shortcut_folder_uri (GtkFileChooser *chooser, const char *uri, GError **error) { - GtkFilePath *path; + GFile *file; gboolean result; g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE); g_return_val_if_fail (uri != NULL, FALSE); - path = gtk_file_system_uri_to_path (_gtk_file_chooser_get_file_system (chooser), uri); - if (!path) - { - g_set_error (error, - GTK_FILE_CHOOSER_ERROR, - GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, - _("Invalid filename: %s"), - uri); - return FALSE; - } - - result = GTK_FILE_CHOOSER_GET_IFACE (chooser)->remove_shortcut_folder (chooser, path, error); - - gtk_file_path_free (path); + file = g_file_new_for_uri (uri); + result = GTK_FILE_CHOOSER_GET_IFACE (chooser)->remove_shortcut_folder (chooser, file, error); + g_object_unref (file); return result; } @@ -1892,10 +1789,10 @@ gtk_file_chooser_list_shortcut_folder_uris (GtkFileChooser *chooser) folders = GTK_FILE_CHOOSER_GET_IFACE (chooser)->list_shortcut_folders (chooser); - result = file_paths_to_strings (_gtk_file_chooser_get_file_system (chooser), - folders, - gtk_file_system_path_to_uri); - gtk_file_paths_free (folders); + result = files_to_strings (folders, g_file_get_uri); + g_slist_foreach (folders, (GFunc) g_object_unref, NULL); + g_slist_free (folders); + return result; } diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c index 9e31e0506..bca2312a9 100644 --- a/gtk/gtkfilechooserbutton.c +++ b/gtk/gtkfilechooserbutton.c @@ -52,10 +52,6 @@ #include "gtkfilechooserbutton.h" -#ifdef G_OS_WIN32 -#include "gtkfilesystemwin32.h" -#endif - #include "gtkprivate.h" #include "gtkalias.h" @@ -102,7 +98,7 @@ enum TYPE_COLUMN, DATA_COLUMN, IS_FOLDER_COLUMN, - HANDLE_COLUMN, + CANCELLABLE_COLUMN, NUM_COLUMNS }; @@ -143,7 +139,7 @@ struct _GtkFileChooserButtonPrivate gchar *backend; GtkFileSystem *fs; - GtkFilePath *old_path; + GFile *old_file; gulong combo_box_changed_id; gulong dialog_file_activated_id; @@ -152,9 +148,9 @@ struct _GtkFileChooserButtonPrivate gulong fs_volumes_changed_id; gulong fs_bookmarks_changed_id; - GtkFileSystemHandle *dnd_select_folder_handle; - GtkFileSystemHandle *update_button_handle; - GSList *change_icon_theme_handles; + GCancellable *dnd_select_folder_cancellable; + GCancellable *update_button_cancellable; + GSList *change_icon_theme_cancellables; gint icon_size; @@ -195,10 +191,10 @@ enum /* GtkFileChooserIface Functions */ static void gtk_file_chooser_button_file_chooser_iface_init (GtkFileChooserIface *iface); static gboolean gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); static gboolean gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); /* GObject Functions */ @@ -240,8 +236,8 @@ static void gtk_file_chooser_button_screen_changed (GtkWidget *wi /* Utility Functions */ static GtkIconTheme *get_icon_theme (GtkWidget *widget); -static void set_info_for_path_at_iter (GtkFileChooserButton *fs, - const GtkFilePath *path, +static void set_info_for_file_at_iter (GtkFileChooserButton *fs, + GFile *file, GtkTreeIter *iter); static gint model_get_type_position (GtkFileChooserButton *button, @@ -255,7 +251,7 @@ static void model_add_volumes (GtkFileChooserButton *button, static void model_add_bookmarks (GtkFileChooserButton *button, GSList *bookmarks); static void model_update_current_folder (GtkFileChooserButton *button, - const GtkFilePath *path); + GFile *file); static void model_remove_rows (GtkFileChooserButton *button, gint pos, gint n_rows); @@ -486,7 +482,7 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button) G_TYPE_CHAR, /* Row Type */ G_TYPE_POINTER /* Volume || Path */, G_TYPE_BOOLEAN /* Is Folder? */, - G_TYPE_POINTER /* handle */)); + G_TYPE_POINTER /* cancellable */)); priv->combo_box = gtk_combo_box_new (); priv->combo_box_changed_id = @@ -537,16 +533,16 @@ gtk_file_chooser_button_file_chooser_iface_init (GtkFileChooserIface *iface) } static gboolean -gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { GtkFileChooser *delegate; gboolean retval; delegate = g_object_get_qdata (G_OBJECT (chooser), GTK_FILE_CHOOSER_DELEGATE_QUARK); - retval = _gtk_file_chooser_add_shortcut_folder (delegate, path, error); + retval = _gtk_file_chooser_add_shortcut_folder (delegate, file, error); if (retval) { @@ -563,10 +559,10 @@ gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, ICON_COLUMN, NULL, DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME), TYPE_COLUMN, ROW_TYPE_SHORTCUT, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, FALSE, -1); - set_info_for_path_at_iter (button, path, &iter); + set_info_for_file_at_iter (button, file, &iter); priv->n_shortcuts++; gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); @@ -576,9 +572,9 @@ gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, } static gboolean -gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { GtkFileChooser *delegate; gboolean retval; @@ -586,7 +582,7 @@ gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, delegate = g_object_get_qdata (G_OBJECT (chooser), GTK_FILE_CHOOSER_DELEGATE_QUARK); - retval = _gtk_file_chooser_remove_shortcut_folder (delegate, path, error); + retval = _gtk_file_chooser_remove_shortcut_folder (delegate, file, error); if (retval) { @@ -609,8 +605,7 @@ gtk_file_chooser_button_remove_shortcut_folder (GtkFileChooser *chooser, -1); if (type == ROW_TYPE_SHORTCUT && - data && - gtk_file_path_compare (data, path) == 0) + data && g_file_equal (data, file)) { model_free_row_data (GTK_FILE_CHOOSER_BUTTON (chooser), &iter); gtk_list_store_remove (GTK_LIST_STORE (priv->model), &iter); @@ -728,7 +723,8 @@ gtk_file_chooser_button_constructor (GType type, list = gtk_file_system_list_bookmarks (priv->fs); model_add_bookmarks (button, list); - gtk_file_paths_free (list); + g_slist_foreach (list, (GFunc) g_object_unref, NULL); + g_slist_free (list); model_add_other (button); @@ -899,8 +895,8 @@ gtk_file_chooser_button_finalize (GObject *object) GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object); GtkFileChooserButtonPrivate *priv = button->priv; - if (priv->old_path) - gtk_file_path_free (priv->old_path); + if (priv->old_file) + g_object_unref (priv->old_file); if (G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->finalize != NULL) (*G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->finalize) (object); @@ -930,27 +926,27 @@ gtk_file_chooser_button_destroy (GtkObject *object) } while (gtk_tree_model_iter_next (priv->model, &iter)); - if (priv->dnd_select_folder_handle) + if (priv->dnd_select_folder_cancellable) { - gtk_file_system_cancel_operation (priv->dnd_select_folder_handle); - priv->dnd_select_folder_handle = NULL; + g_cancellable_cancel (priv->dnd_select_folder_cancellable); + priv->dnd_select_folder_cancellable = NULL; } - if (priv->update_button_handle) + if (priv->update_button_cancellable) { - gtk_file_system_cancel_operation (priv->update_button_handle); - priv->update_button_handle = NULL; + g_cancellable_cancel (priv->update_button_cancellable); + priv->update_button_cancellable = NULL; } - if (priv->change_icon_theme_handles) + if (priv->change_icon_theme_cancellables) { - for (l = priv->change_icon_theme_handles; l; l = l->next) + for (l = priv->change_icon_theme_cancellables; l; l = l->next) { - GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data); - gtk_file_system_cancel_operation (handle); + GCancellable *cancellable = G_CANCELLABLE (l->data); + g_cancellable_cancel (cancellable); } - g_slist_free (priv->change_icon_theme_handles); - priv->change_icon_theme_handles = NULL; + g_slist_free (priv->change_icon_theme_cancellables); + priv->change_icon_theme_cancellables = NULL; } if (priv->model) @@ -984,45 +980,48 @@ gtk_file_chooser_button_destroy (GtkObject *object) struct DndSelectFolderData { + GtkFileSystem *file_system; GtkFileChooserButton *button; GtkFileChooserAction action; - GtkFilePath *path; + GFile *file; gchar **uris; guint i; gboolean selected; }; static void -dnd_select_folder_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +dnd_select_folder_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct DndSelectFolderData *data = user_data; - if (handle != data->button->priv->dnd_select_folder_handle) + if (cancellable != data->button->priv->dnd_select_folder_cancellable) { g_object_unref (data->button); - gtk_file_path_free (data->path); + g_object_unref (data->file); g_strfreev (data->uris); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); return; } - data->button->priv->dnd_select_folder_handle = NULL; + data->button->priv->dnd_select_folder_cancellable = NULL; if (!cancelled && !error && info != NULL) { - data->selected = - (((data->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER && - gtk_file_info_get_is_folder (info)) || - (data->action == GTK_FILE_CHOOSER_ACTION_OPEN && - !gtk_file_info_get_is_folder (info))) && - _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (data->button->priv->dialog), - data->path, NULL)); + gboolean is_folder; + + is_folder = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); + + data->selected = + (((data->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER && is_folder) || + (data->action == GTK_FILE_CHOOSER_ACTION_OPEN && !is_folder)) && + _gtk_file_chooser_select_file (GTK_FILE_CHOOSER (data->button->priv->dialog), + data->file, NULL)); } else data->selected = FALSE; @@ -1030,26 +1029,25 @@ dnd_select_folder_get_info_cb (GtkFileSystemHandle *handle, if (data->selected || data->uris[++data->i] == NULL) { g_object_unref (data->button); - gtk_file_path_free (data->path); + g_object_unref (data->file); g_strfreev (data->uris); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); return; } - if (data->path) - gtk_file_path_free (data->path); + if (data->file) + g_object_unref (data->file); - data->path = gtk_file_system_uri_to_path (handle->file_system, - data->uris[data->i]); + data->file = g_file_new_for_uri (data->uris[data->i]); - data->button->priv->dnd_select_folder_handle = - gtk_file_system_get_info (handle->file_system, data->path, - GTK_FILE_INFO_IS_FOLDER, + data->button->priv->dnd_select_folder_cancellable = + gtk_file_system_get_info (data->file_system, data->file, + "standard::type", dnd_select_folder_get_info_cb, user_data); - g_object_unref (handle); + g_object_unref (cancellable); } static void @@ -1063,7 +1061,7 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget, { GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget); GtkFileChooserButtonPrivate *priv = button->priv; - GtkFilePath *path; + GFile *file; gchar *text; if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->drag_data_received != NULL) @@ -1093,27 +1091,28 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget, info->i = 0; info->uris = uris; info->selected = FALSE; + info->file_system = priv->fs; g_object_get (priv->dialog, "action", &info->action, NULL); - info->path = gtk_file_system_uri_to_path (priv->fs, - info->uris[info->i]); + info->file = g_file_new_for_uri (info->uris[info->i]); - if (priv->dnd_select_folder_handle) - gtk_file_system_cancel_operation (priv->dnd_select_folder_handle); + if (priv->dnd_select_folder_cancellable) + g_cancellable_cancel (priv->dnd_select_folder_cancellable); - priv->dnd_select_folder_handle = - gtk_file_system_get_info (priv->fs, info->path, - GTK_FILE_INFO_IS_FOLDER, + priv->dnd_select_folder_cancellable = + gtk_file_system_get_info (priv->fs, info->file, + "standard::type", dnd_select_folder_get_info_cb, info); } break; case TEXT_PLAIN: text = (char*) gtk_selection_data_get_text (data); - path = gtk_file_path_new_steal (text); - _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (priv->dialog), path, + file = g_file_new_for_uri (text); + _gtk_file_chooser_select_file (GTK_FILE_CHOOSER (priv->dialog), file, NULL); - gtk_file_path_free (path); + g_object_unref (file); + g_free (text); break; default: @@ -1212,26 +1211,25 @@ struct ChangeIconThemeData }; static void -change_icon_theme_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +change_icon_theme_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GdkPixbuf *pixbuf; struct ChangeIconThemeData *data = user_data; - if (!g_slist_find (data->button->priv->change_icon_theme_handles, handle)) + if (!g_slist_find (data->button->priv->change_icon_theme_cancellables, cancellable)) goto out; - data->button->priv->change_icon_theme_handles = - g_slist_remove (data->button->priv->change_icon_theme_handles, handle); + data->button->priv->change_icon_theme_cancellables = + g_slist_remove (data->button->priv->change_icon_theme_cancellables, cancellable); if (cancelled || error) goto out; - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->button), - data->button->priv->icon_size, NULL); + pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size); if (pixbuf) { @@ -1263,7 +1261,7 @@ out: gtk_tree_row_reference_free (data->row_ref); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static void @@ -1276,13 +1274,13 @@ change_icon_theme (GtkFileChooserButton *button) GSList *l; gint width = 0, height = 0; - for (l = button->priv->change_icon_theme_handles; l; l = l->next) + for (l = button->priv->change_icon_theme_cancellables; l; l = l->next) { - GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data); - gtk_file_system_cancel_operation (handle); + GCancellable *cancellable = G_CANCELLABLE (l->data); + g_cancellable_cancel (cancellable); } - g_slist_free (button->priv->change_icon_theme_handles); - button->priv->change_icon_theme_handles = NULL; + g_slist_free (button->priv->change_icon_theme_cancellables); + button->priv->change_icon_theme_cancellables = NULL; settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button))); @@ -1318,10 +1316,10 @@ change_icon_theme (GtkFileChooserButton *button) case ROW_TYPE_CURRENT_FOLDER: if (data) { - if (gtk_file_system_path_is_local (priv->fs, (GtkFilePath *)data)) + if (g_file_is_native (G_FILE (data))) { GtkTreePath *path; - GtkFileSystemHandle *handle; + GCancellable *cancellable; struct ChangeIconThemeData *info; info = g_new0 (struct ChangeIconThemeData, 1); @@ -1329,13 +1327,14 @@ change_icon_theme (GtkFileChooserButton *button) path = gtk_tree_model_get_path (priv->model, &iter); info->row_ref = gtk_tree_row_reference_new (priv->model, path); gtk_tree_path_free (path); - - handle = - gtk_file_system_get_info (priv->fs, data, GTK_FILE_INFO_ICON, + + cancellable = + gtk_file_system_get_info (priv->fs, data, + "standard::icon", change_icon_theme_get_info_cb, info); - button->priv->change_icon_theme_handles = - g_slist_append (button->priv->change_icon_theme_handles, handle); + button->priv->change_icon_theme_cancellables = + g_slist_append (button->priv->change_icon_theme_cancellables, cancellable); pixbuf = NULL; } else @@ -1353,7 +1352,7 @@ change_icon_theme (GtkFileChooserButton *button) break; case ROW_TYPE_VOLUME: if (data) - pixbuf = gtk_file_system_volume_render_icon (priv->fs, data, + pixbuf = gtk_file_system_volume_render_icon (data, GTK_WIDGET (button), priv->icon_size, NULL); @@ -1430,17 +1429,18 @@ struct SetDisplayNameData }; static void -set_info_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer callback_data) +set_info_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer callback_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GdkPixbuf *pixbuf; GtkTreePath *path; GtkTreeIter iter; - GtkFileSystemHandle *model_handle; + GCancellable *model_cancellable; struct SetDisplayNameData *data = callback_data; + gboolean is_folder; if (!data->button->priv->model) /* button got destroyed */ @@ -1448,37 +1448,38 @@ set_info_get_info_cb (GtkFileSystemHandle *handle, path = gtk_tree_row_reference_get_path (data->row_ref); if (!path) - /* Handle doesn't exist anymore in the model */ + /* Cancellable doesn't exist anymore in the model */ goto out; gtk_tree_model_get_iter (data->button->priv->model, &iter, path); gtk_tree_path_free (path); - /* Validate the handle */ + /* Validate the cancellable */ gtk_tree_model_get (data->button->priv->model, &iter, - HANDLE_COLUMN, &model_handle, + CANCELLABLE_COLUMN, &model_cancellable, -1); - if (handle != model_handle) + if (cancellable != model_cancellable) goto out; gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, - HANDLE_COLUMN, NULL, + CANCELLABLE_COLUMN, NULL, -1); if (cancelled || error) /* There was an error, leave the fallback name in there */ goto out; - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->button), - data->button->priv->icon_size, NULL); + pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size); if (!data->label) - data->label = g_strdup (gtk_file_info_get_display_name (info)); + data->label = g_strdup (g_file_info_get_display_name (info)); + + is_folder = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, ICON_COLUMN, pixbuf, DISPLAY_NAME_COLUMN, data->label, - IS_FOLDER_COLUMN, gtk_file_info_get_is_folder (info), + IS_FOLDER_COLUMN, is_folder, -1); if (pixbuf) @@ -1490,32 +1491,32 @@ out: gtk_tree_row_reference_free (data->row_ref); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static void -set_info_for_path_at_iter (GtkFileChooserButton *button, - const GtkFilePath *path, +set_info_for_file_at_iter (GtkFileChooserButton *button, + GFile *file, GtkTreeIter *iter) { struct SetDisplayNameData *data; GtkTreePath *tree_path; - GtkFileSystemHandle *handle; + GCancellable *cancellable; data = g_new0 (struct SetDisplayNameData, 1); data->button = g_object_ref (button); - data->label = gtk_file_system_get_bookmark_label (button->priv->fs, path); + data->label = gtk_file_system_get_bookmark_label (button->priv->fs, file); tree_path = gtk_tree_model_get_path (button->priv->model, iter); data->row_ref = gtk_tree_row_reference_new (button->priv->model, tree_path); gtk_tree_path_free (tree_path); - handle = gtk_file_system_get_info (button->priv->fs, path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_ICON, - set_info_get_info_cb, data); + cancellable = gtk_file_system_get_info (button->priv->fs, file, + "standard::type,standard::icon,standard::display-name", + set_info_get_info_cb, data); gtk_list_store_set (GTK_LIST_STORE (button->priv->model), iter, - HANDLE_COLUMN, handle, + CANCELLABLE_COLUMN, cancellable, -1); } @@ -1579,16 +1580,16 @@ model_free_row_data (GtkFileChooserButton *button, { gchar type; gpointer data; - GtkFileSystemHandle *handle; + GCancellable *cancellable; gtk_tree_model_get (button->priv->model, iter, TYPE_COLUMN, &type, DATA_COLUMN, &data, - HANDLE_COLUMN, &handle, + CANCELLABLE_COLUMN, &cancellable, -1); - if (handle) - gtk_file_system_cancel_operation (handle); + if (cancellable) + g_cancellable_cancel (cancellable); switch (type) { @@ -1596,10 +1597,10 @@ model_free_row_data (GtkFileChooserButton *button, case ROW_TYPE_SHORTCUT: case ROW_TYPE_BOOKMARK: case ROW_TYPE_CURRENT_FOLDER: - gtk_file_path_free (data); + g_object_unref (data); break; case ROW_TYPE_VOLUME: - gtk_file_system_volume_free (button->priv->fs, data); + gtk_file_system_volume_free (data); break; default: break; @@ -1607,16 +1608,16 @@ model_free_row_data (GtkFileChooserButton *button, } static void -model_add_special_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +model_add_special_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GtkTreeIter iter; GtkTreePath *path; GdkPixbuf *pixbuf; - GtkFileSystemHandle *model_handle; + GCancellable *model_cancellable; struct ChangeIconThemeData *data = user_data; gchar *name; @@ -1626,27 +1627,26 @@ model_add_special_get_info_cb (GtkFileSystemHandle *handle, path = gtk_tree_row_reference_get_path (data->row_ref); if (!path) - /* Handle doesn't exist anymore in the model */ + /* Cancellable doesn't exist anymore in the model */ goto out; gtk_tree_model_get_iter (data->button->priv->model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (data->button->priv->model, &iter, - HANDLE_COLUMN, &model_handle, + CANCELLABLE_COLUMN, &model_cancellable, -1); - if (handle != model_handle) + if (cancellable != model_cancellable) goto out; gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, - HANDLE_COLUMN, NULL, + CANCELLABLE_COLUMN, NULL, -1); if (cancelled || error) goto out; - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->button), - data->button->priv->icon_size, NULL); + pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size); if (pixbuf) { @@ -1661,7 +1661,7 @@ model_add_special_get_info_cb (GtkFileSystemHandle *handle, -1); if (!name) gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter, - DISPLAY_NAME_COLUMN, gtk_file_info_get_display_name (info), + DISPLAY_NAME_COLUMN, g_file_info_get_display_name (info), -1); g_free (name); @@ -1670,7 +1670,7 @@ out: gtk_tree_row_reference_free (data->row_ref); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static inline void @@ -1680,7 +1680,7 @@ model_add_special (GtkFileChooserButton *button) const gchar *desktopdir; GtkListStore *store; GtkTreeIter iter; - GtkFilePath *path; + GFile *file; gint pos; store = GTK_LIST_STORE (button->priv->model); @@ -1691,10 +1691,10 @@ model_add_special (GtkFileChooserButton *button) if (homedir) { GtkTreePath *tree_path; - GtkFileSystemHandle *handle; + GCancellable *cancellable; struct ChangeIconThemeData *info; - path = gtk_file_system_filename_to_path (button->priv->fs, homedir); + file = g_file_new_for_path (homedir); gtk_list_store_insert (store, &iter, pos); pos++; @@ -1705,17 +1705,17 @@ model_add_special (GtkFileChooserButton *button) tree_path); gtk_tree_path_free (tree_path); - handle = gtk_file_system_get_info (button->priv->fs, path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON, - model_add_special_get_info_cb, info); + cancellable = gtk_file_system_get_info (button->priv->fs, file, + "standard::icon,standard::display-name", + model_add_special_get_info_cb, info); gtk_list_store_set (store, &iter, ICON_COLUMN, NULL, DISPLAY_NAME_COLUMN, NULL, TYPE_COLUMN, ROW_TYPE_SPECIAL, - DATA_COLUMN, path, + DATA_COLUMN, file, IS_FOLDER_COLUMN, TRUE, - HANDLE_COLUMN, handle, + CANCELLABLE_COLUMN, cancellable, -1); button->priv->n_special++; @@ -1726,10 +1726,10 @@ model_add_special (GtkFileChooserButton *button) if (desktopdir) { GtkTreePath *tree_path; - GtkFileSystemHandle *handle; + GCancellable *cancellable; struct ChangeIconThemeData *info; - path = gtk_file_system_filename_to_path (button->priv->fs, desktopdir); + file = g_file_new_for_path (desktopdir); gtk_list_store_insert (store, &iter, pos); pos++; @@ -1740,17 +1740,17 @@ model_add_special (GtkFileChooserButton *button) tree_path); gtk_tree_path_free (tree_path); - handle = gtk_file_system_get_info (button->priv->fs, path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON, - model_add_special_get_info_cb, info); + cancellable = gtk_file_system_get_info (button->priv->fs, file, + "standard::icon,standard::display-name", + model_add_special_get_info_cb, info); gtk_list_store_set (store, &iter, TYPE_COLUMN, ROW_TYPE_SPECIAL, ICON_COLUMN, NULL, DISPLAY_NAME_COLUMN, _(DESKTOP_DISPLAY_NAME), - DATA_COLUMN, path, + DATA_COLUMN, file, IS_FOLDER_COLUMN, TRUE, - HANDLE_COLUMN, handle, + CANCELLABLE_COLUMN, cancellable, -1); button->priv->n_special++; @@ -1786,31 +1786,24 @@ model_add_volumes (GtkFileChooserButton *button, if (local_only) { - if (gtk_file_system_volume_get_is_mounted (file_system, volume)) + if (gtk_file_system_volume_is_mounted (volume)) { - GtkFilePath *base_path; + GFile *base_file; - base_path = gtk_file_system_volume_get_base_path (file_system, volume); - if (base_path != NULL) + base_file = gtk_file_system_volume_get_root (volume); + if (base_file != NULL && !g_file_is_native (base_file)) { - gboolean is_local = gtk_file_system_path_is_local (file_system, base_path); - gtk_file_path_free (base_path); - - if (!is_local) - { - gtk_file_system_volume_free (file_system, volume); - continue; - } + gtk_file_system_volume_free (volume); + continue; } } } - pixbuf = gtk_file_system_volume_render_icon (file_system, - volume, + pixbuf = gtk_file_system_volume_render_icon (volume, GTK_WIDGET (button), button->priv->icon_size, NULL); - display_name = gtk_file_system_volume_get_display_name (file_system, volume); + display_name = gtk_file_system_volume_get_display_name (volume); gtk_list_store_insert (store, &iter, pos); gtk_list_store_set (store, &iter, @@ -1830,7 +1823,7 @@ model_add_volumes (GtkFileChooserButton *button, } } -extern gchar * _gtk_file_chooser_label_for_uri (const gchar *uri); +extern gchar * _gtk_file_chooser_label_for_file (const gchar *uri); static void model_add_bookmarks (GtkFileChooserButton *button, @@ -1851,21 +1844,21 @@ model_add_bookmarks (GtkFileChooserButton *button, for (l = bookmarks; l; l = l->next) { - GtkFilePath *path; + GFile *file; - path = l->data; + file = l->data; - if (gtk_file_system_path_is_local (button->priv->fs, path)) + if (g_file_is_native (file)) { gtk_list_store_insert (store, &iter, pos); gtk_list_store_set (store, &iter, ICON_COLUMN, NULL, DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME), TYPE_COLUMN, ROW_TYPE_BOOKMARK, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, FALSE, -1); - set_info_for_path_at_iter (button, path, &iter); + set_info_for_file_at_iter (button, file, &iter); } else { @@ -1881,15 +1874,9 @@ model_add_bookmarks (GtkFileChooserButton *button, * If we switch to a better bookmarks file format (XBEL), we * should use mime info to get a better icon. */ - label = gtk_file_system_get_bookmark_label (button->priv->fs, path); + label = gtk_file_system_get_bookmark_label (button->priv->fs, file); if (!label) - { - gchar *uri; - - uri = gtk_file_system_path_to_uri (button->priv->fs, path); - label = _gtk_file_chooser_label_for_uri (uri); - g_free (uri); - } + label = _gtk_file_chooser_label_for_file (file); icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button))); pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-share", @@ -1900,7 +1887,7 @@ model_add_bookmarks (GtkFileChooserButton *button, ICON_COLUMN, pixbuf, DISPLAY_NAME_COLUMN, label, TYPE_COLUMN, ROW_TYPE_BOOKMARK, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, TRUE, -1); @@ -1931,13 +1918,13 @@ model_add_bookmarks (GtkFileChooserButton *button, static void model_update_current_folder (GtkFileChooserButton *button, - const GtkFilePath *path) + GFile *file) { GtkListStore *store; GtkTreeIter iter; gint pos; - if (!path) + if (!file) return; store = GTK_LIST_STORE (button->priv->model); @@ -1968,16 +1955,16 @@ model_update_current_folder (GtkFileChooserButton *button, model_free_row_data (button, &iter); } - if (gtk_file_system_path_is_local (button->priv->fs, path)) + if (g_file_is_native (file)) { gtk_list_store_set (store, &iter, ICON_COLUMN, NULL, DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME), TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, FALSE, -1); - set_info_for_path_at_iter (button, path, &iter); + set_info_for_file_at_iter (button, file, &iter); } else { @@ -1990,18 +1977,13 @@ model_update_current_folder (GtkFileChooserButton *button, * If we switch to a better bookmarks file format (XBEL), we * should use mime info to get a better icon. */ - label = gtk_file_system_get_bookmark_label (button->priv->fs, path); + label = gtk_file_system_get_bookmark_label (button->priv->fs, file); if (!label) - { - gchar *uri; - - uri = gtk_file_system_path_to_uri (button->priv->fs, path); - label = _gtk_file_chooser_label_for_uri (uri); - g_free (uri); - } - + label = _gtk_file_chooser_label_for_file (file); + icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button))); - if (gtk_file_system_path_is_local (button->priv->fs, path)) + + if (g_file_is_native (file)) pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-directory", button->priv->icon_size, 0, NULL); else @@ -2012,10 +1994,10 @@ model_update_current_folder (GtkFileChooserButton *button, ICON_COLUMN, pixbuf, DISPLAY_NAME_COLUMN, label, TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER, - DATA_COLUMN, gtk_file_path_copy (path), + DATA_COLUMN, g_object_ref (file), IS_FOLDER_COLUMN, TRUE, -1); - + g_free (label); g_object_unref (pixbuf); } @@ -2080,15 +2062,15 @@ model_remove_rows (GtkFileChooserButton *button, /* Filter Model */ static inline gboolean -test_if_path_is_visible (GtkFileSystem *fs, - const GtkFilePath *path, - gboolean local_only, - gboolean is_folder) +test_if_file_is_visible (GtkFileSystem *fs, + GFile *file, + gboolean local_only, + gboolean is_folder) { - if (!path) + if (!file) return FALSE; - if (local_only && !gtk_file_system_path_is_local (fs, path)) + if (local_only && !g_file_is_native (file)) return FALSE; if (!is_folder) @@ -2126,25 +2108,22 @@ filter_model_visible_func (GtkTreeModel *model, case ROW_TYPE_SPECIAL: case ROW_TYPE_SHORTCUT: case ROW_TYPE_BOOKMARK: - retval = test_if_path_is_visible (priv->fs, data, local_only, is_folder); + retval = test_if_file_is_visible (priv->fs, data, local_only, is_folder); break; case ROW_TYPE_VOLUME: { retval = TRUE; if (local_only) { - if (gtk_file_system_volume_get_is_mounted (priv->fs, data)) + if (gtk_file_system_volume_is_mounted (data)) { - GtkFilePath *base_path; - - base_path = gtk_file_system_volume_get_base_path (priv->fs, data); - if (base_path) - { - gboolean is_local = gtk_file_system_path_is_local (priv->fs, base_path); - - gtk_file_path_free (base_path); + GFile *base_file; - if (!is_local) + base_file = gtk_file_system_volume_get_root (data); + + if (base_file) + { + if (!g_file_is_native (base_file)) retval = FALSE; } else @@ -2200,13 +2179,13 @@ static void update_combo_box (GtkFileChooserButton *button) { GtkFileChooserButtonPrivate *priv = button->priv; - GSList *paths; + GSList *files; GtkTreeIter iter; gboolean row_found; gtk_tree_model_get_iter_first (priv->filter_model, &iter); - paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog)); + files = _gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->dialog)); row_found = FALSE; @@ -2229,21 +2208,21 @@ update_combo_box (GtkFileChooserButton *button) case ROW_TYPE_SHORTCUT: case ROW_TYPE_BOOKMARK: case ROW_TYPE_CURRENT_FOLDER: - row_found = (paths && - paths->data && - gtk_file_path_compare (data, paths->data) == 0); + row_found = (files && + files->data && + g_file_equal (data, files->data)); break; case ROW_TYPE_VOLUME: { - GtkFilePath *base_path; + GFile *base_file; - base_path = gtk_file_system_volume_get_base_path (priv->fs, data); - if (base_path) + base_file = gtk_file_system_volume_get_root (data); + if (base_file) { - row_found = (paths && - paths->data && - gtk_file_path_compare (base_path, paths->data) == 0); - gtk_file_path_free (base_path); + row_found = (files && + files->data && + g_file_equal (base_file, files->data)); + g_object_unref (base_file); } } break; @@ -2264,12 +2243,12 @@ update_combo_box (GtkFileChooserButton *button) while (!row_found && gtk_tree_model_iter_next (priv->filter_model, &iter)); /* If it hasn't been found already, update & select the current-folder row. */ - if (!row_found && paths && paths->data) + if (!row_found && files && files->data) { GtkTreeIter filter_iter; gint pos; - model_update_current_folder (button, paths->data); + model_update_current_folder (button, files->data); gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER); @@ -2283,33 +2262,34 @@ update_combo_box (GtkFileChooserButton *button) g_signal_handler_unblock (priv->combo_box, priv->combo_box_changed_id); } - gtk_file_paths_free (paths); + g_slist_foreach (files, (GFunc) g_object_unref, NULL); + g_slist_free (files); } /* Button */ static void -update_label_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer data) +update_label_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GdkPixbuf *pixbuf; GtkFileChooserButton *button = data; GtkFileChooserButtonPrivate *priv = button->priv; - if (handle != priv->update_button_handle) + if (cancellable != priv->update_button_cancellable) goto out; - priv->update_button_handle = NULL; + priv->update_button_cancellable = NULL; if (cancelled || error) goto out; - gtk_label_set_text (GTK_LABEL (priv->label), gtk_file_info_get_display_name (info)); + gtk_label_set_text (GTK_LABEL (priv->label), g_file_info_get_display_name (info)); + + pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (priv->image), priv->icon_size); - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (priv->image), - priv->icon_size, NULL); if (!pixbuf) pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)), FALLBACK_ICON_NAME, @@ -2321,7 +2301,7 @@ update_label_get_info_cb (GtkFileSystemHandle *handle, out: g_object_unref (button); - g_object_unref (handle); + g_object_unref (cancellable); } static void @@ -2330,55 +2310,54 @@ update_label_and_image (GtkFileChooserButton *button) GtkFileChooserButtonPrivate *priv = button->priv; GdkPixbuf *pixbuf; gchar *label_text; - GSList *paths; + GSList *files; - paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog)); + files = _gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->dialog)); label_text = NULL; pixbuf = NULL; - if (paths && paths->data) + if (files && files->data) { - GtkFilePath *path; + GFile *file; GtkFileSystemVolume *volume = NULL; - - path = paths->data; - volume = gtk_file_system_get_volume_for_path (priv->fs, path); + file = files->data; + + volume = gtk_file_system_get_volume_for_file (priv->fs, file); if (volume) { - GtkFilePath *base_path; + GFile *base_file; - base_path = gtk_file_system_volume_get_base_path (priv->fs, volume); - if (base_path && gtk_file_path_compare (base_path, path) == 0) + base_file = gtk_file_system_volume_get_root (volume); + if (base_file && g_file_equal (base_file, file)) { - label_text = gtk_file_system_volume_get_display_name (priv->fs, - volume); - pixbuf = gtk_file_system_volume_render_icon (priv->fs, volume, + label_text = gtk_file_system_volume_get_display_name (volume); + pixbuf = gtk_file_system_volume_render_icon (volume, GTK_WIDGET (button), priv->icon_size, NULL); } - if (base_path) - gtk_file_path_free (base_path); + if (base_file) + g_object_unref (base_file); - gtk_file_system_volume_free (priv->fs, volume); + gtk_file_system_volume_free (volume); if (label_text) goto out; } - if (priv->update_button_handle) + if (priv->update_button_cancellable) { - gtk_file_system_cancel_operation (priv->update_button_handle); - priv->update_button_handle = NULL; + g_cancellable_cancel (priv->update_button_cancellable); + priv->update_button_cancellable = NULL; } - - if (gtk_file_system_path_is_local (priv->fs, path)) + + if (g_file_is_native (file)) { - priv->update_button_handle = - gtk_file_system_get_info (priv->fs, path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON, + priv->update_button_cancellable = + gtk_file_system_get_info (priv->fs, file, + "standard::icon,standard::display-name", update_label_get_info_cb, g_object_ref (button)); } @@ -2386,7 +2365,7 @@ update_label_and_image (GtkFileChooserButton *button) { GdkPixbuf *pixbuf; - label_text = gtk_file_system_get_bookmark_label (button->priv->fs, path); + label_text = gtk_file_system_get_bookmark_label (button->priv->fs, file); pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)), "gnome-fs-regular", @@ -2399,7 +2378,8 @@ update_label_and_image (GtkFileChooserButton *button) } } out: - gtk_file_paths_free (paths); + g_slist_foreach (files, (GFunc) g_object_unref, NULL); + g_slist_free (files); if (label_text) { @@ -2456,7 +2436,8 @@ fs_bookmarks_changed_cb (GtkFileSystem *fs, priv->has_bookmark_separator = FALSE; priv->n_bookmarks = 0; model_add_bookmarks (user_data, bookmarks); - gtk_file_paths_free (bookmarks); + g_slist_foreach (bookmarks, (GFunc) g_object_unref, NULL); + g_slist_free (bookmarks); gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model)); @@ -2491,7 +2472,7 @@ open_dialog (GtkFileChooserButton *button) if (!priv->active) { - GSList *paths; + GSList *files; g_signal_handler_block (priv->dialog, priv->dialog_folder_changed_id); @@ -2499,13 +2480,14 @@ open_dialog (GtkFileChooserButton *button) priv->dialog_file_activated_id); g_signal_handler_block (priv->dialog, priv->dialog_selection_changed_id); - paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog)); - if (paths) + files = _gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->dialog)); + if (files) { - if (paths->data) - priv->old_path = gtk_file_path_copy (paths->data); + if (files->data) + priv->old_file = g_object_ref (files->data); - gtk_file_paths_free (paths); + g_slist_foreach (files, (GFunc) g_object_unref, NULL); + g_slist_free (files); } priv->active = TRUE; @@ -2545,20 +2527,20 @@ combo_box_changed_cb (GtkComboBox *combo_box, case ROW_TYPE_CURRENT_FOLDER: gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog)); if (data) - _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog), + _gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (priv->dialog), data, NULL); break; case ROW_TYPE_VOLUME: { - GtkFilePath *base_path; + GFile *base_file; gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog)); - base_path = gtk_file_system_volume_get_base_path (priv->fs, data); - if (base_path) + base_file = gtk_file_system_volume_get_root (data); + if (base_file) { - _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog), - base_path, NULL); - gtk_file_path_free (base_path); + _gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (priv->dialog), + base_file, NULL); + g_object_unref (base_file); } } break; @@ -2647,9 +2629,8 @@ dialog_notify_cb (GObject *dialog, /* If the path isn't local but we're in local-only mode now, remove * the custom-folder row */ - if (data && - (!gtk_file_system_path_is_local (priv->fs, data) && - gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (priv->dialog)))) + if (data && g_file_is_native (G_FILE (data)) && + gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (priv->dialog))) { pos--; model_remove_rows (user_data, pos, 2); @@ -2685,17 +2666,17 @@ dialog_response_cb (GtkDialog *dialog, g_signal_emit_by_name (user_data, "current-folder-changed"); g_signal_emit_by_name (user_data, "selection-changed"); } - else if (priv->old_path) + else if (priv->old_file) { switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog))) { case GTK_FILE_CHOOSER_ACTION_OPEN: - _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (dialog), priv->old_path, + _gtk_file_chooser_select_file (GTK_FILE_CHOOSER (dialog), priv->old_file, NULL); break; case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: - _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (dialog), - priv->old_path, NULL); + _gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog), + priv->old_file, NULL); break; default: g_assert_not_reached (); @@ -2705,10 +2686,10 @@ dialog_response_cb (GtkDialog *dialog, else gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (dialog)); - if (priv->old_path) + if (priv->old_file) { - gtk_file_path_free (priv->old_path); - priv->old_path = NULL; + g_object_unref (priv->old_file); + priv->old_file = NULL; } update_label_and_image (user_data); diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index dcc28642a..94149d01a 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -40,6 +40,7 @@ #include "gtkfilechoosersettings.h" #include "gtkfilechooserutils.h" #include "gtkfilechooser.h" +#include "gtkfilesystem.h" #include "gtkfilesystemmodel.h" #include "gtkframe.h" #include "gtkhbox.h" @@ -53,6 +54,7 @@ #include "gtkmarshalers.h" #include "gtkmenuitem.h" #include "gtkmessagedialog.h" +#include "gtkmountoperation.h" #include "gtkpathbar.h" #include "gtkprivate.h" #include "gtkradiobutton.h" @@ -70,13 +72,6 @@ #include "gtktypebuiltins.h" #include "gtkvbox.h" -#if defined (G_OS_UNIX) -#include "gtkfilesystemunix.h" -#elif defined (G_OS_WIN32) -#include -#include "gtkfilesystemwin32.h" -#endif - #include "gtkalias.h" #include @@ -184,12 +179,12 @@ enum { SHORTCUTS_COL_TYPE, SHORTCUTS_COL_REMOVABLE, SHORTCUTS_COL_PIXBUF_VISIBLE, - SHORTCUTS_COL_HANDLE, + SHORTCUTS_COL_CANCELLABLE, SHORTCUTS_COL_NUM_COLUMNS }; typedef enum { - SHORTCUT_TYPE_PATH, + SHORTCUT_TYPE_FILE, SHORTCUT_TYPE_VOLUME, SHORTCUT_TYPE_SEPARATOR, SHORTCUT_TYPE_SEARCH, @@ -208,11 +203,11 @@ enum { * Keep this in sync with search_setup_model() */ enum { - SEARCH_MODEL_COL_PATH, + SEARCH_MODEL_COL_FILE, SEARCH_MODEL_COL_DISPLAY_NAME, SEARCH_MODEL_COL_COLLATION_KEY, SEARCH_MODEL_COL_STAT, - SEARCH_MODEL_COL_HANDLE, + SEARCH_MODEL_COL_CANCELLABLE, SEARCH_MODEL_COL_PIXBUF, SEARCH_MODEL_COL_MIME_TYPE, SEARCH_MODEL_COL_IS_FOLDER, @@ -220,11 +215,11 @@ enum { }; enum { - RECENT_MODEL_COL_PATH, + RECENT_MODEL_COL_FILE, RECENT_MODEL_COL_DISPLAY_NAME, RECENT_MODEL_COL_INFO, RECENT_MODEL_COL_IS_FOLDER, - RECENT_MODEL_COL_HANDLE, + RECENT_MODEL_COL_CANCELLABLE, RECENT_MODEL_COL_NUM_COLUMNS }; @@ -330,25 +325,25 @@ static void gtk_file_chooser_default_size_allocate (GtkWidget * GtkAllocation *allocation); static gboolean gtk_file_chooser_default_set_current_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *folder, GError **error); static gboolean gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *folder, gboolean keep_trail, gboolean clear_entry, GError **error); -static GtkFilePath * gtk_file_chooser_default_get_current_folder (GtkFileChooser *chooser); +static GFile * gtk_file_chooser_default_get_current_folder (GtkFileChooser *chooser); static void gtk_file_chooser_default_set_current_name (GtkFileChooser *chooser, const gchar *name); -static gboolean gtk_file_chooser_default_select_path (GtkFileChooser *chooser, - const GtkFilePath *path, +static gboolean gtk_file_chooser_default_select_file (GtkFileChooser *chooser, + GFile *file, GError **error); -static void gtk_file_chooser_default_unselect_path (GtkFileChooser *chooser, - const GtkFilePath *path); +static void gtk_file_chooser_default_unselect_file (GtkFileChooser *chooser, + GFile *file); static void gtk_file_chooser_default_select_all (GtkFileChooser *chooser); static void gtk_file_chooser_default_unselect_all (GtkFileChooser *chooser); -static GSList * gtk_file_chooser_default_get_paths (GtkFileChooser *chooser); -static GtkFilePath * gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser); +static GSList * gtk_file_chooser_default_get_files (GtkFileChooser *chooser); +static GFile * gtk_file_chooser_default_get_preview_file (GtkFileChooser *chooser); static GtkFileSystem *gtk_file_chooser_default_get_file_system (GtkFileChooser *chooser); static void gtk_file_chooser_default_add_filter (GtkFileChooser *chooser, GtkFileFilter *filter); @@ -356,10 +351,10 @@ static void gtk_file_chooser_default_remove_filter (GtkFileCh GtkFileFilter *filter); static GSList * gtk_file_chooser_default_list_filters (GtkFileChooser *chooser); static gboolean gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); static gboolean gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); static GSList * gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser); @@ -407,7 +402,7 @@ static void shortcuts_activate_iter (GtkFileChooserDefault *impl, static int shortcuts_get_index (GtkFileChooserDefault *impl, ShortcutsIndex where); static int shortcut_find_position (GtkFileChooserDefault *impl, - const GtkFilePath *path); + GFile *file); static void bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl); @@ -430,8 +425,8 @@ static void select_func (GtkFileSystemModel *model, gpointer user_data); static void path_bar_clicked (GtkPathBar *path_bar, - GtkFilePath *file_path, - GtkFilePath *child_path, + GFile *file, + GFile *child, gboolean child_is_hidden, GtkFileChooserDefault *impl); @@ -465,8 +460,8 @@ static void list_mtime_data_func (GtkTreeViewColumn *tree_column, GtkTreeIter *iter, gpointer data); -static const GtkFileInfo *get_list_file_info (GtkFileChooserDefault *impl, - GtkTreeIter *iter); +static GFileInfo *get_list_file_info (GtkFileChooserDefault *impl, + GtkTreeIter *iter); static void load_remove_timer (GtkFileChooserDefault *impl); static void browse_files_center_selected_row (GtkFileChooserDefault *impl); @@ -481,7 +476,7 @@ static void search_clear_model (GtkFileChooserDefault *impl, gboolean remove_from_treeview); static gboolean search_should_respond (GtkFileChooserDefault *impl); static void search_switch_to_browse_mode (GtkFileChooserDefault *impl); -static GSList *search_get_selected_paths (GtkFileChooserDefault *impl); +static GSList *search_get_selected_files (GtkFileChooserDefault *impl); static void search_entry_activate_cb (GtkEntry *entry, gpointer data); static void settings_load (GtkFileChooserDefault *impl); @@ -495,10 +490,12 @@ static void recent_clear_model (GtkFileChooserDefault *impl, gboolean remove_from_treeview); static gboolean recent_should_respond (GtkFileChooserDefault *impl); static void recent_switch_to_browse_mode (GtkFileChooserDefault *impl); -static GSList * recent_get_selected_paths (GtkFileChooserDefault *impl); +static GSList * recent_get_selected_files (GtkFileChooserDefault *impl); static void recent_get_valid_child_iter (GtkFileChooserDefault *impl, GtkTreeIter *child_iter, GtkTreeIter *iter); +static void set_file_system_backend (GtkFileChooserDefault *impl); + @@ -788,12 +785,12 @@ _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class) static void gtk_file_chooser_default_iface_init (GtkFileChooserIface *iface) { - iface->select_path = gtk_file_chooser_default_select_path; - iface->unselect_path = gtk_file_chooser_default_unselect_path; + iface->select_file = gtk_file_chooser_default_select_file; + iface->unselect_file = gtk_file_chooser_default_unselect_file; iface->select_all = gtk_file_chooser_default_select_all; iface->unselect_all = gtk_file_chooser_default_unselect_all; - iface->get_paths = gtk_file_chooser_default_get_paths; - iface->get_preview_path = gtk_file_chooser_default_get_preview_path; + iface->get_files = gtk_file_chooser_default_get_files; + iface->get_preview_file = gtk_file_chooser_default_get_preview_file; iface->get_file_system = gtk_file_chooser_default_get_file_system; iface->set_current_folder = gtk_file_chooser_default_set_current_folder; iface->get_current_folder = gtk_file_chooser_default_get_current_folder; @@ -829,7 +826,7 @@ _gtk_file_chooser_default_init (GtkFileChooserDefault *impl) impl->icon_size = FALLBACK_ICON_SIZE; impl->load_state = LOAD_EMPTY; impl->reload_state = RELOAD_EMPTY; - impl->pending_select_paths = NULL; + impl->pending_select_files = NULL; impl->location_mode = LOCATION_MODE_PATH_BAR; impl->operation_mode = OPERATION_MODE_BROWSE; @@ -838,6 +835,8 @@ _gtk_file_chooser_default_init (GtkFileChooserDefault *impl) impl->tooltips = gtk_tooltips_new (); g_object_ref_sink (impl->tooltips); + set_file_system_backend (impl); + profile_end ("end", NULL); } @@ -848,18 +847,18 @@ shortcuts_free_row_data (GtkFileChooserDefault *impl, { gpointer col_data; ShortcutType shortcut_type; - GtkFileSystemHandle *handle; + GCancellable *cancellable; gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter, SHORTCUTS_COL_DATA, &col_data, SHORTCUTS_COL_TYPE, &shortcut_type, - SHORTCUTS_COL_HANDLE, &handle, + SHORTCUTS_COL_CANCELLABLE, &cancellable, -1); - if (handle) - gtk_file_system_cancel_operation (handle); + if (cancellable) + g_cancellable_cancel (cancellable); - if (!(shortcut_type == SHORTCUT_TYPE_PATH || + if (!(shortcut_type == SHORTCUT_TYPE_FILE || shortcut_type == SHORTCUT_TYPE_VOLUME) || !col_data) return; @@ -869,16 +868,16 @@ shortcuts_free_row_data (GtkFileChooserDefault *impl, GtkFileSystemVolume *volume; volume = col_data; - gtk_file_system_volume_free (impl->file_system, volume); + gtk_file_system_volume_free (volume); } else { - GtkFilePath *path; + GFile *file; - g_assert (shortcut_type == SHORTCUT_TYPE_PATH); + g_assert (shortcut_type == SHORTCUT_TYPE_FILE); - path = col_data; - gtk_file_path_free (path); + file = col_data; + g_object_unref (file); } } @@ -903,28 +902,19 @@ shortcuts_free (GtkFileChooserDefault *impl) } static void -pending_select_paths_free (GtkFileChooserDefault *impl) +pending_select_files_free (GtkFileChooserDefault *impl) { - GSList *l; - - for (l = impl->pending_select_paths; l; l = l->next) - { - GtkFilePath *path; - - path = l->data; - gtk_file_path_free (path); - } - - g_slist_free (impl->pending_select_paths); - impl->pending_select_paths = NULL; + g_slist_foreach (impl->pending_select_files, (GFunc) g_object_unref, NULL); + g_slist_free (impl->pending_select_files); + impl->pending_select_files = NULL; } static void -pending_select_paths_add (GtkFileChooserDefault *impl, - const GtkFilePath *path) +pending_select_files_add (GtkFileChooserDefault *impl, + GFile *file) { - impl->pending_select_paths = - g_slist_prepend (impl->pending_select_paths, gtk_file_path_copy (path)); + impl->pending_select_files = + g_slist_prepend (impl->pending_select_files, g_object_ref (file)); } /* Used from gtk_tree_selection_selected_foreach() */ @@ -936,21 +926,21 @@ store_selection_foreach (GtkTreeModel *model, { GtkFileChooserDefault *impl; GtkTreeIter child_iter; - const GtkFilePath *file_path; + GFile *file; impl = GTK_FILE_CHOOSER_DEFAULT (data); gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, iter); - file_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter); - pending_select_paths_add (impl, file_path); + file = _gtk_file_system_model_get_file (impl->browse_files_model, &child_iter); + pending_select_files_add (impl, file); } /* Stores the current selection in the list of paths to select; this is used to * preserve the selection when reloading the current folder. */ static void -pending_select_paths_store_selection (GtkFileChooserDefault *impl) +pending_select_files_store_selection (GtkFileChooserDefault *impl) { GtkTreeSelection *selection; @@ -988,14 +978,14 @@ gtk_file_chooser_default_finalize (GObject *object) if (impl->current_filter) g_object_unref (impl->current_filter); - if (impl->current_volume_path) - gtk_file_path_free (impl->current_volume_path); + if (impl->current_volume_file) + g_object_unref (impl->current_volume_file); if (impl->current_folder) - gtk_file_path_free (impl->current_folder); + g_object_unref (impl->current_folder); - if (impl->preview_path) - gtk_file_path_free (impl->preview_path); + if (impl->preview_file) + g_object_unref (impl->preview_file); load_remove_timer (impl); @@ -1068,7 +1058,7 @@ error_message (GtkFileChooserDefault *impl, static void error_dialog (GtkFileChooserDefault *impl, const char *msg, - const GtkFilePath *path, + GFile *file, GError *error) { if (error) @@ -1076,8 +1066,8 @@ error_dialog (GtkFileChooserDefault *impl, char *uri = NULL; char *text; - if (path) - uri = gtk_file_system_path_to_uri (impl->file_system, path); + if (file) + uri = g_file_get_uri (file); text = g_strdup_printf (msg, uri); error_message (impl, text, error->message); g_free (text); @@ -1091,45 +1081,45 @@ error_dialog (GtkFileChooserDefault *impl, */ static void error_getting_info_dialog (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, GError *error) { error_dialog (impl, _("Could not retrieve information about the file"), - path, error); + file, error); } /* Shows an error dialog about not being able to add a bookmark */ static void error_adding_bookmark_dialog (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, GError *error) { error_dialog (impl, _("Could not add a bookmark"), - path, error); + file, error); } /* Shows an error dialog about not being able to remove a bookmark */ static void error_removing_bookmark_dialog (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, GError *error) { error_dialog (impl, _("Could not remove bookmark"), - path, error); + file, error); } /* Shows an error dialog about not being able to create a folder */ static void error_creating_folder_dialog (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, GError *error) { error_dialog (impl, _("The folder could not be created"), - path, error); + file, error); } /* Shows an error about not being able to create a folder because a file with @@ -1137,21 +1127,19 @@ error_creating_folder_dialog (GtkFileChooserDefault *impl, */ static void error_creating_folder_over_existing_file_dialog (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, GError *error) { error_dialog (impl, _("The folder could not be created, as a file with the same " "name already exists. Try using a different name for the " "folder, or rename the file first."), - path, error); + file, error); } /* Shows an error dialog about not being able to create a filename */ static void error_building_filename_dialog (GtkFileChooserDefault *impl, - const GtkFilePath *folder_part, - const char *file_part, GError *error) { error_dialog (impl, _("Invalid file name"), @@ -1161,47 +1149,38 @@ error_building_filename_dialog (GtkFileChooserDefault *impl, /* Shows an error dialog when we cannot switch to a folder */ static void error_changing_folder_dialog (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, GError *error) { error_dialog (impl, _("The folder contents could not be displayed"), - path, error); + file, error); } /* Changes folders, displaying an error dialog if this fails */ static gboolean change_folder_and_display_error (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, gboolean clear_entry) { GError *error; gboolean result; - GtkFilePath *path_copy; - g_return_val_if_fail (path != NULL, FALSE); - - profile_start ("start", (char *) path); + g_return_val_if_fail (G_IS_FILE (file), FALSE); /* We copy the path because of this case: * * list_row_activated() * fetches path from model; path belongs to the model (*) * calls change_folder_and_display_error() - * calls _gtk_file_chooser_set_current_folder_path() + * calls _gtk_file_chooser_set_current_folder_file() * changing folders fails, sets model to NULL, thus freeing the path in (*) */ - path_copy = gtk_file_path_copy (path); - error = NULL; - result = gtk_file_chooser_default_update_current_folder (GTK_FILE_CHOOSER (impl), path_copy, TRUE, clear_entry, &error); + result = gtk_file_chooser_default_update_current_folder (GTK_FILE_CHOOSER (impl), file, TRUE, clear_entry, &error); if (!result) - error_changing_folder_dialog (impl, path_copy, error); - - gtk_file_path_free (path_copy); - - profile_end ("end", (char *) path); + error_changing_folder_dialog (impl, file, error); return result; } @@ -1299,27 +1278,26 @@ struct ReloadIconsData }; static void -shortcuts_reload_icons_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +shortcuts_reload_icons_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { GdkPixbuf *pixbuf; GtkTreeIter iter; GtkTreePath *path; - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct ReloadIconsData *data = user_data; - if (!g_slist_find (data->impl->reload_icon_handles, handle)) + if (!g_slist_find (data->impl->reload_icon_cancellables, cancellable)) goto out; - data->impl->reload_icon_handles = g_slist_remove (data->impl->reload_icon_handles, handle); + data->impl->reload_icon_cancellables = g_slist_remove (data->impl->reload_icon_cancellables, cancellable); if (cancelled || error) goto out; - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->impl), - data->impl->icon_size, NULL); + pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->impl), data->impl->icon_size); path = gtk_tree_row_reference_get_path (data->row_ref); gtk_tree_model_get_iter (GTK_TREE_MODEL (data->impl->shortcuts_model), &iter, path); @@ -1336,7 +1314,7 @@ out: g_object_unref (data->impl); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static void @@ -1350,13 +1328,13 @@ shortcuts_reload_icons (GtkFileChooserDefault *impl) if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter)) goto out; - for (l = impl->reload_icon_handles; l; l = l->next) + for (l = impl->reload_icon_cancellables; l; l = l->next) { - GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data); - gtk_file_system_cancel_operation (handle); + GCancellable *cancellable = G_CANCELLABLE (l->data); + g_cancellable_cancel (cancellable); } - g_slist_free (impl->reload_icon_handles); - impl->reload_icon_handles = NULL; + g_slist_free (impl->reload_icon_cancellables); + impl->reload_icon_cancellables = NULL; do { @@ -1379,19 +1357,19 @@ shortcuts_reload_icons (GtkFileChooserDefault *impl) GtkFileSystemVolume *volume; volume = data; - pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl), + pixbuf = gtk_file_system_volume_render_icon (volume, GTK_WIDGET (impl), impl->icon_size, NULL); } - else if (shortcut_type == SHORTCUT_TYPE_PATH) + else if (shortcut_type == SHORTCUT_TYPE_FILE) { - if (gtk_file_system_path_is_local (impl->file_system, (GtkFilePath *)data)) + if (g_file_is_native (G_FILE (data))) { - const GtkFilePath *path; + GFile *file; struct ReloadIconsData *info; GtkTreePath *tree_path; - GtkFileSystemHandle *handle; + GCancellable *cancellable; - path = data; + file = data; info = g_new0 (struct ReloadIconsData, 1); info->impl = g_object_ref (impl); @@ -1399,11 +1377,11 @@ shortcuts_reload_icons (GtkFileChooserDefault *impl) info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), tree_path); gtk_tree_path_free (tree_path); - handle = gtk_file_system_get_info (impl->file_system, path, - GTK_FILE_INFO_ICON, - shortcuts_reload_icons_get_info_cb, - info); - impl->reload_icon_handles = g_slist_append (impl->reload_icon_handles, handle); + cancellable = gtk_file_system_get_info (impl->file_system, file, + "standard::icon", + shortcuts_reload_icons_get_info_cb, + info); + impl->reload_icon_cancellables = g_slist_append (impl->reload_icon_cancellables, cancellable); } else { @@ -1446,7 +1424,7 @@ shortcuts_reload_icons (GtkFileChooserDefault *impl) static void shortcuts_find_folder (GtkFileChooserDefault *impl, - GtkFilePath *folder) + GFile *folder) { GtkTreeSelection *selection; int pos; @@ -1547,8 +1525,7 @@ shortcuts_update_count (GtkFileChooserDefault *impl, struct ShortcutsInsertRequest { GtkFileChooserDefault *impl; - GtkFilePath *parent_path; - GtkFilePath *path; + GFile *file; int pos; char *label_copy; GtkTreeRowReference *row_ref; @@ -1558,17 +1535,17 @@ struct ShortcutsInsertRequest }; static void -get_file_info_finished (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer data) +get_file_info_finished (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer data) { gint pos = -1; - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GdkPixbuf *pixbuf; GtkTreePath *path; GtkTreeIter iter; - GtkFileSystemHandle *model_handle; + GCancellable *model_cancellable; struct ShortcutsInsertRequest *request = data; path = gtk_tree_row_reference_get_path (request->row_ref); @@ -1581,16 +1558,16 @@ get_file_info_finished (GtkFileSystemHandle *handle, &iter, path); gtk_tree_path_free (path); - /* validate handle, else goto out */ + /* validate cancellable, else goto out */ gtk_tree_model_get (GTK_TREE_MODEL (request->impl->shortcuts_model), &iter, - SHORTCUTS_COL_HANDLE, &model_handle, + SHORTCUTS_COL_CANCELLABLE, &model_cancellable, -1); - if (handle != model_handle) + if (cancellable != model_cancellable) goto out; - /* set the handle to NULL in the model (we unref later on) */ + /* set the cancellable to NULL in the model (we unref later on) */ gtk_list_store_set (request->impl->shortcuts_model, &iter, - SHORTCUTS_COL_HANDLE, NULL, + SHORTCUTS_COL_CANCELLABLE, NULL, -1); if (cancelled) @@ -1603,12 +1580,11 @@ get_file_info_finished (GtkFileSystemHandle *handle, if (request->type == SHORTCUTS_HOME) { - const char *home = g_get_home_dir (); - GtkFilePath *home_path; + GFile *home; - home_path = gtk_file_system_filename_to_path (request->impl->file_system, home); - error_getting_info_dialog (request->impl, home_path, g_error_copy (error)); - gtk_file_path_free (home_path); + home = g_file_new_for_path (g_get_home_dir ()); + error_getting_info_dialog (request->impl, home, g_error_copy (error)); + g_object_unref (home); } else if (request->type == SHORTCUTS_CURRENT_FOLDER) { @@ -1621,15 +1597,15 @@ get_file_info_finished (GtkFileSystemHandle *handle, } if (!request->label_copy) - request->label_copy = g_strdup (gtk_file_info_get_display_name (info)); + request->label_copy = g_strdup (g_file_info_get_display_name (info)); pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (request->impl), - request->impl->icon_size, NULL); + request->impl->icon_size); gtk_list_store_set (request->impl->shortcuts_model, &iter, SHORTCUTS_COL_PIXBUF, pixbuf, SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE, SHORTCUTS_COL_NAME, request->label_copy, - SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_PATH, + SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_FILE, SHORTCUTS_COL_REMOVABLE, request->removable, -1); @@ -1667,13 +1643,12 @@ get_file_info_finished (GtkFileSystemHandle *handle, out: g_object_unref (request->impl); - gtk_file_path_free (request->parent_path); - gtk_file_path_free (request->path); + g_object_unref (request->file); gtk_tree_row_reference_free (request->row_ref); g_free (request->label_copy); g_free (request); - g_object_unref (handle); + g_object_unref (cancellable); } /* FIXME: GtkFileSystem needs a function to split a remote path @@ -1683,11 +1658,13 @@ out: * This function is also used in gtkfilechooserbutton.c */ gchar * -_gtk_file_chooser_label_for_uri (const gchar *uri) +_gtk_file_chooser_label_for_file (GFile *file) { const gchar *path, *start, *end, *p; - gchar *host, *label; - + gchar *uri, *host, *label; + + uri = g_file_get_uri (file); + start = strstr (uri, "://"); start += 3; path = strchr (start, '/'); @@ -1720,6 +1697,7 @@ _gtk_file_chooser_label_for_uri (const gchar *uri) label = g_strdup_printf (_("%1$s on %2$s"), path, host); g_free (host); + g_free (uri); return label; } @@ -1728,11 +1706,11 @@ _gtk_file_chooser_label_for_uri (const gchar *uri) * inserts a volume. A position of -1 indicates the end of the tree. */ static void -shortcuts_insert_path (GtkFileChooserDefault *impl, +shortcuts_insert_file (GtkFileChooserDefault *impl, int pos, ShortcutType shortcut_type, GtkFileSystemVolume *volume, - const GtkFilePath *path, + GFile *file, const char *label, gboolean removable, ShortcutsIndex type) @@ -1741,29 +1719,28 @@ shortcuts_insert_path (GtkFileChooserDefault *impl, GdkPixbuf *pixbuf = NULL; gpointer data = NULL; GtkTreeIter iter; - GtkIconTheme *icon_theme; + GtkIconTheme *icon_theme; - profile_start ("start", (shortcut_type == SHORTCUT_TYPE_VOLUME) ? "volume" - : ((shortcut_type == SHORTCUT_TYPE_PATH) ? (char *) path : NULL)); + profile_start ("start shortcut", NULL); if (shortcut_type == SHORTCUT_TYPE_VOLUME) { data = volume; - label_copy = gtk_file_system_volume_get_display_name (impl->file_system, volume); - pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl), + label_copy = gtk_file_system_volume_get_display_name (volume); + pixbuf = gtk_file_system_volume_render_icon (volume, GTK_WIDGET (impl), impl->icon_size, NULL); } - else if (shortcut_type == SHORTCUT_TYPE_PATH) + else if (shortcut_type == SHORTCUT_TYPE_FILE) { - if (gtk_file_system_path_is_local (impl->file_system, path)) + if (g_file_is_native (file)) { struct ShortcutsInsertRequest *request; - GtkFileSystemHandle *handle; + GCancellable *cancellable; GtkTreePath *p; request = g_new0 (struct ShortcutsInsertRequest, 1); request->impl = g_object_ref (impl); - request->path = gtk_file_path_copy (path); + request->file = g_object_ref (file); request->name_only = TRUE; request->removable = removable; request->pos = pos; @@ -1780,14 +1757,14 @@ shortcuts_insert_path (GtkFileChooserDefault *impl, request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), p); gtk_tree_path_free (p); - handle = gtk_file_system_get_info (request->impl->file_system, request->path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_HIDDEN | GTK_FILE_INFO_ICON, - get_file_info_finished, request); + cancellable = gtk_file_system_get_info (request->impl->file_system, request->file, + "standard::is-hidden,standard::display-name,standard::icon", + get_file_info_finished, request); gtk_list_store_set (impl->shortcuts_model, &iter, - SHORTCUTS_COL_DATA, gtk_file_path_copy (path), - SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_PATH, - SHORTCUTS_COL_HANDLE, handle, + SHORTCUTS_COL_DATA, g_object_ref (file), + SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_FILE, + SHORTCUTS_COL_CANCELLABLE, cancellable, -1); shortcuts_update_count (impl, type, 1); @@ -1799,20 +1776,12 @@ shortcuts_insert_path (GtkFileChooserDefault *impl, /* Don't call get_info for remote paths to avoid latency and * auth dialogs. */ - data = gtk_file_path_copy (path); + data = g_object_ref (file); if (label) label_copy = g_strdup (label); else - { - gchar *uri; - - uri = gtk_file_system_path_to_uri (impl->file_system, path); - - label_copy = _gtk_file_chooser_label_for_uri (uri); + label_copy = _gtk_file_chooser_label_for_file (file); - g_free (uri); - } - /* If we switch to a better bookmarks file format (XBEL), we * should use mime info to get a better icon. */ @@ -1842,7 +1811,7 @@ shortcuts_insert_path (GtkFileChooserDefault *impl, SHORTCUTS_COL_DATA, data, SHORTCUTS_COL_TYPE, shortcut_type, SHORTCUTS_COL_REMOVABLE, removable, - SHORTCUTS_COL_HANDLE, NULL, + SHORTCUTS_COL_CANCELLABLE, NULL, -1); if (impl->shortcuts_pane_filter_model) @@ -1935,24 +1904,23 @@ shortcuts_append_recent (GtkFileChooserDefault *impl) static void shortcuts_append_home (GtkFileChooserDefault *impl) { - const char *home; - GtkFilePath *home_path; + const char *home_path; + GFile *home; profile_start ("start", NULL); - home = g_get_home_dir (); - if (home == NULL) + home_path = g_get_home_dir (); + if (home_path == NULL) { profile_end ("end - no home directory!?", NULL); return; } - home_path = gtk_file_system_filename_to_path (impl->file_system, home); - - shortcuts_insert_path (impl, -1, SHORTCUT_TYPE_PATH, NULL, home_path, NULL, FALSE, SHORTCUTS_HOME); + home = g_file_new_for_path (home_path); + shortcuts_insert_file (impl, -1, SHORTCUT_TYPE_FILE, NULL, home, NULL, FALSE, SHORTCUTS_HOME); impl->has_home = TRUE; - gtk_file_path_free (home_path); + g_object_unref (home); profile_end ("end", NULL); } @@ -1962,57 +1930,54 @@ static void shortcuts_append_desktop (GtkFileChooserDefault *impl) { const char *name; - GtkFilePath *path; + GFile *file; profile_start ("start", NULL); name = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP); - path = gtk_file_system_filename_to_path (impl->file_system, name); - shortcuts_insert_path (impl, -1, SHORTCUT_TYPE_PATH, NULL, path, _("Desktop"), FALSE, SHORTCUTS_DESKTOP); + file = g_file_new_for_path (name); + shortcuts_insert_file (impl, -1, SHORTCUT_TYPE_FILE, NULL, file, _("Desktop"), FALSE, SHORTCUTS_DESKTOP); impl->has_desktop = TRUE; /* We do not actually pop up an error dialog if there is no desktop directory * because some people may really not want to have one. */ - gtk_file_path_free (path); + g_object_unref (file); profile_end ("end", NULL); } -/* Appends a list of GtkFilePath to the shortcuts model; returns how many were inserted */ +/* Appends a list of GFile to the shortcuts model; returns how many were inserted */ static int -shortcuts_append_paths (GtkFileChooserDefault *impl, - GSList *paths) +shortcuts_append_bookmarks (GtkFileChooserDefault *impl, + GSList *bookmarks) { int start_row; int num_inserted; - gchar *label; + const gchar *label; profile_start ("start", NULL); start_row = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR) + 1; num_inserted = 0; - for (; paths; paths = paths->next) + for (; bookmarks; bookmarks = bookmarks->next) { - GtkFilePath *path; + GFile *file; - path = paths->data; + file = bookmarks->data; - if (impl->local_only && - !gtk_file_system_path_is_local (impl->file_system, path)) + if (impl->local_only && !g_file_is_native (file)) continue; - if (shortcut_find_position (impl, path) != -1) + + if (shortcut_find_position (impl, file) != -1) continue; - label = gtk_file_system_get_bookmark_label (impl->file_system, path); + label = gtk_file_system_get_bookmark_label (impl->file_system, file); - /* NULL GError, but we don't really want to show error boxes here */ - shortcuts_insert_path (impl, start_row + num_inserted, SHORTCUT_TYPE_PATH, NULL, path, label, TRUE, SHORTCUTS_BOOKMARKS); + shortcuts_insert_file (impl, start_row + num_inserted, SHORTCUT_TYPE_FILE, NULL, file, label, TRUE, SHORTCUTS_BOOKMARKS); num_inserted++; - - g_free (label); } profile_end ("end", NULL); @@ -2101,7 +2066,6 @@ shortcuts_add_volumes (GtkFileChooserDefault *impl) profile_start ("start", NULL); - old_changing_folders = impl->changing_folder; impl->changing_folder = TRUE; @@ -2121,26 +2085,17 @@ shortcuts_add_volumes (GtkFileChooserDefault *impl) if (impl->local_only) { - if (gtk_file_system_volume_get_is_mounted (impl->file_system, volume)) + if (gtk_file_system_volume_is_mounted (volume)) { - GtkFilePath *base_path; - - base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume); - if (base_path != NULL) - { - gboolean is_local = gtk_file_system_path_is_local (impl->file_system, base_path); - gtk_file_path_free (base_path); - - if (!is_local) - { - gtk_file_system_volume_free (impl->file_system, volume); - continue; - } - } + GFile *base_file; + + base_file = gtk_file_system_volume_get_root (volume); + if (base_file != NULL && !g_file_is_native (base_file)) + continue; } } - shortcuts_insert_path (impl, start_row + n, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_VOLUMES); + shortcuts_insert_file (impl, start_row + n, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_VOLUMES); n++; } @@ -2187,8 +2142,8 @@ shortcuts_add_bookmarks (GtkFileChooserDefault *impl) GSList *bookmarks; gboolean old_changing_folders; GtkTreeIter iter; - GtkFilePath *list_selected = NULL; - GtkFilePath *combo_selected = NULL; + GFile *list_selected = NULL; + GFile *combo_selected = NULL; ShortcutType shortcut_type; gpointer col_data; @@ -2205,8 +2160,8 @@ shortcuts_add_bookmarks (GtkFileChooserDefault *impl) SHORTCUTS_COL_TYPE, &shortcut_type, -1); - if (col_data && shortcut_type == SHORTCUT_TYPE_PATH) - list_selected = gtk_file_path_copy (col_data); + if (col_data && shortcut_type == SHORTCUT_TYPE_FILE) + list_selected = g_object_ref (col_data); } if (impl->save_folder_combo && @@ -2224,8 +2179,8 @@ shortcuts_add_bookmarks (GtkFileChooserDefault *impl) SHORTCUTS_COL_TYPE, &shortcut_type, -1); - if (col_data && shortcut_type == SHORTCUT_TYPE_PATH) - combo_selected = gtk_file_path_copy (col_data); + if (col_data && shortcut_type == SHORTCUT_TYPE_FILE) + combo_selected = g_object_ref (col_data); } if (impl->num_bookmarks > 0) @@ -2237,8 +2192,8 @@ shortcuts_add_bookmarks (GtkFileChooserDefault *impl) shortcuts_insert_separator (impl, SHORTCUTS_BOOKMARKS_SEPARATOR); bookmarks = gtk_file_system_list_bookmarks (impl->file_system); - shortcuts_append_paths (impl, bookmarks); - gtk_file_paths_free (bookmarks); + shortcuts_append_bookmarks (impl, bookmarks); + g_slist_free (bookmarks); if (impl->num_bookmarks == 0) shortcuts_remove_rows (impl, shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR), 1); @@ -2252,7 +2207,7 @@ shortcuts_add_bookmarks (GtkFileChooserDefault *impl) if (list_selected) { shortcuts_find_folder (impl, list_selected); - gtk_file_path_free (list_selected); + g_object_unref (list_selected); } if (combo_selected) @@ -2271,7 +2226,7 @@ shortcuts_add_bookmarks (GtkFileChooserDefault *impl) gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), pos); } - gtk_file_path_free (combo_selected); + g_object_unref (combo_selected); } impl->changing_folder = old_changing_folders; @@ -2296,7 +2251,7 @@ shortcuts_add_current_folder (GtkFileChooserDefault *impl) if (pos == -1) { GtkFileSystemVolume *volume; - GtkFilePath *base_path; + GFile *base_file; /* Separator */ @@ -2306,26 +2261,19 @@ shortcuts_add_current_folder (GtkFileChooserDefault *impl) pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER); - volume = gtk_file_system_get_volume_for_path (impl->file_system, impl->current_folder); + volume = gtk_file_system_get_volume_for_file (impl->file_system, impl->current_folder); if (volume) - base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume); + base_file = gtk_file_system_volume_get_root (volume); else - base_path = NULL; + base_file = NULL; - if (base_path && - strcmp (gtk_file_path_get_string (base_path), gtk_file_path_get_string (impl->current_folder)) == 0) - { - shortcuts_insert_path (impl, pos, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER); - } + if (base_file && g_file_equal (base_file, impl->current_folder)) + shortcuts_insert_file (impl, pos, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER); else - { - shortcuts_insert_path (impl, pos, SHORTCUT_TYPE_PATH, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER); - if (volume) - gtk_file_system_volume_free (impl->file_system, volume); - } + shortcuts_insert_file (impl, pos, SHORTCUT_TYPE_FILE, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER); - if (base_path) - gtk_file_path_free (base_path); + if (base_file) + g_object_unref (base_file); } else if (impl->save_folder_combo != NULL) { @@ -2390,7 +2338,7 @@ shortcuts_model_create (GtkFileChooserDefault *impl) G_TYPE_INT, /* ShortcutType */ G_TYPE_BOOLEAN, /* removable */ G_TYPE_BOOLEAN, /* pixbuf cell visibility */ - G_TYPE_POINTER); /* GtkFileSystemHandle */ + G_TYPE_POINTER); /* GCancellable */ if (search_is_possible (impl)) { @@ -2450,33 +2398,6 @@ new_folder_button_clicked (GtkButton *button, gtk_tree_path_free (path); } -static void -edited_idle_create_folder_cb (GtkFileSystemHandle *handle, - const GtkFilePath *path, - const GError *error, - gpointer data) -{ - gboolean cancelled = handle->cancelled; - GtkFileChooserDefault *impl = data; - - if (!g_slist_find (impl->pending_handles, handle)) - goto out; - - impl->pending_handles = g_slist_remove (impl->pending_handles, handle); - - if (cancelled) - goto out; - - if (!error) - change_folder_and_display_error (impl, path, FALSE); - else - error_creating_folder_dialog (impl, path, g_error_copy (error)); - - out: - g_object_unref (impl); - g_object_unref (handle); -} - /* Idle handler for creating a new folder after editing its name cell, or for * canceling the editing. */ @@ -2495,27 +2416,25 @@ edited_idle_cb (GtkFileChooserDefault *impl) if (impl->edited_new_text) /* not cancelled? */ { - GError *error; - GtkFilePath *file_path; + GError *error = NULL; + GFile *file; - error = NULL; - file_path = gtk_file_system_make_path (impl->file_system, - impl->current_folder, - impl->edited_new_text, - &error); - if (file_path) + file = g_file_get_child_for_display_name (impl->current_folder, + impl->edited_new_text, + &error); + if (file) { - GtkFileSystemHandle *handle; + GError *error = NULL; - handle = gtk_file_system_create_folder (impl->file_system, file_path, - edited_idle_create_folder_cb, - g_object_ref (impl)); - impl->pending_handles = g_slist_append (impl->pending_handles, handle); + if (!g_file_make_directory (file, NULL, &error)) + change_folder_and_display_error (impl, file, FALSE); + else + error_creating_folder_dialog (impl, file, error); - gtk_file_path_free (file_path); + g_object_unref (file); } else - error_creating_folder_dialog (impl, file_path, error); + error_creating_folder_dialog (impl, file, error); g_free (impl->edited_new_text); impl->edited_new_text = NULL; @@ -2616,7 +2535,7 @@ button_new (GtkFileChooserDefault *impl, /* Looks for a path among the shortcuts; returns its index or -1 if it doesn't exist */ static int shortcut_find_position (GtkFileChooserDefault *impl, - const GtkFilePath *path) + GFile *file) { GtkTreeIter iter; int i; @@ -2648,26 +2567,27 @@ shortcut_find_position (GtkFileChooserDefault *impl, if (shortcut_type == SHORTCUT_TYPE_VOLUME) { GtkFileSystemVolume *volume; - GtkFilePath *base_path; + GFile *base_file; gboolean exists; volume = col_data; - base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume); + base_file = gtk_file_system_volume_get_root (volume); - exists = base_path && strcmp (gtk_file_path_get_string (path), - gtk_file_path_get_string (base_path)) == 0; - g_free (base_path); + exists = base_file && g_file_equal (file, base_file); + + if (base_file) + g_object_unref (base_file); if (exists) return i; } - else if (shortcut_type == SHORTCUT_TYPE_PATH) + else if (shortcut_type == SHORTCUT_TYPE_FILE) { - GtkFilePath *model_path; + GFile *model_file; - model_path = col_data; + model_file = col_data; - if (model_path && gtk_file_path_compare (model_path, path) == 0) + if (model_file && g_file_equal (model_file, file)) return i; } } @@ -2684,21 +2604,21 @@ shortcut_find_position (GtkFileChooserDefault *impl, /* Tries to add a bookmark from a path name */ static gboolean -shortcuts_add_bookmark_from_path (GtkFileChooserDefault *impl, - const GtkFilePath *path, +shortcuts_add_bookmark_from_file (GtkFileChooserDefault *impl, + GFile *file, int pos) { GError *error; - g_return_val_if_fail (path != NULL, FALSE); - - if (shortcut_find_position (impl, path) != -1) + g_return_val_if_fail (G_IS_FILE (file), FALSE); + + if (shortcut_find_position (impl, file) != -1) return FALSE; error = NULL; - if (!gtk_file_system_insert_bookmark (impl->file_system, path, pos, &error)) + if (!gtk_file_system_insert_bookmark (impl->file_system, file, pos, &error)) { - error_adding_bookmark_dialog (impl, path, error); + error_adding_bookmark_dialog (impl, file, error); return FALSE; } @@ -2714,7 +2634,7 @@ add_bookmark_foreach_cb (GtkTreeModel *model, GtkFileChooserDefault *impl; GtkFileSystemModel *fs_model; GtkTreeIter child_iter; - const GtkFilePath *file_path; + GFile *file; impl = (GtkFileChooserDefault *) data; @@ -2723,25 +2643,25 @@ add_bookmark_foreach_cb (GtkTreeModel *model, case OPERATION_MODE_BROWSE: fs_model = impl->browse_files_model; gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, iter); - file_path = _gtk_file_system_model_get_path (fs_model, &child_iter); + file = _gtk_file_system_model_get_file (fs_model, &child_iter); break; case OPERATION_MODE_SEARCH: search_get_valid_child_iter (impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, - SEARCH_MODEL_COL_PATH, &file_path, + SEARCH_MODEL_COL_FILE, &file, -1); break; case OPERATION_MODE_RECENT: recent_get_valid_child_iter (impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, - RECENT_MODEL_COL_PATH, &file_path, + RECENT_MODEL_COL_FILE, &file, -1); break; } - - shortcuts_add_bookmark_from_path (impl, file_path, -1); + + shortcuts_add_bookmark_from_file (impl, file, -1); } /* Adds a bookmark from the currently selected item in the file list */ @@ -2753,7 +2673,7 @@ bookmarks_add_selected_folder (GtkFileChooserDefault *impl) selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); if (gtk_tree_selection_count_selected_rows (selection) == 0) - shortcuts_add_bookmark_from_path (impl, impl->current_folder, -1); + shortcuts_add_bookmark_from_file (impl, impl->current_folder, -1); else gtk_tree_selection_selected_foreach (selection, add_bookmark_foreach_cb, @@ -2798,7 +2718,7 @@ remove_selected_bookmarks (GtkFileChooserDefault *impl) { GtkTreeIter iter; gpointer col_data; - GtkFilePath *path; + GFile *file; gboolean removable; GError *error; @@ -2815,11 +2735,11 @@ remove_selected_bookmarks (GtkFileChooserDefault *impl) g_assert (col_data != NULL); - path = col_data; + file = col_data; error = NULL; - if (!gtk_file_system_remove_bookmark (impl->file_system, path, &error)) - error_removing_bookmark_dialog (impl, path, error); + if (!gtk_file_system_remove_bookmark (impl->file_system, file, &error)) + error_removing_bookmark_dialog (impl, file, error); } /* Callback used when the "Remove bookmark" button is clicked */ @@ -2846,7 +2766,7 @@ selection_check_foreach_cb (GtkTreeModel *model, { struct selection_check_closure *closure; GtkTreeIter child_iter; - const GtkFileInfo *info; + GFileInfo *info; gboolean is_folder; closure = data; @@ -2857,7 +2777,7 @@ selection_check_foreach_cb (GtkTreeModel *model, case OPERATION_MODE_BROWSE: gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter); info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter); - is_folder = info ? gtk_file_info_get_is_folder (info) : FALSE; + is_folder = info ? (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) : FALSE; break; case OPERATION_MODE_SEARCH: @@ -2911,18 +2831,18 @@ selection_check (GtkFileChooserDefault *impl, *all_folders = closure.all_folders; } -struct get_selected_path_closure { +struct get_selected_file_closure { GtkFileChooserDefault *impl; - const GtkFilePath *path; + GFile *file; }; static void -get_selected_path_foreach_cb (GtkTreeModel *model, +get_selected_file_foreach_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { - struct get_selected_path_closure *closure; + struct get_selected_file_closure *closure; GtkTreeIter child_iter; closure = data; @@ -2931,41 +2851,41 @@ get_selected_path_foreach_cb (GtkTreeModel *model, { case OPERATION_MODE_BROWSE: gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter); - closure->path = _gtk_file_system_model_get_path (closure->impl->browse_files_model, &child_iter); + closure->file = _gtk_file_system_model_get_file (closure->impl->browse_files_model, &child_iter); break; case OPERATION_MODE_SEARCH: search_get_valid_child_iter (closure->impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->search_model), &child_iter, - SEARCH_MODEL_COL_PATH, &closure->path, + SEARCH_MODEL_COL_FILE, &closure->file, -1); break; case OPERATION_MODE_RECENT: recent_get_valid_child_iter (closure->impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->recent_model), &child_iter, - RECENT_MODEL_COL_PATH, &closure->path, + RECENT_MODEL_COL_FILE, &closure->file, -1); break; } } /* Returns a selected path from the file list */ -static const GtkFilePath * -get_selected_path (GtkFileChooserDefault *impl) +static GFile * +get_selected_file (GtkFileChooserDefault *impl) { - struct get_selected_path_closure closure; + struct get_selected_file_closure closure; GtkTreeSelection *selection; closure.impl = impl; - closure.path = NULL; + closure.file = NULL; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); gtk_tree_selection_selected_foreach (selection, - get_selected_path_foreach_cb, + get_selected_file_foreach_cb, &closure); - return closure.path; + return closure.file; } typedef struct { @@ -2981,7 +2901,7 @@ update_tooltip (GtkTreeModel *model, { UpdateTooltipData *udata = data; GtkTreeIter child_iter; - const GtkFileInfo *info; + GFileInfo *info; if (udata->tip == NULL) { @@ -2994,7 +2914,7 @@ update_tooltip (GtkTreeModel *model, &child_iter, iter); info = _gtk_file_system_model_get_info (udata->impl->browse_files_model, &child_iter); - display_name = gtk_file_info_get_display_name (info); + display_name = g_file_info_get_display_name (info); break; case OPERATION_MODE_SEARCH: @@ -3036,10 +2956,10 @@ bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl) active = (impl->current_folder != NULL) && (shortcut_find_position (impl, impl->current_folder) == -1); else if (num_selected == 1) { - const GtkFilePath *path; + GFile *file; - path = get_selected_path (impl); - active = all_folders && (shortcut_find_position (impl, path) == -1); + file = get_selected_file (impl); + active = all_folders && (shortcut_find_position (impl, file) == -1); } else active = all_folders; @@ -3508,30 +3428,15 @@ shortcuts_drop_uris (GtkFileChooserDefault *impl, for (i = 0; uris[i]; i++) { char *uri; - GtkFilePath *path; + GFile *file; uri = uris[i]; - path = gtk_file_system_uri_to_path (impl->file_system, uri); - - if (path) - { - if (shortcuts_add_bookmark_from_path (impl, path, position)) - position++; + file = g_file_new_for_uri (uri); - gtk_file_path_free (path); - } - else - { - GError *error = NULL; + if (shortcuts_add_bookmark_from_file (impl, file, position)) + position++; - g_set_error (&error, - GTK_FILE_CHOOSER_ERROR, - GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, - _("Could not add a bookmark for '%s' " - "because it is an invalid path name."), - uri); - error_adding_bookmark_dialog (impl, path, error); - } + g_object_unref (file); } g_strfreev (uris); @@ -3548,8 +3453,7 @@ shortcuts_reorder (GtkFileChooserDefault *impl, GtkTreePath *path; int old_position; int bookmarks_index; - const GtkFilePath *file_path; - GtkFilePath *file_path_copy; + GFile *file; GError *error; gchar *name; @@ -3572,10 +3476,10 @@ shortcuts_reorder (GtkFileChooserDefault *impl, SHORTCUTS_COL_TYPE, &shortcut_type, -1); g_assert (col_data != NULL); - g_assert (shortcut_type == SHORTCUT_TYPE_PATH); + g_assert (shortcut_type == SHORTCUT_TYPE_FILE); - file_path = col_data; - file_path_copy = gtk_file_path_copy (file_path); /* removal below will free file_path, so we need a copy */ + file = col_data; + g_object_ref (file); /* removal below will free file, so we need a new ref */ /* Remove the path from the old position and insert it in the new one */ @@ -3586,17 +3490,17 @@ shortcuts_reorder (GtkFileChooserDefault *impl, goto out; error = NULL; - if (gtk_file_system_remove_bookmark (impl->file_system, file_path_copy, &error)) + if (gtk_file_system_remove_bookmark (impl->file_system, file, &error)) { - shortcuts_add_bookmark_from_path (impl, file_path_copy, new_position); - gtk_file_system_set_bookmark_label (impl->file_system, file_path_copy, name); + shortcuts_add_bookmark_from_file (impl, file, new_position); + gtk_file_system_set_bookmark_label (impl->file_system, file, name); } else - error_adding_bookmark_dialog (impl, file_path_copy, error); + error_adding_bookmark_dialog (impl, file, error); out: - gtk_file_path_free (file_path_copy); + g_object_unref (file); } /* Callback used when we get the drag data for the bookmarks list. We add the @@ -3675,21 +3579,17 @@ shortcuts_query_tooltip_cb (GtkWidget *widget, { return FALSE; } - else if (shortcut_type == SHORTCUT_TYPE_PATH) + else if (shortcut_type == SHORTCUT_TYPE_FILE) { GFile *file; - char *uri; char *parse_name; - uri = gtk_file_system_path_to_uri (impl->file_system, (GtkFilePath *) col_data); - file = g_file_new_for_uri (uri); + file = G_FILE (col_data); parse_name = g_file_get_parse_name (file); gtk_tooltip_set_text (tooltip, parse_name); - g_free (uri); g_free (parse_name); - g_object_unref (file); return TRUE; } @@ -3928,7 +3828,7 @@ shortcuts_edited (GtkCellRenderer *cell, { GtkTreePath *path; GtkTreeIter iter; - GtkFilePath *shortcut; + GFile *shortcut; g_object_set (cell, "editable", FALSE, NULL); @@ -4205,12 +4105,12 @@ show_hidden_toggled_cb (GtkCheckMenuItem *item, /* Shows an error dialog about not being able to select a dragged file */ static void error_selecting_dragged_file_dialog (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, GError *error) { error_dialog (impl, _("Could not select file"), - path, error); + file, error); } static void @@ -4223,21 +4123,17 @@ file_list_drag_data_select_uris (GtkFileChooserDefault *impl, for (i = 1; uris[i]; i++) { - GtkFilePath *path; + GFile *file; + GError *error = NULL; uri = uris[i]; - path = gtk_file_system_uri_to_path (impl->file_system, uri); + file = g_file_new_for_uri (uri); - if (path) - { - GError *error = NULL; - - gtk_file_chooser_default_select_path (chooser, path, &error); - if (error) - error_selecting_dragged_file_dialog (impl, path, error); + gtk_file_chooser_default_select_file (chooser, file, &error); + if (error) + error_selecting_dragged_file_dialog (impl, file, error); - gtk_file_path_free (path); - } + g_object_unref (file); } } @@ -4245,23 +4141,23 @@ struct FileListDragData { GtkFileChooserDefault *impl; gchar **uris; - GtkFilePath *path; + GFile *file; }; static void -file_list_drag_data_received_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +file_list_drag_data_received_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct FileListDragData *data = user_data; GtkFileChooser *chooser = GTK_FILE_CHOOSER (data->impl); - if (handle != data->impl->file_list_drag_data_received_handle) + if (cancellable != data->impl->file_list_drag_data_received_cancellable) goto out; - data->impl->file_list_drag_data_received_handle = NULL; + data->impl->file_list_drag_data_received_cancellable = NULL; if (cancelled || error) goto out; @@ -4269,16 +4165,16 @@ file_list_drag_data_received_get_info_cb (GtkFileSystemHandle *handle, if ((data->impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || data->impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) && data->uris[1] == 0 && !error && - gtk_file_info_get_is_folder (info)) - change_folder_and_display_error (data->impl, data->path, FALSE); + g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + change_folder_and_display_error (data->impl, data->file, FALSE); else { GError *error = NULL; gtk_file_chooser_default_unselect_all (chooser); - gtk_file_chooser_default_select_path (chooser, data->path, &error); + gtk_file_chooser_default_select_file (chooser, data->file, &error); if (error) - error_selecting_dragged_file_dialog (data->impl, data->path, error); + error_selecting_dragged_file_dialog (data->impl, data->file, error); else browse_files_center_selected_row (data->impl); } @@ -4289,10 +4185,10 @@ file_list_drag_data_received_get_info_cb (GtkFileSystemHandle *handle, out: g_object_unref (data->impl); g_strfreev (data->uris); - gtk_file_path_free (data->path); + g_object_unref (data->file); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static void @@ -4309,9 +4205,8 @@ file_list_drag_data_received_cb (GtkWidget *widget, GtkFileChooser *chooser; gchar **uris; char *uri; - GtkFilePath *path; - GError *error = NULL; - + GFile *file; + impl = GTK_FILE_CHOOSER_DEFAULT (data); chooser = GTK_FILE_CHOOSER (data); @@ -4319,46 +4214,26 @@ file_list_drag_data_received_cb (GtkWidget *widget, uris = g_uri_list_extract_uris ((const char *) selection_data->data); if (uris[0]) { - uri = uris[0]; - path = gtk_file_system_uri_to_path (impl->file_system, uri); - - if (path) - { - struct FileListDragData *data; + struct FileListDragData *data; - data = g_new0 (struct FileListDragData, 1); - data->impl = g_object_ref (impl); - data->uris = uris; - data->path = path; + uri = uris[0]; + file = g_file_new_for_uri (uri); - if (impl->file_list_drag_data_received_handle) - gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle); + data = g_new0 (struct FileListDragData, 1); + data->impl = g_object_ref (impl); + data->uris = uris; + data->file = file; - impl->file_list_drag_data_received_handle = - gtk_file_system_get_info (impl->file_system, path, - GTK_FILE_INFO_IS_FOLDER, - file_list_drag_data_received_get_info_cb, - data); - goto out; - } - else - { - g_set_error (&error, - GTK_FILE_CHOOSER_ERROR, - GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, - _("Could not select file '%s' " - "because it is an invalid path name."), - uri); - error_selecting_dragged_file_dialog (impl, NULL, error); - } + if (impl->file_list_drag_data_received_cancellable) + g_cancellable_cancel (impl->file_list_drag_data_received_cancellable); - if (impl->select_multiple) - file_list_drag_data_select_uris (impl, uris); + impl->file_list_drag_data_received_cancellable = + gtk_file_system_get_info (impl->file_system, file, + "standard::type", + file_list_drag_data_received_get_info_cb, + data); } - g_strfreev (uris); - -out: g_signal_stop_emission_by_name (widget, "drag_data_received"); } @@ -4547,11 +4422,11 @@ file_list_set_sort_column_ids (GtkFileChooserDefault *impl) mtime_id = FILE_LIST_COL_MTIME; break; case OPERATION_MODE_SEARCH: - name_id = SEARCH_MODEL_COL_PATH; + name_id = SEARCH_MODEL_COL_FILE; mtime_id = SEARCH_MODEL_COL_STAT; break; case OPERATION_MODE_RECENT: - name_id = RECENT_MODEL_COL_PATH; + name_id = RECENT_MODEL_COL_FILE; mtime_id = RECENT_MODEL_COL_INFO; break; } @@ -4571,7 +4446,7 @@ file_list_query_tooltip_cb (GtkWidget *widget, GtkFileChooserDefault *impl = user_data; GtkTreeIter iter, child_iter; GtkTreePath *path = NULL; - GtkFilePath *file_path = NULL; + GFile *file; gchar *filename; if (impl->operation_mode == OPERATION_MODE_BROWSE) @@ -4597,7 +4472,7 @@ file_list_query_tooltip_cb (GtkWidget *widget, search_get_valid_child_iter (impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, - SEARCH_MODEL_COL_PATH, &file_path, + SEARCH_MODEL_COL_FILE, &file, -1); break; @@ -4610,7 +4485,7 @@ file_list_query_tooltip_cb (GtkWidget *widget, recent_get_valid_child_iter (impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, - RECENT_MODEL_COL_PATH, &file_path, + RECENT_MODEL_COL_FILE, &file, -1); break; @@ -4619,13 +4494,13 @@ file_list_query_tooltip_cb (GtkWidget *widget, return FALSE; } - if (!file_path) + if (!file) { gtk_tree_path_free (path); return FALSE; } - filename = gtk_file_system_path_to_filename (impl->file_system, file_path); + filename = g_file_get_path (file); gtk_tooltip_set_text (tooltip, filename); gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (impl->browse_files_tree_view), tooltip, @@ -5058,26 +4933,20 @@ location_switch_to_path_bar (GtkFileChooserDefault *impl) static void location_entry_set_initial_text (GtkFileChooserDefault *impl) { - char *text; + gchar *text, *filename; if (!impl->current_folder) return; - if (gtk_file_system_path_is_local (impl->file_system, impl->current_folder)) - { - char *filename; + filename = g_file_get_path (impl->current_folder); - filename = gtk_file_system_path_to_filename (impl->file_system, impl->current_folder); - if (filename) - { - text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); - g_free (filename); - } - else - text = NULL; + if (filename) + { + text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); + g_free (filename); } else - text = gtk_file_system_path_to_uri (impl->file_system, impl->current_folder); + text = g_file_get_uri (impl->current_folder); if (text) { @@ -5103,6 +4972,8 @@ location_entry_set_initial_text (GtkFileChooserDefault *impl) _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), text); g_free (text); } + + g_free (filename); } /* Turns on the location entry. Can be called even if we are already in that @@ -5434,40 +5305,32 @@ set_local_only (GtkFileChooserDefault *impl, shortcuts_add_bookmarks (impl); } - if (local_only && - !gtk_file_system_path_is_local (impl->file_system, impl->current_folder)) + if (local_only && !g_file_is_native (impl->current_folder)) { /* If we are pointing to a non-local folder, make an effort to change * back to a local folder, but it's really up to the app to not cause * such a situation, so we ignore errors. */ const gchar *home = g_get_home_dir (); - GtkFilePath *home_path; + GFile *home_file; if (home == NULL) return; - home_path = gtk_file_system_filename_to_path (impl->file_system, home); + home_file = g_file_new_for_path (home); - _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (impl), home_path, NULL); + _gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (impl), home_file, NULL); - gtk_file_path_free (home_path); + g_object_unref (home_file); } } } static void -volumes_changed_cb (GtkFileSystem *file_system, - GtkFileChooserDefault *impl) +volumes_bookmarks_changed_cb (GtkFileSystem *file_system, + GtkFileChooserDefault *impl) { shortcuts_add_volumes (impl); -} - -/* Callback used when the set of bookmarks changes in the file system */ -static void -bookmarks_changed_cb (GtkFileSystem *file_system, - GtkFileChooserDefault *impl) -{ shortcuts_add_bookmarks (impl); bookmarks_check_add_sensitivity (impl); @@ -5501,56 +5364,16 @@ set_select_multiple (GtkFileChooserDefault *impl, } static void -set_file_system_backend (GtkFileChooserDefault *impl, - const char *backend) +set_file_system_backend (GtkFileChooserDefault *impl) { - profile_start ("start for backend", backend ? backend : "default"); + profile_start ("start for backend", "default"); - if (impl->file_system) - { - g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id); - impl->volumes_changed_id = 0; - g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id); - impl->bookmarks_changed_id = 0; - g_object_unref (impl->file_system); - } + impl->file_system = gtk_file_system_new (); - impl->file_system = NULL; - if (backend) - impl->file_system = gtk_file_system_create (backend); - else - { - GtkSettings *settings = gtk_settings_get_default (); - gchar *default_backend = NULL; - - g_object_get (settings, "gtk-file-chooser-backend", &default_backend, NULL); - if (default_backend) - { - impl->file_system = gtk_file_system_create (default_backend); - g_free (default_backend); - } - } - - if (!impl->file_system) - { -#if defined (G_OS_UNIX) - impl->file_system = gtk_file_system_unix_new (); -#elif defined (G_OS_WIN32) - impl->file_system = gtk_file_system_win32_new (); -#else -#error "No default filesystem implementation on the platform" -#endif - } - - if (impl->file_system) - { - impl->volumes_changed_id = g_signal_connect (impl->file_system, "volumes-changed", - G_CALLBACK (volumes_changed_cb), - impl); - impl->bookmarks_changed_id = g_signal_connect (impl->file_system, "bookmarks-changed", - G_CALLBACK (bookmarks_changed_cb), - impl); - } + g_signal_connect (impl->file_system, "volumes-changed", + G_CALLBACK (volumes_bookmarks_changed_cb), impl); + g_signal_connect (impl->file_system, "bookmarks-changed", + G_CALLBACK (volumes_bookmarks_changed_cb), impl); profile_end ("end", NULL); } @@ -5661,7 +5484,7 @@ gtk_file_chooser_default_set_property (GObject *object, break; case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND: - set_file_system_backend (impl, g_value_get_string (value)); + /* Ignore property */ break; case GTK_FILE_CHOOSER_PROP_FILTER: @@ -5817,88 +5640,76 @@ gtk_file_chooser_default_dispose (GObject *object) impl->extra_widget = NULL; } - if (impl->volumes_changed_id > 0) - { - g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id); - impl->volumes_changed_id = 0; - } - - if (impl->bookmarks_changed_id > 0) - { - g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id); - impl->bookmarks_changed_id = 0; - } - - pending_select_paths_free (impl); + pending_select_files_free (impl); /* cancel all pending operations */ - if (impl->pending_handles) + if (impl->pending_cancellables) { - for (l = impl->pending_handles; l; l = l->next) + for (l = impl->pending_cancellables; l; l = l->next) { - GtkFileSystemHandle *handle =l->data; - gtk_file_system_cancel_operation (handle); + GCancellable *cancellable = G_CANCELLABLE (l->data); + g_cancellable_cancel (cancellable); } - g_slist_free (impl->pending_handles); - impl->pending_handles = NULL; + g_slist_free (impl->pending_cancellables); + impl->pending_cancellables = NULL; } - if (impl->reload_icon_handles) + if (impl->reload_icon_cancellables) { - for (l = impl->reload_icon_handles; l; l = l->next) + for (l = impl->reload_icon_cancellables; l; l = l->next) { - GtkFileSystemHandle *handle =l->data; - gtk_file_system_cancel_operation (handle); + GCancellable *cancellable = G_CANCELLABLE (l->data); + g_cancellable_cancel (cancellable); } - g_slist_free (impl->reload_icon_handles); - impl->reload_icon_handles = NULL; + g_slist_free (impl->reload_icon_cancellables); + impl->reload_icon_cancellables = NULL; } if (impl->loading_shortcuts) { for (l = impl->loading_shortcuts; l; l = l->next) { - GtkFileSystemHandle *handle =l->data; - gtk_file_system_cancel_operation (handle); + GCancellable *cancellable = G_CANCELLABLE (l->data); + g_cancellable_cancel (cancellable); } g_slist_free (impl->loading_shortcuts); impl->loading_shortcuts = NULL; } - if (impl->file_list_drag_data_received_handle) + if (impl->file_list_drag_data_received_cancellable) { - gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle); - impl->file_list_drag_data_received_handle = NULL; + g_cancellable_cancel (impl->file_list_drag_data_received_cancellable); + impl->file_list_drag_data_received_cancellable = NULL; } - if (impl->update_current_folder_handle) + if (impl->update_current_folder_cancellable) { - gtk_file_system_cancel_operation (impl->update_current_folder_handle); - impl->update_current_folder_handle = NULL; + g_cancellable_cancel (impl->update_current_folder_cancellable); + impl->update_current_folder_cancellable = NULL; } - if (impl->show_and_select_paths_handle) + if (impl->show_and_select_files_cancellable) { - gtk_file_system_cancel_operation (impl->show_and_select_paths_handle); - impl->show_and_select_paths_handle = NULL; + g_cancellable_cancel (impl->show_and_select_files_cancellable); + impl->show_and_select_files_cancellable = NULL; } - if (impl->should_respond_get_info_handle) + if (impl->should_respond_get_info_cancellable) { - gtk_file_system_cancel_operation (impl->should_respond_get_info_handle); - impl->should_respond_get_info_handle = NULL; + g_cancellable_cancel (impl->should_respond_get_info_cancellable); + impl->should_respond_get_info_cancellable = NULL; } - if (impl->update_from_entry_handle) + if (impl->update_from_entry_cancellable) { - gtk_file_system_cancel_operation (impl->update_from_entry_handle); - impl->update_from_entry_handle = NULL; + g_cancellable_cancel (impl->update_from_entry_cancellable); + impl->update_from_entry_cancellable = NULL; } - if (impl->shortcuts_activate_iter_handle) + if (impl->shortcuts_activate_iter_cancellable) { - gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle); - impl->shortcuts_activate_iter_handle = NULL; + g_cancellable_cancel (impl->shortcuts_activate_iter_cancellable); + impl->shortcuts_activate_iter_cancellable = NULL; } search_stop_searching (impl, TRUE); @@ -6125,8 +5936,8 @@ gtk_file_chooser_default_size_allocate (GtkWidget *widget, static gboolean get_is_file_filtered (GtkFileChooserDefault *impl, - const GtkFilePath *path, - GtkFileInfo *file_info) + GFile *file, + GFileInfo *file_info) { GtkFileFilterInfo filter_info; GtkFileFilterFlags needed; @@ -6139,12 +5950,12 @@ get_is_file_filtered (GtkFileChooserDefault *impl, needed = gtk_file_filter_get_needed (impl->current_filter); - filter_info.display_name = gtk_file_info_get_display_name (file_info); - filter_info.mime_type = gtk_file_info_get_mime_type (file_info); + filter_info.display_name = g_file_info_get_display_name (file_info); + filter_info.mime_type = g_file_info_get_content_type (file_info); if (needed & GTK_FILE_FILTER_FILENAME) { - filter_info.filename = gtk_file_system_path_to_filename (impl->file_system, path); + filter_info.filename = g_file_get_path (file); if (filter_info.filename) filter_info.contains |= GTK_FILE_FILTER_FILENAME; } @@ -6153,7 +5964,7 @@ get_is_file_filtered (GtkFileChooserDefault *impl, if (needed & GTK_FILE_FILTER_URI) { - filter_info.uri = gtk_file_system_path_to_uri (impl->file_system, path); + filter_info.uri = g_file_get_uri (file); if (filter_info.uri) filter_info.contains |= GTK_FILE_FILTER_URI; } @@ -6249,7 +6060,7 @@ gtk_file_chooser_default_map (GtkWidget *widget) */ if (impl->current_folder) { - pending_select_paths_store_selection (impl); + pending_select_files_store_selection (impl); change_folder_and_display_error (impl, impl->current_folder, FALSE); } break; @@ -6259,7 +6070,7 @@ gtk_file_chooser_default_map (GtkWidget *widget) } } - bookmarks_changed_cb (impl->file_system, impl); + volumes_bookmarks_changed_cb (impl->file_system, impl); settings_load (impl); @@ -6283,8 +6094,8 @@ gtk_file_chooser_default_unmap (GtkWidget *widget) static gboolean list_model_filter_func (GtkFileSystemModel *model, - GtkFilePath *path, - const GtkFileInfo *file_info, + GFile *file, + GFileInfo *file_info, gpointer user_data) { GtkFileChooserDefault *impl = user_data; @@ -6292,10 +6103,10 @@ list_model_filter_func (GtkFileSystemModel *model, if (!impl->current_filter) return TRUE; - if (gtk_file_info_get_is_folder (file_info)) + if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) return TRUE; - return !get_is_file_filtered (impl, path, (GtkFileInfo *) file_info); + return !get_is_file_filtered (impl, file, file_info); } static void @@ -6324,17 +6135,17 @@ install_list_model_filter (GtkFileChooserDefault *impl) #define COMPARE_DIRECTORIES \ GtkFileChooserDefault *impl = user_data; \ - const GtkFileInfo *info_a = _gtk_file_system_model_get_info (impl->browse_files_model, a); \ - const GtkFileInfo *info_b = _gtk_file_system_model_get_info (impl->browse_files_model, b); \ + GFileInfo *info_a = _gtk_file_system_model_get_info (impl->browse_files_model, a); \ + GFileInfo *info_b = _gtk_file_system_model_get_info (impl->browse_files_model, b); \ gboolean dir_a, dir_b; \ \ if (info_a) \ - dir_a = gtk_file_info_get_is_folder (info_a); \ + dir_a = (g_file_info_get_file_type (info_a) == G_FILE_TYPE_DIRECTORY); \ else \ return impl->list_sort_ascending ? -1 : 1; \ \ if (info_b) \ - dir_b = gtk_file_info_get_is_folder (info_b); \ + dir_b = (g_file_info_get_file_type (info_b) == G_FILE_TYPE_DIRECTORY); \ else \ return impl->list_sort_ascending ? 1 : -1; \ \ @@ -6350,7 +6161,19 @@ name_sort_func (GtkTreeModel *model, { COMPARE_DIRECTORIES; else - return strcmp (gtk_file_info_get_display_key (info_a), gtk_file_info_get_display_key (info_b)); + { + gchar *key_a, *key_b; + gint result; + + key_a = g_utf8_collate_key_for_filename (g_file_info_get_display_name (info_a), -1); + key_b = g_utf8_collate_key_for_filename (g_file_info_get_display_name (info_b), -1); + result = strcmp (key_a, key_b); + + g_free (key_a); + g_free (key_b); + + return result; + } } /* Sort callback for the size column */ @@ -6363,8 +6186,8 @@ size_sort_func (GtkTreeModel *model, COMPARE_DIRECTORIES; else { - gint64 size_a = gtk_file_info_get_size (info_a); - gint64 size_b = gtk_file_info_get_size (info_b); + goffset size_a = g_file_info_get_size (info_a); + goffset size_b = g_file_info_get_size (info_b); return size_a > size_b ? -1 : (size_a == size_b ? 0 : 1); } @@ -6380,10 +6203,12 @@ mtime_sort_func (GtkTreeModel *model, COMPARE_DIRECTORIES; else { - GtkFileTime ta = gtk_file_info_get_modification_time (info_a); - GtkFileTime tb = gtk_file_info_get_modification_time (info_b); + GTimeVal ta, tb; - return ta > tb ? -1 : (ta == tb ? 0 : 1); + g_file_info_get_modification_time (info_a, &ta); + g_file_info_get_modification_time (info_b, &tb); + + return ta.tv_sec > tb.tv_sec ? -1 : (ta.tv_sec == tb.tv_sec ? 0 : 1); } } @@ -6566,12 +6391,12 @@ browse_files_center_selected_row (GtkFileChooserDefault *impl) struct ShowAndSelectPathsData { GtkFileChooserDefault *impl; - GSList *paths; + GSList *files; }; static void -show_and_select_paths_finished_loading (GtkFileFolder *folder, - gpointer user_data) +show_and_select_files_finished_loading (GtkFolder *folder, + gpointer user_data) { gboolean have_hidden; gboolean have_filtered; @@ -6581,24 +6406,24 @@ show_and_select_paths_finished_loading (GtkFileFolder *folder, have_hidden = FALSE; have_filtered = FALSE; - for (l = data->paths; l; l = l->next) + for (l = data->files; l; l = l->next) { - const GtkFilePath *path; - GtkFileInfo *info; + GFile *file; + GFileInfo *info; - path = l->data; + file = l->data; - /* NULL GError */ - info = gtk_file_folder_get_info (folder, path, NULL); + info = gtk_folder_get_info (folder, file); if (info) { if (!have_hidden) - have_hidden = gtk_file_info_get_is_hidden (info); + have_hidden = g_file_info_get_is_hidden (info); if (!have_filtered) - have_filtered = !gtk_file_info_get_is_folder (info) && get_is_file_filtered (data->impl, path, info); + have_filtered = (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) && + get_is_file_filtered (data->impl, file, info); - gtk_file_info_free (info); + g_object_unref (info); if (have_hidden && have_filtered) break; /* we now have all the information we need */ @@ -6606,80 +6431,80 @@ show_and_select_paths_finished_loading (GtkFileFolder *folder, } g_signal_handlers_disconnect_by_func (folder, - show_and_select_paths_finished_loading, + show_and_select_files_finished_loading, user_data); - g_object_unref (folder); - if (have_hidden) g_object_set (data->impl, "show-hidden", TRUE, NULL); if (have_filtered) set_current_filter (data->impl, NULL); - for (l = data->paths; l; l = l->next) + for (l = data->files; l; l = l->next) { - const GtkFilePath *path; + GFile *file; - path = l->data; - _gtk_file_system_model_path_do (data->impl->browse_files_model, path, + file = l->data; + _gtk_file_system_model_path_do (data->impl->browse_files_model, file, select_func, data->impl); } browse_files_center_selected_row (data->impl); g_object_unref (data->impl); - gtk_file_paths_free (data->paths); + g_slist_foreach (data->files, (GFunc) g_object_unref, NULL); + g_slist_free (data->files); g_free (data); } static void -show_and_select_paths_get_folder_cb (GtkFileSystemHandle *handle, - GtkFileFolder *folder, - const GError *error, - gpointer user_data) +show_and_select_files_get_folder_cb (GCancellable *cancellable, + GtkFolder *folder, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct ShowAndSelectPathsData *data = user_data; - if (data->impl->show_and_select_paths_handle != handle) + if (data->impl->show_and_select_files_cancellable != cancellable) goto out; - data->impl->show_and_select_paths_handle = NULL; + data->impl->show_and_select_files_cancellable = NULL; if (cancelled || error) goto out; - g_object_unref (handle); + g_object_unref (cancellable); - if (gtk_file_folder_is_finished_loading (folder)) - show_and_select_paths_finished_loading (folder, user_data); + if (gtk_folder_is_finished_loading (folder)) + show_and_select_files_finished_loading (folder, user_data); else g_signal_connect (folder, "finished-loading", - G_CALLBACK (show_and_select_paths_finished_loading), + G_CALLBACK (show_and_select_files_finished_loading), user_data); return; out: g_object_unref (data->impl); - gtk_file_paths_free (data->paths); + g_slist_foreach (data->files, (GFunc) g_object_unref, NULL); + g_slist_free (data->files); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static gboolean -show_and_select_paths (GtkFileChooserDefault *impl, - const GtkFilePath *parent_path, - GSList *paths, +show_and_select_files (GtkFileChooserDefault *impl, + GFile *parent_file, + GSList *files, GError **error) { struct ShowAndSelectPathsData *info; profile_start ("start", NULL); - if (!paths) + if (!files) { profile_end ("end", NULL); return TRUE; @@ -6687,15 +6512,16 @@ show_and_select_paths (GtkFileChooserDefault *impl, info = g_new (struct ShowAndSelectPathsData, 1); info->impl = g_object_ref (impl); - info->paths = gtk_file_paths_copy (paths); + info->files = g_slist_copy (files); + g_slist_foreach (info->files, (GFunc) g_object_ref, NULL); - if (impl->show_and_select_paths_handle) - gtk_file_system_cancel_operation (impl->show_and_select_paths_handle); + if (impl->show_and_select_files_cancellable) + g_cancellable_cancel (impl->show_and_select_files_cancellable); - impl->show_and_select_paths_handle = - gtk_file_system_get_folder (impl->file_system, parent_path, - GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_IS_HIDDEN, - show_and_select_paths_get_folder_cb, info); + impl->show_and_select_files_cancellable = + gtk_file_system_get_folder (impl->file_system, parent_file, + "standard::is-hidden,standard::type,standard::name", + show_and_select_files_get_folder_cb, info); profile_end ("end", NULL); return TRUE; @@ -6703,17 +6529,17 @@ show_and_select_paths (GtkFileChooserDefault *impl, /* Processes the pending operation when a folder is finished loading */ static void -pending_select_paths_process (GtkFileChooserDefault *impl) +pending_select_files_process (GtkFileChooserDefault *impl) { g_assert (impl->load_state == LOAD_FINISHED); g_assert (impl->browse_files_model != NULL); g_assert (impl->sort_model != NULL); - if (impl->pending_select_paths) + if (impl->pending_select_files) { /* NULL GError */ - show_and_select_paths (impl, impl->current_folder, impl->pending_select_paths, NULL); - pending_select_paths_free (impl); + show_and_select_files (impl, impl->current_folder, impl->pending_select_files, NULL); + pending_select_files_free (impl); browse_files_center_selected_row (impl); } else @@ -6729,7 +6555,7 @@ pending_select_paths_process (GtkFileChooserDefault *impl) browse_files_select_first_row (impl); } - g_assert (impl->pending_select_paths == NULL); + g_assert (impl->pending_select_files == NULL); } /* Callback used when the file system model finishes loading */ @@ -6761,7 +6587,7 @@ browse_files_model_finished_loading_cb (GtkFileSystemModel *model, impl->load_state = LOAD_FINISHED; - pending_select_paths_process (impl); + pending_select_files_process (impl); set_busy_cursor (impl, FALSE); #ifdef PROFILE_FILE_CHOOSER access ("MARK: *** FINISHED LOADING", F_OK); @@ -6806,7 +6632,7 @@ set_list_model (GtkFileChooserDefault *impl, impl->browse_files_model = _gtk_file_system_model_new (impl->file_system, impl->current_folder, 0, - GTK_FILE_INFO_ALL, + "standard,time,thumbnail::*", error); if (!impl->browse_files_model) { @@ -6905,7 +6731,7 @@ update_chooser_entry (GtkFileChooserDefault *impl) if (impl->operation_mode == OPERATION_MODE_BROWSE) { - const GtkFileInfo *info; + GFileInfo *info; gboolean change_entry; gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, @@ -6922,11 +6748,14 @@ update_chooser_entry (GtkFileChooserDefault *impl) g_free (impl->browse_files_last_selected_name); impl->browse_files_last_selected_name = - g_strdup (gtk_file_info_get_display_name (info)); + g_strdup (g_file_info_get_display_name (info)); if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) - change_entry = !gtk_file_info_get_is_folder (info); /* We don't want the name to change when clicking on a folder... */ + { + /* We don't want the name to change when clicking on a folder... */ + change_entry = (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY); + } else change_entry = TRUE; /* ... unless we are in one of the folder modes */ @@ -6990,38 +6819,38 @@ update_chooser_entry (GtkFileChooserDefault *impl) } static gboolean -gtk_file_chooser_default_set_current_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +gtk_file_chooser_default_set_current_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { - return gtk_file_chooser_default_update_current_folder (chooser, path, FALSE, FALSE, error); + return gtk_file_chooser_default_update_current_folder (chooser, file, FALSE, FALSE, error); } struct UpdateCurrentFolderData { GtkFileChooserDefault *impl; - GtkFilePath *path; + GFile *file; gboolean keep_trail; gboolean clear_entry; - GtkFilePath *original_path; + GFile *original_file; GError *original_error; }; static void -update_current_folder_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +update_current_folder_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct UpdateCurrentFolderData *data = user_data; GtkFileChooserDefault *impl = data->impl; - if (handle != impl->update_current_folder_handle) + if (cancellable != impl->update_current_folder_cancellable) goto out; - impl->update_current_folder_handle = NULL; + impl->update_current_folder_cancellable = NULL; impl->reload_state = RELOAD_EMPTY; set_busy_cursor (impl, FALSE); @@ -7031,29 +6860,30 @@ update_current_folder_get_info_cb (GtkFileSystemHandle *handle, if (error) { - GtkFilePath *parent_path; + GFile *parent_file; - if (!data->original_path) + if (!data->original_file) { - data->original_path = gtk_file_path_copy (data->path); + data->original_file = g_object_ref (data->file); data->original_error = g_error_copy (error); } + parent_file = g_file_get_parent (data->file); + /* get parent path and try to change the folder to that */ - if (gtk_file_system_get_parent (impl->file_system, data->path, &parent_path, NULL) && - parent_path != NULL) + if (parent_file) { - gtk_file_path_free (data->path); - data->path = parent_path; + g_object_unref (data->file); + data->file = parent_file; - g_object_unref (handle); + g_object_unref (cancellable); /* restart the update current folder operation */ impl->reload_state = RELOAD_HAS_FOLDER; - impl->update_current_folder_handle = - gtk_file_system_get_info (impl->file_system, data->path, - GTK_FILE_INFO_IS_FOLDER, + impl->update_current_folder_cancellable = + gtk_file_system_get_info (impl->file_system, data->file, + "standard::type", update_current_folder_get_info_cb, data); @@ -7064,33 +6894,32 @@ update_current_folder_get_info_cb (GtkFileSystemHandle *handle, else { /* error and bail out */ - error_changing_folder_dialog (impl, data->original_path, data->original_error); - - gtk_file_path_free (data->original_path); + error_changing_folder_dialog (impl, data->original_file, data->original_error); + g_object_unref (data->original_file); goto out; } } - if (data->original_path) + if (data->original_file) { - error_changing_folder_dialog (impl, data->original_path, data->original_error); + error_changing_folder_dialog (impl, data->original_file, data->original_error); - gtk_file_path_free (data->original_path); + g_object_unref (data->original_file); } - if (!gtk_file_info_get_is_folder (info)) + if (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) goto out; - if (!_gtk_path_bar_set_path (GTK_PATH_BAR (impl->browse_path_bar), data->path, data->keep_trail, NULL)) + if (!_gtk_path_bar_set_file (GTK_PATH_BAR (impl->browse_path_bar), data->file, data->keep_trail, NULL)) goto out; - if (impl->current_folder != data->path) + if (impl->current_folder != data->file) { if (impl->current_folder) - gtk_file_path_free (impl->current_folder); + g_object_unref (impl->current_folder); - impl->current_folder = gtk_file_path_copy (data->path); + impl->current_folder = g_object_ref (data->file); impl->reload_state = RELOAD_HAS_FOLDER; } @@ -7135,15 +6964,15 @@ update_current_folder_get_info_cb (GtkFileSystemHandle *handle, g_signal_emit_by_name (impl, "selection-changed", 0); out: - gtk_file_path_free (data->path); + g_object_unref (data->file); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static gboolean gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, gboolean keep_trail, gboolean clear_entry, GError **error) @@ -7151,7 +6980,7 @@ gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser, GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); struct UpdateCurrentFolderData *data; - profile_start ("start", (char *) path); + profile_start ("start", NULL); switch (impl->operation_mode) { @@ -7165,34 +6994,32 @@ gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser, break; } - g_assert (path != NULL); - - if (impl->local_only && - !gtk_file_system_path_is_local (impl->file_system, path)) + if (impl->local_only && !g_file_is_native (file)) { g_set_error (error, GTK_FILE_CHOOSER_ERROR, GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, _("Cannot change to folder because it is not local")); - profile_end ("end - not local", (char *) path); + profile_end ("end - not local", NULL); return FALSE; } - if (impl->update_current_folder_handle) - gtk_file_system_cancel_operation (impl->update_current_folder_handle); + if (impl->update_current_folder_cancellable) + g_cancellable_cancel (impl->update_current_folder_cancellable); /* Test validity of path here. */ data = g_new0 (struct UpdateCurrentFolderData, 1); data->impl = impl; - data->path = gtk_file_path_copy (path); + data->file = g_object_ref (file); data->keep_trail = keep_trail; data->clear_entry = clear_entry; impl->reload_state = RELOAD_HAS_FOLDER; - impl->update_current_folder_handle = - gtk_file_system_get_info (impl->file_system, path, GTK_FILE_INFO_IS_FOLDER, + impl->update_current_folder_cancellable = + gtk_file_system_get_info (impl->file_system, file, + "standard::type", update_current_folder_get_info_cb, data); @@ -7202,7 +7029,7 @@ gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser, return TRUE; } -static GtkFilePath * +static GFile * gtk_file_chooser_default_get_current_folder (GtkFileChooser *chooser) { GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); @@ -7214,19 +7041,19 @@ gtk_file_chooser_default_get_current_folder (GtkFileChooser *chooser) if (impl->reload_state == RELOAD_EMPTY) { char *current_working_dir; - GtkFilePath *path; + GFile *file; /* We are unmapped, or we had an error while loading the last folder. We'll return * the $cwd since once we get (re)mapped, we'll load $cwd anyway unless the caller * explicitly calls set_current_folder() on us. */ current_working_dir = g_get_current_dir (); - path = gtk_file_system_filename_to_path (impl->file_system, current_working_dir); + file = g_file_new_for_path (current_working_dir); g_free (current_working_dir); - return path; + return file; } - return gtk_file_path_copy (impl->current_folder); + return g_object_ref (impl->current_folder); } static void @@ -7238,7 +7065,7 @@ gtk_file_chooser_default_set_current_name (GtkFileChooser *chooser, g_return_if_fail (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER); - pending_select_paths_free (impl); + pending_select_files_free (impl); _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), name); } @@ -7259,19 +7086,18 @@ select_func (GtkFileSystemModel *model, } static gboolean -gtk_file_chooser_default_select_path (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +gtk_file_chooser_default_select_file (GtkFileChooser *chooser, + GFile *file, + GError **error) { GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); - GtkFilePath *parent_path; + GFile *parent_file; gboolean same_path; - if (!gtk_file_system_get_parent (impl->file_system, path, &parent_path, error)) - return FALSE; + parent_file = g_file_get_parent (file); - if (!parent_path) - return _gtk_file_chooser_set_current_folder_path (chooser, path, error); + if (!parent_file) + return _gtk_file_chooser_set_current_folder_file (chooser, file, error); if (impl->operation_mode == OPERATION_MODE_SEARCH || impl->operation_mode == OPERATION_MODE_RECENT || @@ -7283,34 +7109,34 @@ gtk_file_chooser_default_select_path (GtkFileChooser *chooser, { g_assert (impl->current_folder != NULL); - same_path = gtk_file_path_compare (parent_path, impl->current_folder) == 0; + same_path = g_file_equal (parent_file, impl->current_folder); } if (same_path && impl->load_state == LOAD_FINISHED) { gboolean result; - GSList paths; + GSList files; - paths.data = (gpointer) path; - paths.next = NULL; + files.data = (gpointer) file; + files.next = NULL; - result = show_and_select_paths (impl, parent_path, &paths, error); - gtk_file_path_free (parent_path); + result = show_and_select_files (impl, parent_file, &files, error); + g_object_unref (parent_file); return result; } - pending_select_paths_add (impl, path); + pending_select_files_add (impl, file); if (!same_path) { gboolean result; - result = _gtk_file_chooser_set_current_folder_path (chooser, parent_path, error); - gtk_file_path_free (parent_path); + result = _gtk_file_chooser_set_current_folder_file (chooser, parent_file, error); + g_object_unref (parent_file); return result; } - gtk_file_path_free (parent_path); + g_object_unref (parent_file); return TRUE; } @@ -7332,15 +7158,15 @@ unselect_func (GtkFileSystemModel *model, } static void -gtk_file_chooser_default_unselect_path (GtkFileChooser *chooser, - const GtkFilePath *path) +gtk_file_chooser_default_unselect_file (GtkFileChooser *chooser, + GFile *file) { GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); if (!impl->browse_files_model) return; - _gtk_file_system_model_path_do (impl->browse_files_model, path, + _gtk_file_system_model_path_do (impl->browse_files_model, file, unselect_func, impl); } @@ -7352,13 +7178,13 @@ maybe_select (GtkTreeModel *model, { GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data); GtkTreeSelection *selection; - const GtkFileInfo *info; + GFileInfo *info; gboolean is_folder; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); info = get_list_file_info (impl, iter); - is_folder = gtk_file_info_get_is_folder (info); + is_folder = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); if ((is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) || (!is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)) @@ -7396,7 +7222,7 @@ gtk_file_chooser_default_unselect_all (GtkFileChooser *chooser) GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); gtk_tree_selection_unselect_all (selection); - pending_select_paths_free (impl); + pending_select_files_free (impl); } /* Checks whether the filename entry for the Save modes contains a well-formed filename. @@ -7410,16 +7236,16 @@ gtk_file_chooser_default_unselect_all (GtkFileChooser *chooser) */ static void check_save_entry (GtkFileChooserDefault *impl, - GtkFilePath **path_ret, + GFile **file_ret, gboolean *is_well_formed_ret, gboolean *is_empty_ret, gboolean *is_file_part_empty_ret, gboolean *is_folder) { GtkFileChooserEntry *chooser_entry; - const GtkFilePath *current_folder; + GFile *current_folder; const char *file_part; - GtkFilePath *path; + GFile *file; GError *error; g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE @@ -7432,7 +7258,7 @@ check_save_entry (GtkFileChooserDefault *impl, if (strlen (gtk_entry_get_text (GTK_ENTRY (chooser_entry))) == 0) { - *path_ret = NULL; + *file_ret = NULL; *is_well_formed_ret = TRUE; *is_empty_ret = TRUE; *is_file_part_empty_ret = TRUE; @@ -7446,7 +7272,7 @@ check_save_entry (GtkFileChooserDefault *impl, current_folder = _gtk_file_chooser_entry_get_current_folder (chooser_entry); if (!current_folder) { - *path_ret = NULL; + *file_ret = NULL; *is_well_formed_ret = FALSE; *is_file_part_empty_ret = FALSE; *is_folder = FALSE; @@ -7458,7 +7284,7 @@ check_save_entry (GtkFileChooserDefault *impl, if (!file_part || file_part[0] == '\0') { - *path_ret = gtk_file_path_copy (current_folder); + *file_ret = g_object_ref (current_folder); *is_well_formed_ret = TRUE; *is_file_part_empty_ret = TRUE; *is_folder = TRUE; @@ -7469,37 +7295,37 @@ check_save_entry (GtkFileChooserDefault *impl, *is_file_part_empty_ret = FALSE; error = NULL; - path = gtk_file_system_make_path (impl->file_system, current_folder, file_part, &error); + file = g_file_get_child_for_display_name (current_folder, file_part, &error); - if (!path) + if (!file) { - error_building_filename_dialog (impl, current_folder, file_part, error); - *path_ret = NULL; + error_building_filename_dialog (impl, error); + *file_ret = NULL; *is_well_formed_ret = FALSE; *is_folder = FALSE; return; } - *path_ret = path; + *file_ret = file; *is_well_formed_ret = TRUE; - *is_folder = _gtk_file_chooser_entry_get_is_folder (chooser_entry, path); + *is_folder = _gtk_file_chooser_entry_get_is_folder (chooser_entry, file); } -struct get_paths_closure { +struct get_files_closure { GtkFileChooserDefault *impl; GSList *result; - GtkFilePath *path_from_entry; + GFile *file_from_entry; }; static void -get_paths_foreach (GtkTreeModel *model, +get_files_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { - struct get_paths_closure *info; - const GtkFilePath *file_path; + struct get_files_closure *info; + GFile *file; GtkFileSystemModel *fs_model; GtkTreeIter sel_iter; @@ -7507,33 +7333,32 @@ get_paths_foreach (GtkTreeModel *model, fs_model = info->impl->browse_files_model; gtk_tree_model_sort_convert_iter_to_child_iter (info->impl->sort_model, &sel_iter, iter); - file_path = _gtk_file_system_model_get_path (fs_model, &sel_iter); - if (!file_path) + file = _gtk_file_system_model_get_file (fs_model, &sel_iter); + if (!file) return; /* We are on the editable row */ - if (!info->path_from_entry - || gtk_file_path_compare (info->path_from_entry, file_path) != 0) - info->result = g_slist_prepend (info->result, gtk_file_path_copy (file_path)); + if (!info->file_from_entry || !g_file_equal (info->file_from_entry, file)) + info->result = g_slist_prepend (info->result, g_object_ref (file)); } static GSList * -gtk_file_chooser_default_get_paths (GtkFileChooser *chooser) +gtk_file_chooser_default_get_files (GtkFileChooser *chooser) { GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); - struct get_paths_closure info; + struct get_files_closure info; GtkWindow *toplevel; GtkWidget *current_focus; gboolean file_list_seen; if (impl->operation_mode == OPERATION_MODE_SEARCH) - return search_get_selected_paths (impl); + return search_get_selected_files (impl); if (impl->operation_mode == OPERATION_MODE_RECENT) - return recent_get_selected_paths (impl); + return recent_get_selected_files (impl); info.impl = impl; info.result = NULL; - info.path_from_entry = NULL; + info.file_from_entry = NULL; toplevel = get_toplevel (GTK_WIDGET (impl)); if (toplevel) @@ -7550,7 +7375,7 @@ gtk_file_chooser_default_get_paths (GtkFileChooser *chooser) file_list_seen = TRUE; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); - gtk_tree_selection_selected_foreach (selection, get_paths_foreach, &info); + gtk_tree_selection_selected_foreach (selection, get_files_foreach, &info); /* If there is no selection in the file list, we probably have this situation: * @@ -7569,7 +7394,7 @@ gtk_file_chooser_default_get_paths (GtkFileChooser *chooser) file_entry: - check_save_entry (impl, &info.path_from_entry, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder); + check_save_entry (impl, &info.file_from_entry, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder); if (is_empty) goto out; @@ -7579,12 +7404,12 @@ gtk_file_chooser_default_get_paths (GtkFileChooser *chooser) if (is_file_part_empty && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) { - gtk_file_path_free (info.path_from_entry); + g_object_unref (info.file_from_entry); return NULL; } - if (info.path_from_entry) - info.result = g_slist_prepend (info.result, info.path_from_entry); + if (info.file_from_entry) + info.result = g_slist_prepend (info.result, info.file_from_entry); else if (!file_list_seen) goto file_list; else @@ -7611,19 +7436,19 @@ gtk_file_chooser_default_get_paths (GtkFileChooser *chooser) if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER && info.result == NULL) { - info.result = g_slist_prepend (info.result, _gtk_file_chooser_get_current_folder_path (chooser)); + info.result = g_slist_prepend (info.result, _gtk_file_chooser_get_current_folder_file (chooser)); } return g_slist_reverse (info.result); } -static GtkFilePath * -gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser) +static GFile * +gtk_file_chooser_default_get_preview_file (GtkFileChooser *chooser) { GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); - if (impl->preview_path) - return gtk_file_path_copy (impl->preview_path); + if (impl->preview_file) + return g_object_ref (impl->preview_file); else return NULL; } @@ -7734,57 +7559,57 @@ shortcuts_get_pos_for_shortcut_folder (GtkFileChooserDefault *impl, struct AddShortcutData { GtkFileChooserDefault *impl; - GtkFilePath *path; + GFile *file; }; static void -add_shortcut_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +add_shortcut_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { int pos; - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct AddShortcutData *data = user_data; - if (!g_slist_find (data->impl->loading_shortcuts, handle)) + if (!g_slist_find (data->impl->loading_shortcuts, cancellable)) goto out; - data->impl->loading_shortcuts = g_slist_remove (data->impl->loading_shortcuts, handle); + data->impl->loading_shortcuts = g_slist_remove (data->impl->loading_shortcuts, cancellable); - if (cancelled || error || !gtk_file_info_get_is_folder (info)) + if (cancelled || error || g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) goto out; pos = shortcuts_get_pos_for_shortcut_folder (data->impl, data->impl->num_shortcuts); - shortcuts_insert_path (data->impl, pos, SHORTCUT_TYPE_PATH, NULL, data->path, NULL, FALSE, SHORTCUTS_SHORTCUTS); + shortcuts_insert_file (data->impl, pos, SHORTCUT_TYPE_FILE, NULL, data->file, NULL, FALSE, SHORTCUTS_SHORTCUTS); out: g_object_unref (data->impl); - gtk_file_path_free (data->path); + g_object_unref (data->file); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static gboolean -gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { - GtkFileSystemHandle *handle; + GCancellable *cancellable; GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); struct AddShortcutData *data; GSList *l; int pos; /* Avoid adding duplicates */ - pos = shortcut_find_position (impl, path); + pos = shortcut_find_position (impl, file); if (pos >= 0 && pos < shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR)) { gchar *uri; - uri = gtk_file_system_path_to_uri (impl->file_system, path); + uri = g_file_get_uri (file); /* translators, "Shortcut" means "Bookmark" here */ g_set_error (error, GTK_FILE_CHOOSER_ERROR, @@ -7798,15 +7623,15 @@ gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser, for (l = impl->loading_shortcuts; l; l = l->next) { - GtkFileSystemHandle *h = l->data; - GtkFilePath *p; + GCancellable *c = l->data; + GFile *f; - p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key"); - if (p && !gtk_file_path_compare (path, p)) + f = g_object_get_data (G_OBJECT (c), "add-shortcut-path-key"); + if (f && g_file_equal (file, f)) { gchar *uri; - uri = gtk_file_system_path_to_uri (impl->file_system, path); + uri = g_file_get_uri (file); g_set_error (error, GTK_FILE_CHOOSER_ERROR, GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS, @@ -7820,25 +7645,25 @@ gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser, data = g_new0 (struct AddShortcutData, 1); data->impl = g_object_ref (impl); - data->path = gtk_file_path_copy (path); + data->file = g_object_ref (file); - handle = gtk_file_system_get_info (impl->file_system, path, - GTK_FILE_INFO_IS_FOLDER, - add_shortcut_get_info_cb, data); + cancellable = gtk_file_system_get_info (impl->file_system, file, + "standard::type", + add_shortcut_get_info_cb, data); - if (!handle) + if (!cancellable) return FALSE; - impl->loading_shortcuts = g_slist_append (impl->loading_shortcuts, handle); - g_object_set_data (G_OBJECT (handle), "add-shortcut-path-key", data->path); + impl->loading_shortcuts = g_slist_append (impl->loading_shortcuts, cancellable); + g_object_set_data (G_OBJECT (cancellable), "add-shortcut-path-key", data->file); return TRUE; } static gboolean -gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser); int pos; @@ -7849,14 +7674,14 @@ gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser, for (l = impl->loading_shortcuts; l; l = l->next) { - GtkFileSystemHandle *h = l->data; - GtkFilePath *p; + GCancellable *c = l->data; + GFile *f; - p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key"); - if (p && !gtk_file_path_compare (path, p)) + f = g_object_get_data (G_OBJECT (c), "add-shortcut-path-key"); + if (f && g_file_equal (file, f)) { - impl->loading_shortcuts = g_slist_remove (impl->loading_shortcuts, h); - gtk_file_system_cancel_operation (h); + impl->loading_shortcuts = g_slist_remove (impl->loading_shortcuts, c); + g_cancellable_cancel (c); return TRUE; } } @@ -7872,17 +7697,17 @@ gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser, { gpointer col_data; ShortcutType shortcut_type; - GtkFilePath *shortcut; + GFile *shortcut; gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, SHORTCUTS_COL_DATA, &col_data, SHORTCUTS_COL_TYPE, &shortcut_type, -1); g_assert (col_data != NULL); - g_assert (shortcut_type == SHORTCUT_TYPE_PATH); + g_assert (shortcut_type == SHORTCUT_TYPE_FILE); shortcut = col_data; - if (gtk_file_path_compare (shortcut, path) == 0) + if (g_file_equal (shortcut, file)) { shortcuts_remove_rows (impl, pos + i, 1); impl->num_shortcuts--; @@ -7895,7 +7720,7 @@ gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser, out: - uri = gtk_file_system_path_to_uri (impl->file_system, path); + uri = g_file_get_uri (file); /* translators, "Shortcut" means "Bookmark" here */ g_set_error (error, GTK_FILE_CHOOSER_ERROR, @@ -7929,17 +7754,17 @@ gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser) { gpointer col_data; ShortcutType shortcut_type; - GtkFilePath *shortcut; + GFile *shortcut; gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter, SHORTCUTS_COL_DATA, &col_data, SHORTCUTS_COL_TYPE, &shortcut_type, -1); g_assert (col_data != NULL); - g_assert (shortcut_type == SHORTCUT_TYPE_PATH); + g_assert (shortcut_type == SHORTCUT_TYPE_FILE); shortcut = col_data; - list = g_slist_prepend (list, gtk_file_path_copy (shortcut)); + list = g_slist_prepend (list, g_object_ref (shortcut)); if (i != impl->num_shortcuts - 1) { @@ -8018,7 +7843,7 @@ gtk_file_chooser_default_get_default_size (GtkFileChooserEmbed *chooser_embed, struct switch_folder_closure { GtkFileChooserDefault *impl; - const GtkFilePath *path; + GFile *file; int num_selected; }; @@ -8036,7 +7861,7 @@ switch_folder_foreach_cb (GtkTreeModel *model, gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter); - closure->path = _gtk_file_system_model_get_path (closure->impl->browse_files_model, &child_iter); + closure->file = _gtk_file_system_model_get_file (closure->impl->browse_files_model, &child_iter); closure->num_selected++; } @@ -8052,27 +7877,27 @@ switch_to_selected_folder (GtkFileChooserDefault *impl) */ closure.impl = impl; - closure.path = NULL; + closure.file = NULL; closure.num_selected = 0; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); gtk_tree_selection_selected_foreach (selection, switch_folder_foreach_cb, &closure); - g_assert (closure.path && closure.num_selected == 1); + g_assert (closure.file && closure.num_selected == 1); - change_folder_and_display_error (impl, closure.path, FALSE); + change_folder_and_display_error (impl, closure.file, FALSE); } -/* Gets the GtkFileInfo for the selected row in the file list; assumes single +/* Gets the GFileInfo for the selected row in the file list; assumes single * selection mode. */ -static const GtkFileInfo * +static GFileInfo * get_selected_file_info_from_file_list (GtkFileChooserDefault *impl, gboolean *had_selection) { GtkTreeSelection *selection; GtkTreeIter iter, child_iter; - const GtkFileInfo *info; + GFileInfo *info; g_assert (!impl->select_multiple); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); @@ -8098,14 +7923,14 @@ get_selected_file_info_from_file_list (GtkFileChooserDefault *impl, static const gchar * get_display_name_from_file_list (GtkFileChooserDefault *impl) { - const GtkFileInfo *info; + GFileInfo *info; gboolean had_selection; info = get_selected_file_info_from_file_list (impl, &had_selection); g_assert (had_selection); g_assert (info != NULL); - return gtk_file_info_get_display_name (info); + return g_file_info_get_display_name (info); } static void @@ -8176,19 +8001,19 @@ struct GetDisplayNameData }; static void -confirmation_confirm_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +confirmation_confirm_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); gboolean should_respond = FALSE; struct GetDisplayNameData *data = user_data; - if (handle != data->impl->should_respond_get_info_handle) + if (cancellable != data->impl->should_respond_get_info_cancellable) goto out; - data->impl->should_respond_get_info_handle = NULL; + data->impl->should_respond_get_info_cancellable = NULL; if (cancelled) goto out; @@ -8197,7 +8022,7 @@ confirmation_confirm_get_info_cb (GtkFileSystemHandle *handle, /* Huh? Did the folder disappear? Let the caller deal with it */ should_respond = TRUE; else - should_respond = confirm_dialog_should_accept_filename (data->impl, data->file_part, gtk_file_info_get_display_name (info)); + should_respond = confirm_dialog_should_accept_filename (data->impl, data->file_part, g_file_info_get_display_name (info)); set_busy_cursor (data->impl, FALSE); if (should_respond) @@ -8208,7 +8033,7 @@ out: g_free (data->file_part); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } /* Does overwrite confirmation if appropriate, and returns whether the dialog @@ -8217,7 +8042,7 @@ out: static gboolean should_respond_after_confirm_overwrite (GtkFileChooserDefault *impl, const gchar *file_part, - const GtkFilePath *parent_path) + GFile *parent_file) { GtkFileChooserConfirmation conf; @@ -8240,12 +8065,12 @@ should_respond_after_confirm_overwrite (GtkFileChooserDefault *impl, data->impl = g_object_ref (impl); data->file_part = g_strdup (file_part); - if (impl->should_respond_get_info_handle) - gtk_file_system_cancel_operation (impl->should_respond_get_info_handle); + if (impl->should_respond_get_info_cancellable) + g_cancellable_cancel (impl->should_respond_get_info_cancellable); - impl->should_respond_get_info_handle = - gtk_file_system_get_info (impl->file_system, parent_path, - GTK_FILE_INFO_DISPLAY_NAME, + impl->should_respond_get_info_cancellable = + gtk_file_system_get_info (impl->file_system, parent_file, + "standard::display-name", confirmation_confirm_get_info_cb, data); set_busy_cursor (data->impl, TRUE); @@ -8264,57 +8089,28 @@ should_respond_after_confirm_overwrite (GtkFileChooserDefault *impl, } } -static void -action_create_folder_cb (GtkFileSystemHandle *handle, - const GtkFilePath *path, - const GError *error, - gpointer user_data) -{ - gboolean cancelled = handle->cancelled; - GtkFileChooserDefault *impl = user_data; - - if (!g_slist_find (impl->pending_handles, handle)) - goto out; - - impl->pending_handles = g_slist_remove (impl->pending_handles, handle); - - set_busy_cursor (impl, FALSE); - - if (cancelled) - goto out; - - if (error) - error_creating_folder_dialog (impl, path, g_error_copy (error)); - else - g_signal_emit_by_name (impl, "response-requested"); - -out: - g_object_unref (impl); - g_object_unref (handle); -} - struct FileExistsData { GtkFileChooserDefault *impl; gboolean file_exists_and_is_not_folder; - GtkFilePath *parent_path; - GtkFilePath *path; + GFile *parent_file; + GFile *file; }; static void -save_entry_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +save_entry_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { gboolean parent_is_folder; - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct FileExistsData *data = user_data; - if (handle != data->impl->should_respond_get_info_handle) + if (cancellable != data->impl->should_respond_get_info_cancellable) goto out; - data->impl->should_respond_get_info_handle = NULL; + data->impl->should_respond_get_info_cancellable = NULL; set_busy_cursor (data->impl, FALSE); @@ -8324,7 +8120,7 @@ save_entry_get_info_cb (GtkFileSystemHandle *handle, if (!info) parent_is_folder = FALSE; else - parent_is_folder = gtk_file_info_get_is_folder (info); + parent_is_folder = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); if (parent_is_folder) { @@ -8336,7 +8132,7 @@ save_entry_get_info_cb (GtkFileSystemHandle *handle, const char *file_part; file_part = _gtk_file_chooser_entry_get_file_part (GTK_FILE_CHOOSER_ENTRY (data->impl->location_entry)); - retval = should_respond_after_confirm_overwrite (data->impl, file_part, data->parent_path); + retval = should_respond_after_confirm_overwrite (data->impl, file_part, data->parent_file); if (retval) g_signal_emit_by_name (data->impl, "response-requested"); @@ -8346,54 +8142,55 @@ save_entry_get_info_cb (GtkFileSystemHandle *handle, } else /* GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER */ { - GtkFileSystemHandle *handle; - - g_object_ref (data->impl); - handle = gtk_file_system_create_folder (data->impl->file_system, - data->path, - action_create_folder_cb, - data->impl); - data->impl->pending_handles = g_slist_append (data->impl->pending_handles, handle); + GError *error = NULL; + set_busy_cursor (data->impl, TRUE); + g_file_make_directory (data->file, NULL, &error); + set_busy_cursor (data->impl, FALSE); + + if (!error) + g_signal_emit_by_name (data->impl, "response-requested"); + else + error_creating_folder_dialog (data->impl, data->file, error); } } else { /* This will display an error, which is what we want */ - change_folder_and_display_error (data->impl, data->parent_path, FALSE); + change_folder_and_display_error (data->impl, data->parent_file, FALSE); } out: g_object_unref (data->impl); - gtk_file_path_free (data->path); - gtk_file_path_free (data->parent_path); + g_object_unref (data->file); + g_object_unref (data->parent_file); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static void -file_exists_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +file_exists_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { gboolean data_ownership_taken = FALSE; - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); gboolean file_exists_and_is_not_folder; struct FileExistsData *data = user_data; - if (handle != data->impl->file_exists_get_info_handle) + if (cancellable != data->impl->file_exists_get_info_cancellable) goto out; - data->impl->file_exists_get_info_handle = NULL; + data->impl->file_exists_get_info_cancellable = NULL; set_busy_cursor (data->impl, FALSE); if (cancelled) goto out; - file_exists_and_is_not_folder = info && !gtk_file_info_get_is_folder (info); + file_exists_and_is_not_folder = info && (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY); if (data->impl->action == GTK_FILE_CHOOSER_ACTION_OPEN) /* user typed a filename; we are done */ @@ -8404,7 +8201,7 @@ file_exists_get_info_cb (GtkFileSystemHandle *handle, /* Oops, the user typed the name of an existing path which is not * a folder */ - error_creating_folder_over_existing_file_dialog (data->impl, data->path, + error_creating_folder_over_existing_file_dialog (data->impl, data->file, g_error_copy (error)); } else @@ -8414,13 +8211,13 @@ file_exists_get_info_cb (GtkFileSystemHandle *handle, data->file_exists_and_is_not_folder = file_exists_and_is_not_folder; data_ownership_taken = TRUE; - if (data->impl->should_respond_get_info_handle) - gtk_file_system_cancel_operation (data->impl->should_respond_get_info_handle); + if (data->impl->should_respond_get_info_cancellable) + g_cancellable_cancel (data->impl->should_respond_get_info_cancellable); - data->impl->should_respond_get_info_handle = + data->impl->should_respond_get_info_cancellable = gtk_file_system_get_info (data->impl->file_system, - data->parent_path, - GTK_FILE_INFO_IS_FOLDER, + data->parent_file, + "standard::type", save_entry_get_info_cb, data); set_busy_cursor (data->impl, TRUE); @@ -8430,12 +8227,12 @@ out: if (!data_ownership_taken) { g_object_unref (data->impl); - gtk_file_path_free (data->path); - gtk_file_path_free (data->parent_path); + g_object_unref (data->file); + g_object_unref (data->parent_file); g_free (data); } - g_object_unref (handle); + g_object_unref (cancellable); } static void @@ -8443,32 +8240,17 @@ paste_text_received (GtkClipboard *clipboard, const gchar *text, GtkFileChooserDefault *impl) { - GtkFilePath *path; + GFile *file; if (!text) return; - path = gtk_file_system_uri_to_path (impl->file_system, text); - if (!path) - { - if (!g_path_is_absolute (text)) - { - location_popup_handler (impl, text); - return; - } + file = g_file_new_for_uri (text); - path = gtk_file_system_filename_to_path (impl->file_system, text); - if (!path) - { - location_popup_handler (impl, text); - return; - } - } - - if (!gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (impl), path, NULL)) + if (!gtk_file_chooser_default_select_file (GTK_FILE_CHOOSER (impl), file, NULL)) location_popup_handler (impl, text); - gtk_file_path_free (path); + g_object_unref (file); } /* Handler for the "location-popup-on-paste" keybinding signal */ @@ -8582,7 +8364,7 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed) } else if ((impl->location_entry != NULL) && (current_focus == impl->location_entry)) { - GtkFilePath *path; + GFile *file; gboolean is_well_formed, is_empty, is_file_part_empty; gboolean is_folder; gboolean retval; @@ -8598,12 +8380,12 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed) && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)); entry = GTK_FILE_CHOOSER_ENTRY (impl->location_entry); - check_save_entry (impl, &path, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder); + check_save_entry (impl, &file, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder); if (is_empty || !is_well_formed) return FALSE; - g_assert (path != NULL); + g_assert (file != NULL); error = NULL; if (is_folder) @@ -8611,7 +8393,7 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed) if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) { - change_folder_and_display_error (impl, path, TRUE); + change_folder_and_display_error (impl, file, TRUE); retval = FALSE; } else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || @@ -8632,19 +8414,19 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed) { struct FileExistsData *data; - /* We need to check whether path exists and is not a folder */ + /* We need to check whether file exists and is not a folder */ data = g_new0 (struct FileExistsData, 1); data->impl = g_object_ref (impl); - data->path = gtk_file_path_copy (path); - data->parent_path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry)); + data->file = g_object_ref (file); + data->parent_file = g_object_ref (_gtk_file_chooser_entry_get_current_folder (entry)); - if (impl->file_exists_get_info_handle) - gtk_file_system_cancel_operation (impl->file_exists_get_info_handle); + if (impl->file_exists_get_info_cancellable) + g_cancellable_cancel (impl->file_exists_get_info_cancellable); - impl->file_exists_get_info_handle = - gtk_file_system_get_info (impl->file_system, path, - GTK_FILE_INFO_IS_FOLDER, + impl->file_exists_get_info_cancellable = + gtk_file_system_get_info (impl->file_system, file, + "standard::type", file_exists_get_info_cb, data); @@ -8655,7 +8437,7 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed) g_error_free (error); } - gtk_file_path_free (path); + g_object_unref (file); return retval; } else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view) @@ -8719,27 +8501,25 @@ gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed) gtk_widget_grab_focus (widget); } -/* Callback used from gtk_tree_selection_selected_foreach(); gets the selected GtkFilePaths */ +/* Callback used from gtk_tree_selection_selected_foreach(); gets the selected GFiles */ static void -search_selected_foreach_get_path_cb (GtkTreeModel *model, +search_selected_foreach_get_file_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { GSList **list; - const GtkFilePath *file_path; - GtkFilePath *file_path_copy; + GFile *file; list = data; - gtk_tree_model_get (model, iter, SEARCH_MODEL_COL_PATH, &file_path, -1); - file_path_copy = gtk_file_path_copy (file_path); - *list = g_slist_prepend (*list, file_path_copy); + gtk_tree_model_get (model, iter, SEARCH_MODEL_COL_FILE, &file, -1); + *list = g_slist_prepend (*list, file); } /* Constructs a list of the selected paths in search mode */ static GSList * -search_get_selected_paths (GtkFileChooserDefault *impl) +search_get_selected_files (GtkFileChooserDefault *impl) { GSList *result; GtkTreeSelection *selection; @@ -8747,7 +8527,7 @@ search_get_selected_paths (GtkFileChooserDefault *impl) result = NULL; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); - gtk_tree_selection_selected_foreach (selection, search_selected_foreach_get_path_cb, &result); + gtk_tree_selection_selected_foreach (selection, search_selected_foreach_get_file_cb, &result); result = g_slist_reverse (result); return result; @@ -8770,21 +8550,21 @@ search_should_respond (GtkFileChooserDefault *impl) struct SearchHitInsertRequest { GtkFileChooserDefault *impl; - GtkFilePath *path; + GFile *file; GtkTreeRowReference *row_ref; }; static void -search_hit_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer data) +search_hit_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GdkPixbuf *pixbuf = NULL; GtkTreePath *path; GtkTreeIter iter; - GtkFileSystemHandle *model_handle; + GCancellable *model_cancellable; gboolean is_folder = FALSE; char *mime_type; char *display_name; @@ -8802,14 +8582,14 @@ search_hit_get_info_cb (GtkFileSystemHandle *handle, gtk_tree_path_free (path); gtk_tree_model_get (GTK_TREE_MODEL (request->impl->search_model), &iter, - SEARCH_MODEL_COL_HANDLE, &model_handle, + SEARCH_MODEL_COL_CANCELLABLE, &model_cancellable, -1); - if (handle != model_handle) + if (cancellable != model_cancellable) goto out; - /* set the handle to NULL in the model */ + /* set the cancellable to NULL in the model */ gtk_list_store_set (request->impl->search_model, &iter, - SEARCH_MODEL_COL_HANDLE, NULL, + SEARCH_MODEL_COL_CANCELLABLE, NULL, -1); if (cancelled) @@ -8821,11 +8601,11 @@ search_hit_get_info_cb (GtkFileSystemHandle *handle, goto out; } - display_name = g_strdup (gtk_file_info_get_display_name (info)); - mime_type = g_strdup (gtk_file_info_get_mime_type (info)); - is_folder = gtk_file_info_get_is_folder (info); + display_name = g_strdup (g_file_info_get_display_name (info)); + mime_type = g_strdup (g_file_info_get_content_type (info)); + is_folder = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (request->impl), - request->impl->icon_size, NULL); + request->impl->icon_size); gtk_list_store_set (request->impl->search_model, &iter, SEARCH_MODEL_COL_PIXBUF, pixbuf, @@ -8839,11 +8619,11 @@ search_hit_get_info_cb (GtkFileSystemHandle *handle, out: g_object_unref (request->impl); - gtk_file_path_free (request->path); + g_object_unref (request->file); gtk_tree_row_reference_free (request->row_ref); g_free (request); - g_object_unref (handle); + g_object_unref (cancellable); } /* Adds one hit from the search engine to the search_model */ @@ -8851,7 +8631,7 @@ static void search_add_hit (GtkFileChooserDefault *impl, gchar *uri) { - GtkFilePath *path; + GFile *file; char *filename; char *tmp; char *collation_key; @@ -8859,23 +8639,22 @@ search_add_hit (GtkFileChooserDefault *impl, struct stat *statbuf_copy; GtkTreeIter iter; GtkTreePath *p; - GtkFileSystemHandle *handle; + GCancellable *cancellable; struct SearchHitInsertRequest *request; - path = gtk_file_system_uri_to_path (impl->file_system, uri); - if (!path) - return; + file = g_file_new_for_uri (uri); - filename = gtk_file_system_path_to_filename (impl->file_system, path); - if (!filename) + if (!g_file_is_native (file)) { - gtk_file_path_free (path); + g_object_unref (file); return; } + filename = g_file_get_path (file); + if (stat (filename, &statbuf) != 0) { - gtk_file_path_free (path); + g_object_unref (file); g_free (filename); return; } @@ -8883,13 +8662,13 @@ search_add_hit (GtkFileChooserDefault *impl, statbuf_copy = g_new (struct stat, 1); *statbuf_copy = statbuf; - tmp = g_filename_display_name (filename); + tmp = g_file_get_parse_name (file); collation_key = g_utf8_collate_key_for_filename (tmp, -1); g_free (tmp); request = g_new0 (struct SearchHitInsertRequest, 1); request->impl = g_object_ref (impl); - request->path = gtk_file_path_copy (path); + request->file = g_object_ref (file); gtk_list_store_append (impl->search_model, &iter); p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->search_model), &iter); @@ -8897,17 +8676,21 @@ search_add_hit (GtkFileChooserDefault *impl, request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->search_model), p); gtk_tree_path_free (p); - handle = gtk_file_system_get_info (impl->file_system, path, - GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_ICON | GTK_FILE_INFO_MIME_TYPE | GTK_FILE_INFO_DISPLAY_NAME, - search_hit_get_info_cb, - request); + cancellable = gtk_file_system_get_info (impl->file_system, file, + "standard::type,standard::icon," + "standard::content-type,standard::display-name", + search_hit_get_info_cb, + request); gtk_list_store_set (impl->search_model, &iter, - SEARCH_MODEL_COL_PATH, path, + SEARCH_MODEL_COL_FILE, file, SEARCH_MODEL_COL_COLLATION_KEY, collation_key, SEARCH_MODEL_COL_STAT, statbuf_copy, - SEARCH_MODEL_COL_HANDLE, handle, + SEARCH_MODEL_COL_CANCELLABLE, cancellable, -1); + + g_object_unref (file); + g_free (filename); } /* Callback used from GtkSearchEngine when we get new hits */ @@ -8990,27 +8773,14 @@ search_clear_model (GtkFileChooserDefault *impl, if (gtk_tree_model_get_iter_first (model, &iter)) do { - GtkFilePath *path; - gchar *display_name; - gchar *collation_key; - struct stat *statbuf; - GtkFileSystemHandle *handle; + GCancellable *cancellable; gtk_tree_model_get (model, &iter, - SEARCH_MODEL_COL_PATH, &path, - SEARCH_MODEL_COL_DISPLAY_NAME, &display_name, - SEARCH_MODEL_COL_COLLATION_KEY, &collation_key, - SEARCH_MODEL_COL_STAT, &statbuf, - SEARCH_MODEL_COL_HANDLE, &handle, + SEARCH_MODEL_COL_CANCELLABLE, &cancellable, -1); - - if (handle) - gtk_file_system_cancel_operation (handle); - gtk_file_path_free (path); - g_free (display_name); - g_free (collation_key); - g_free (statbuf); + if (cancellable) + g_cancellable_cancel (cancellable); } while (gtk_tree_model_iter_next (model, &iter)); @@ -9162,7 +8932,7 @@ search_column_mtime_sort_func (GtkTreeModel *model, static gboolean search_get_is_filtered (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, const gchar *display_name, const gchar *mime_type) { @@ -9181,7 +8951,7 @@ search_get_is_filtered (GtkFileChooserDefault *impl, if (needed & GTK_FILE_FILTER_FILENAME) { - filter_info.filename = gtk_file_system_path_to_filename (impl->file_system, path); + filter_info.filename = g_file_get_path (file); if (filter_info.filename) filter_info.contains |= GTK_FILE_FILTER_FILENAME; } @@ -9190,7 +8960,7 @@ search_get_is_filtered (GtkFileChooserDefault *impl, if (needed & GTK_FILE_FILTER_URI) { - filter_info.uri = gtk_file_system_path_to_uri (impl->file_system, path); + filter_info.uri = g_file_get_uri (file); if (filter_info.uri) filter_info.contains |= GTK_FILE_FILTER_URI; } @@ -9215,7 +8985,7 @@ search_model_visible_func (GtkTreeModel *model, gpointer user_data) { GtkFileChooserDefault *impl = user_data; - GtkFilePath *file_path; + GFile *file; gchar *display_name, *mime_type; gboolean is_folder; @@ -9223,7 +8993,7 @@ search_model_visible_func (GtkTreeModel *model, return TRUE; gtk_tree_model_get (model, iter, - SEARCH_MODEL_COL_PATH, &file_path, + SEARCH_MODEL_COL_FILE, &file, SEARCH_MODEL_COL_IS_FOLDER, &is_folder, SEARCH_MODEL_COL_DISPLAY_NAME, &display_name, SEARCH_MODEL_COL_MIME_TYPE, &mime_type, @@ -9235,7 +9005,7 @@ search_model_visible_func (GtkTreeModel *model, if (is_folder) return TRUE; - return !search_get_is_filtered (impl, file_path, display_name, mime_type); + return !search_get_is_filtered (impl, file, display_name, mime_type); } /* Creates the search_model and puts it in the tree view */ @@ -9248,14 +9018,14 @@ search_setup_model (GtkFileChooserDefault *impl) /* We store these columns in the search model: * - * SEARCH_MODEL_COL_PATH - a GtkFilePath for the hit's URI, stored as a - * pointer not as a GTK_TYPE_FILE_PATH + * SEARCH_MODEL_COL_FILE - a GFile for the hit's URI, stored + * as a pointer not as a G_TYPE_FILE * SEARCH_MODEL_COL_DISPLAY_NAME - a string with the display name, stored * as a pointer not as a G_TYPE_STRING * SEARCH_MODEL_COL_COLLATION_KEY - collation key for the filename, stored * as a pointer not as a G_TYPE_STRING * SEARCH_MODEL_COL_STAT - pointer to a struct stat - * SEARCH_MODEL_COL_HANDLE - handle used when getting the hit's info + * SEARCH_MODEL_COL_CANCELLABLE - cancellable used when getting the hit's info * SEARCH_MODEL_COL_PIXBUF - GdkPixbuf for the hit's icon * SEARCH_MODEL_COL_MIME_TYPE - a string with the hit's MIME type * SEARCH_MODEL_COL_IS_FOLDER - a boolean flag for folders @@ -9282,7 +9052,7 @@ search_setup_model (GtkFileChooserDefault *impl) impl->search_model_sort = GTK_TREE_MODEL_SORT (search_model_sort_new (impl, GTK_TREE_MODEL (impl->search_model_filter))); gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->search_model_sort), - SEARCH_MODEL_COL_PATH, + SEARCH_MODEL_COL_FILE, search_column_path_sort_func, impl, NULL); gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->search_model_sort), @@ -9515,22 +9285,22 @@ recent_clear_model (GtkFileChooserDefault *impl, { do { - GtkFilePath *file_path; - GtkFileSystemHandle *handle; + GFile *file; + GCancellable *cancellable; GtkRecentInfo *recent_info; gchar *display_name; gtk_tree_model_get (model, &iter, RECENT_MODEL_COL_DISPLAY_NAME, &display_name, - RECENT_MODEL_COL_PATH, &file_path, - RECENT_MODEL_COL_HANDLE, &handle, + RECENT_MODEL_COL_FILE, &file, + RECENT_MODEL_COL_CANCELLABLE, &cancellable, RECENT_MODEL_COL_INFO, &recent_info, -1); - - if (handle) - gtk_file_system_cancel_operation (handle); - gtk_file_path_free (file_path); + if (cancellable) + g_cancellable_cancel (cancellable); + + g_object_unref (file); gtk_recent_info_unref (recent_info); g_free (display_name); } @@ -9667,7 +9437,7 @@ recent_column_path_sort_func (GtkTreeModel *model, static gboolean recent_get_is_filtered (GtkFileChooserDefault *impl, - const GtkFilePath *path, + GFile *file, GtkRecentInfo *recent_info) { GtkFileFilterInfo filter_info; @@ -9685,7 +9455,7 @@ recent_get_is_filtered (GtkFileChooserDefault *impl, if (needed & GTK_FILE_FILTER_FILENAME) { - filter_info.filename = gtk_file_system_path_to_filename (impl->file_system, path); + filter_info.filename = g_file_get_path (file); if (filter_info.filename) filter_info.contains |= GTK_FILE_FILTER_FILENAME; } @@ -9694,7 +9464,7 @@ recent_get_is_filtered (GtkFileChooserDefault *impl, if (needed & GTK_FILE_FILTER_URI) { - filter_info.uri = gtk_file_system_path_to_uri (impl->file_system, path); + filter_info.uri = g_file_get_uri (file); if (filter_info.uri) filter_info.contains |= GTK_FILE_FILTER_URI; } @@ -9718,7 +9488,7 @@ recent_model_visible_func (GtkTreeModel *model, gpointer user_data) { GtkFileChooserDefault *impl = user_data; - GtkFilePath *file_path; + GFile *file; GtkRecentInfo *recent_info; gboolean is_folder; @@ -9727,7 +9497,7 @@ recent_model_visible_func (GtkTreeModel *model, gtk_tree_model_get (model, iter, RECENT_MODEL_COL_INFO, &recent_info, - RECENT_MODEL_COL_PATH, &file_path, + RECENT_MODEL_COL_FILE, &file, RECENT_MODEL_COL_IS_FOLDER, &is_folder, -1); @@ -9737,7 +9507,7 @@ recent_model_visible_func (GtkTreeModel *model, if (is_folder) return TRUE; - return !recent_get_is_filtered (impl, file_path, recent_info); + return !recent_get_is_filtered (impl, file, recent_info); } static void @@ -9749,15 +9519,15 @@ recent_setup_model (GtkFileChooserDefault *impl) /* We store these columns in the search model: * - * RECENT_MODEL_COL_PATH - a pointer to GtkFilePath for the hit's URI, - * stored as a pointer and not as a GTK_TYPE_FILE_PATH; + * RECENT_MODEL_COL_FILE - a pointer to GFile for the hit's URI, + * stored as a pointer and not as a G_TYPE_FILE; * RECENT_MODEL_COL_DISPLAY_NAME - a string with the display name, * stored as a pointer and not as a G_TYPE_STRING; * RECENT_MODEL_COL_INFO - GtkRecentInfo, stored as a pointer and not * as a GTK_TYPE_RECENT_INFO; * RECENT_MODEL_COL_IS_FOLDER - boolean flag; - * RECENT_MODEL_COL_HANDLE - GtkFileSystemHandle, stored as a pointer - * and not as a GTK_TYPE_FILE_SYSTEM_HANDLE; + * RECENT_MODEL_COL_CANCELLABLE - GCancellable, stored as a pointer + * and not as a G_TYPE_CANCELLABLE; * * Keep this in sync with the enumeration defined near the beginning of * this file. @@ -9787,7 +9557,7 @@ recent_setup_model (GtkFileChooserDefault *impl) impl->recent_model_sort = GTK_TREE_MODEL_SORT (recent_model_sort_new (impl, GTK_TREE_MODEL (impl->recent_model_filter))); gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort), - RECENT_MODEL_COL_PATH, + RECENT_MODEL_COL_FILE, recent_column_path_sort_func, impl, NULL); gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort), @@ -9833,20 +9603,20 @@ recent_idle_cleanup (gpointer data) struct RecentItemInsertRequest { GtkFileChooserDefault *impl; - GtkFilePath *path; + GFile *file; GtkTreeRowReference *row_ref; }; static void -recent_item_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer data) +recent_item_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GtkTreePath *path; GtkTreeIter iter; - GtkFileSystemHandle *model_handle; + GCancellable *model_cancellable; gboolean is_folder = FALSE; struct RecentItemInsertRequest *request = data; @@ -9862,13 +9632,13 @@ recent_item_get_info_cb (GtkFileSystemHandle *handle, gtk_tree_path_free (path); gtk_tree_model_get (GTK_TREE_MODEL (request->impl->recent_model), &iter, - RECENT_MODEL_COL_HANDLE, &model_handle, + RECENT_MODEL_COL_CANCELLABLE, &model_cancellable, -1); - if (handle != model_handle) + if (cancellable != model_cancellable) goto out; gtk_list_store_set (request->impl->recent_model, &iter, - RECENT_MODEL_COL_HANDLE, NULL, + RECENT_MODEL_COL_CANCELLABLE, NULL, -1); if (cancelled) @@ -9880,7 +9650,7 @@ recent_item_get_info_cb (GtkFileSystemHandle *handle, goto out; } - is_folder = gtk_file_info_get_is_folder (info); + is_folder = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); gtk_list_store_set (request->impl->recent_model, &iter, RECENT_MODEL_COL_IS_FOLDER, is_folder, @@ -9888,11 +9658,11 @@ recent_item_get_info_cb (GtkFileSystemHandle *handle, out: g_object_unref (request->impl); - gtk_file_path_free (request->path); + g_object_unref (request->file); gtk_tree_row_reference_free (request->row_ref); g_free (request); - g_object_unref (handle); + g_object_unref (cancellable); } static gint @@ -9930,8 +9700,8 @@ recent_idle_load (gpointer data) GtkTreePath *p; GtkRecentInfo *info; const gchar *uri, *display_name; - GtkFilePath *path; - GtkFileSystemHandle *handle; + GFile *file; + GCancellable *cancellable; struct RecentItemInsertRequest *request; if (!impl->recent_manager) @@ -9987,33 +9757,29 @@ recent_idle_load (gpointer data) uri = gtk_recent_info_get_uri (info); display_name = gtk_recent_info_get_display_name (info); - path = gtk_file_system_uri_to_path (impl->file_system, uri); - if (!path) - goto load_next; + file = g_file_new_for_uri (uri); gtk_list_store_append (impl->recent_model, &iter); p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->recent_model), &iter); request = g_new0 (struct RecentItemInsertRequest, 1); request->impl = g_object_ref (impl); - request->path = gtk_file_path_copy (path); + request->file = g_object_ref (file); request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->recent_model), p); gtk_tree_path_free (p); - handle = gtk_file_system_get_info (impl->file_system, path, - GTK_FILE_INFO_IS_FOLDER, - recent_item_get_info_cb, - request); + cancellable = gtk_file_system_get_info (impl->file_system, file, + "standard::type", + recent_item_get_info_cb, + request); gtk_list_store_set (impl->recent_model, &iter, - RECENT_MODEL_COL_PATH, path, + RECENT_MODEL_COL_FILE, file, RECENT_MODEL_COL_DISPLAY_NAME, g_strdup (display_name), RECENT_MODEL_COL_INFO, gtk_recent_info_ref (info), - RECENT_MODEL_COL_HANDLE, handle, + RECENT_MODEL_COL_CANCELLABLE, cancellable, -1); -load_next: - load_data->n_loaded_items += 1; /* finished loading items */ @@ -10059,25 +9825,23 @@ recent_start_loading (GtkFileChooserDefault *impl) } static void -recent_selected_foreach_get_path_cb (GtkTreeModel *model, +recent_selected_foreach_get_file_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { GSList **list; - const GtkFilePath *file_path; - GtkFilePath *file_path_copy; + GFile *file; list = data; - gtk_tree_model_get (model, iter, RECENT_MODEL_COL_PATH, &file_path, -1); - file_path_copy = gtk_file_path_copy (file_path); - *list = g_slist_prepend (*list, file_path_copy); + gtk_tree_model_get (model, iter, RECENT_MODEL_COL_FILE, &file, -1); + *list = g_slist_prepend (*list, g_object_ref (file)); } /* Constructs a list of the selected paths in recent files mode */ static GSList * -recent_get_selected_paths (GtkFileChooserDefault *impl) +recent_get_selected_files (GtkFileChooserDefault *impl) { GSList *result; GtkTreeSelection *selection; @@ -10085,7 +9849,7 @@ recent_get_selected_paths (GtkFileChooserDefault *impl) result = NULL; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); - gtk_tree_selection_selected_foreach (selection, recent_selected_foreach_get_path_cb, &result); + gtk_tree_selection_selected_foreach (selection, recent_selected_foreach_get_file_cb, &result); result = g_slist_reverse (result); return result; @@ -10240,11 +10004,11 @@ static void check_preview_change (GtkFileChooserDefault *impl) { GtkTreePath *cursor_path; - const GtkFilePath *new_path; + GFile *new_file; const char *new_display_name; gtk_tree_view_get_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), &cursor_path, NULL); - new_path = NULL; + new_file = NULL; new_display_name = NULL; if (cursor_path) { @@ -10255,17 +10019,17 @@ check_preview_change (GtkFileChooserDefault *impl) if (impl->sort_model) { GtkTreeIter iter; - const GtkFileInfo *new_info; + GFileInfo *new_info; gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, cursor_path); gtk_tree_path_free (cursor_path); gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter); - new_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter); + new_file = _gtk_file_system_model_get_file (impl->browse_files_model, &child_iter); new_info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter); if (new_info) - new_display_name = gtk_file_info_get_display_name (new_info); + new_display_name = g_file_info_get_display_name (new_info); } } else if (impl->operation_mode == OPERATION_MODE_SEARCH) @@ -10278,7 +10042,7 @@ check_preview_change (GtkFileChooserDefault *impl) search_get_valid_child_iter (impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, - SEARCH_MODEL_COL_PATH, &new_path, + SEARCH_MODEL_COL_FILE, &new_file, SEARCH_MODEL_COL_DISPLAY_NAME, &new_display_name, -1); } @@ -10292,30 +10056,30 @@ check_preview_change (GtkFileChooserDefault *impl) recent_get_valid_child_iter (impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, - RECENT_MODEL_COL_PATH, &new_path, + RECENT_MODEL_COL_FILE, &new_file, RECENT_MODEL_COL_DISPLAY_NAME, &new_display_name, -1); } } - if (new_path != impl->preview_path && - !(new_path && impl->preview_path && - gtk_file_path_compare (new_path, impl->preview_path) == 0)) + if (new_file != impl->preview_file && + !(new_file && impl->preview_file && + g_file_equal (new_file, impl->preview_file))) { - if (impl->preview_path) + if (impl->preview_file) { - gtk_file_path_free (impl->preview_path); + g_object_unref (impl->preview_file); g_free (impl->preview_display_name); } - if (new_path) + if (new_file) { - impl->preview_path = gtk_file_path_copy (new_path); + impl->preview_file = g_object_ref (new_file); impl->preview_display_name = g_strdup (new_display_name); } else { - impl->preview_path = NULL; + impl->preview_file = NULL; impl->preview_display_name = NULL; } @@ -10327,19 +10091,19 @@ check_preview_change (GtkFileChooserDefault *impl) } static void -shortcuts_activate_volume_mount_cb (GtkFileSystemHandle *handle, +shortcuts_activate_volume_mount_cb (GCancellable *cancellable, GtkFileSystemVolume *volume, const GError *error, gpointer data) { - GtkFilePath *path; - gboolean cancelled = handle->cancelled; + GFile *file; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GtkFileChooserDefault *impl = data; - if (handle != impl->shortcuts_activate_iter_handle) + if (cancellable != impl->shortcuts_activate_iter_cancellable) goto out; - impl->shortcuts_activate_iter_handle = NULL; + impl->shortcuts_activate_iter_cancellable = NULL; set_busy_cursor (impl, FALSE); @@ -10350,28 +10114,30 @@ shortcuts_activate_volume_mount_cb (GtkFileSystemHandle *handle, { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED)) { - char *msg; + char *msg, *name; + + name = gtk_file_system_volume_get_display_name (volume); + msg = g_strdup_printf (_("Could not mount %s"), name); - msg = g_strdup_printf (_("Could not mount %s"), - gtk_file_system_volume_get_display_name (impl->file_system, volume)); error_message (impl, msg, error->message); + g_free (msg); + g_free (name); } goto out; } - path = gtk_file_system_volume_get_base_path (impl->file_system, volume); - if (path != NULL) + file = gtk_file_system_volume_get_root (volume); + if (file != NULL) { - change_folder_and_display_error (impl, path, FALSE); - - gtk_file_path_free (path); + change_folder_and_display_error (impl, file, FALSE); + g_object_unref (file); } out: g_object_unref (impl); - g_object_unref (handle); + g_object_unref (cancellable); } @@ -10382,7 +10148,7 @@ static void shortcuts_activate_volume (GtkFileChooserDefault *impl, GtkFileSystemVolume *volume) { - GtkFilePath *path; + GFile *file; switch (impl->operation_mode) { @@ -10401,22 +10167,22 @@ shortcuts_activate_volume (GtkFileChooserDefault *impl, */ g_object_ref (impl); - if (!gtk_file_system_volume_get_is_mounted (impl->file_system, volume)) + if (!gtk_file_system_volume_is_mounted (volume)) { set_busy_cursor (impl, TRUE); - impl->shortcuts_activate_iter_handle = - gtk_file_system_volume_mount (impl->file_system, volume, + impl->shortcuts_activate_iter_cancellable = + gtk_file_system_mount_volume (impl->file_system, volume, NULL, shortcuts_activate_volume_mount_cb, g_object_ref (impl)); } else { - path = gtk_file_system_volume_get_base_path (impl->file_system, volume); - if (path != NULL) + file = gtk_file_system_volume_get_root (volume); + if (file != NULL) { - change_folder_and_display_error (impl, path, FALSE); - gtk_file_path_free (path); + change_folder_and_display_error (impl, file, FALSE); + g_object_unref (file); } } @@ -10427,39 +10193,64 @@ shortcuts_activate_volume (GtkFileChooserDefault *impl, struct ShortcutsActivateData { GtkFileChooserDefault *impl; - GtkFilePath *path; + GFile *file; }; static void -shortcuts_activate_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +shortcuts_activate_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct ShortcutsActivateData *data = user_data; - if (handle != data->impl->shortcuts_activate_iter_handle) + if (cancellable != data->impl->shortcuts_activate_iter_cancellable) goto out; - data->impl->shortcuts_activate_iter_handle = NULL; + data->impl->shortcuts_activate_iter_cancellable = NULL; if (cancelled) goto out; - if (!error && gtk_file_info_get_is_folder (info)) - change_folder_and_display_error (data->impl, data->path, FALSE); + if (!error && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + change_folder_and_display_error (data->impl, data->file, FALSE); else - gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (data->impl), - data->path, + gtk_file_chooser_default_select_file (GTK_FILE_CHOOSER (data->impl), + data->file, NULL); out: g_object_unref (data->impl); - gtk_file_path_free (data->path); + g_object_unref (data->file); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); +} + +static void +shortcuts_activate_mount_enclosing_volume (GCancellable *cancellable, + GtkFileSystemVolume *volume, + const GError *error, + gpointer user_data) +{ + struct ShortcutsActivateData *data = user_data; + + if (error) + { + error_changing_folder_dialog (data->impl, data->file, g_error_copy (error)); + + g_object_unref (data->impl); + g_object_unref (data->file); + g_free (data); + + return; + } + + data->impl->shortcuts_activate_iter_cancellable = + gtk_file_system_get_info (data->impl->file_system, data->file, + "standard::type", + shortcuts_activate_get_info_cb, data); } static void @@ -10477,10 +10268,10 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl, SHORTCUTS_COL_TYPE, &shortcut_type, -1); - if (impl->shortcuts_activate_iter_handle) + if (impl->shortcuts_activate_iter_cancellable) { - gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle); - impl->shortcuts_activate_iter_handle = NULL; + g_cancellable_cancel (impl->shortcuts_activate_iter_cancellable); + impl->shortcuts_activate_iter_cancellable = NULL; } if (shortcut_type == SHORTCUT_TYPE_SEPARATOR) @@ -10493,18 +10284,39 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl, shortcuts_activate_volume (impl, volume); } - else if (shortcut_type == SHORTCUT_TYPE_PATH) + else if (shortcut_type == SHORTCUT_TYPE_FILE) { struct ShortcutsActivateData *data; + GtkFileSystemVolume *volume; + + volume = gtk_file_system_get_volume_for_file (impl->file_system, col_data); data = g_new0 (struct ShortcutsActivateData, 1); data->impl = g_object_ref (impl); - data->path = gtk_file_path_copy (col_data); + data->file = g_object_ref (col_data); + + if (!volume || !gtk_file_system_volume_is_mounted (volume)) + { + GMountOperation *mount_operation; + GtkWidget *toplevel; + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (impl)); - impl->shortcuts_activate_iter_handle = - gtk_file_system_get_info (impl->file_system, data->path, - GTK_FILE_INFO_IS_FOLDER, - shortcuts_activate_get_info_cb, data); + mount_operation = gtk_mount_operation_new (GTK_WINDOW (toplevel)); + + impl->shortcuts_activate_iter_cancellable = + gtk_file_system_mount_enclosing_volume (impl->file_system, col_data, + mount_operation, + shortcuts_activate_mount_enclosing_volume, + data); + } + else + { + impl->shortcuts_activate_iter_cancellable = + gtk_file_system_get_info (impl->file_system, data->file, + "standard::type", + shortcuts_activate_get_info_cb, data); + } } else if (shortcut_type == SHORTCUT_TYPE_SEARCH) { @@ -10614,14 +10426,14 @@ list_select_func (GtkTreeSelection *selection, case OPERATION_MODE_BROWSE: { - const GtkFileInfo *info; + GFileInfo *info; if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path)) return FALSE; gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter); info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter); - if (info && !gtk_file_info_get_is_folder (info)) + if (info && g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) return FALSE; } break; @@ -10639,7 +10451,7 @@ list_selection_changed (GtkTreeSelection *selection, if (impl->operation_mode == OPERATION_MODE_BROWSE && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) { - const GtkFileInfo *info; + GFileInfo *info; gboolean had_selection; info = get_selected_file_info_from_file_list (impl, &had_selection); @@ -10675,7 +10487,7 @@ list_row_activated (GtkTreeView *tree_view, { case OPERATION_MODE_SEARCH: { - GtkFilePath *file_path; + GFile *file; gboolean is_folder; if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort), &iter, path)) @@ -10683,13 +10495,13 @@ list_row_activated (GtkTreeView *tree_view, search_get_valid_child_iter (impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter, - SEARCH_MODEL_COL_PATH, &file_path, + SEARCH_MODEL_COL_FILE, &file, SEARCH_MODEL_COL_IS_FOLDER, &is_folder, -1); if (is_folder) { - change_folder_and_display_error (impl, file_path, FALSE); + change_folder_and_display_error (impl, file, FALSE); return; } @@ -10699,7 +10511,7 @@ list_row_activated (GtkTreeView *tree_view, case OPERATION_MODE_RECENT: { - GtkFilePath *file_path; + GFile *file; gboolean is_folder; if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, path)) @@ -10707,13 +10519,13 @@ list_row_activated (GtkTreeView *tree_view, recent_get_valid_child_iter (impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, - RECENT_MODEL_COL_PATH, &file_path, + RECENT_MODEL_COL_FILE, &file, RECENT_MODEL_COL_IS_FOLDER, &is_folder, -1); if (is_folder) { - change_folder_and_display_error (impl, file_path, FALSE); + change_folder_and_display_error (impl, file, FALSE); return; } @@ -10723,7 +10535,7 @@ list_row_activated (GtkTreeView *tree_view, case OPERATION_MODE_BROWSE: { - const GtkFileInfo *info; + GFileInfo *info; if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path)) return; @@ -10733,12 +10545,12 @@ list_row_activated (GtkTreeView *tree_view, info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter); - if (gtk_file_info_get_is_folder (info)) + if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { - const GtkFilePath *file_path; - - file_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter); - change_folder_and_display_error (impl, file_path, FALSE); + GFile *file; + + file = _gtk_file_system_model_get_file (impl->browse_files_model, &child_iter); + change_folder_and_display_error (impl, file, FALSE); return; } @@ -10752,15 +10564,15 @@ list_row_activated (GtkTreeView *tree_view, static void path_bar_clicked (GtkPathBar *path_bar, - GtkFilePath *file_path, - GtkFilePath *child_path, + GFile *file, + GFile *child_file, gboolean child_is_hidden, GtkFileChooserDefault *impl) { - if (child_path) - pending_select_paths_add (impl, child_path); + if (child_file) + pending_select_files_add (impl, child_file); - if (!change_folder_and_display_error (impl, file_path, FALSE)) + if (!change_folder_and_display_error (impl, file, FALSE)) return; /* Say we have "/foo/bar/[.baz]" and the user clicks on "bar". We should then @@ -10771,7 +10583,7 @@ path_bar_clicked (GtkPathBar *path_bar, g_object_set (impl, "show-hidden", TRUE, NULL); } -static const GtkFileInfo * +static GFileInfo * get_list_file_info (GtkFileChooserDefault *impl, GtkTreeIter *iter) { @@ -10839,22 +10651,21 @@ list_icon_data_func (GtkTreeViewColumn *tree_column, case OPERATION_MODE_BROWSE: { - const GtkFileInfo *info; - const GtkFilePath *path; + GFileInfo *info; + GFile *file; info = get_list_file_info (impl, iter); gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, iter); - path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter); - if (path) + file = _gtk_file_system_model_get_file (impl->browse_files_model, &child_iter); + if (file) { if (info) { /* FIXME: NULL GError */ - pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (impl), - impl->icon_size, NULL); + pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (impl), impl->icon_size); } } else @@ -10866,7 +10677,7 @@ list_icon_data_func (GtkTreeViewColumn *tree_column, if (info && (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)) - sensitive = gtk_file_info_get_is_folder (info); + sensitive = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); } break; } @@ -10890,7 +10701,7 @@ list_name_data_func (GtkTreeViewColumn *tree_column, gpointer data) { GtkFileChooserDefault *impl = data; - const GtkFileInfo *info; + GFileInfo *info; gboolean sensitive = TRUE; if (impl->operation_mode == OPERATION_MODE_SEARCH) @@ -10970,11 +10781,11 @@ list_name_data_func (GtkTreeViewColumn *tree_column, if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) { - sensitive = gtk_file_info_get_is_folder (info); - } - + sensitive = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); + } + g_object_set (cell, - "text", gtk_file_info_get_display_name (info), + "text", g_file_info_get_display_name (info), "sensitive", sensitive, "ellipsize", PANGO_ELLIPSIZE_END, NULL); @@ -10989,12 +10800,12 @@ list_size_data_func (GtkTreeViewColumn *tree_column, gpointer data) { GtkFileChooserDefault *impl = data; - const GtkFileInfo *info = get_list_file_info (impl, iter); + GFileInfo *info = get_list_file_info (impl, iter); gint64 size; gchar *str; gboolean sensitive = TRUE; - if (!info || gtk_file_info_get_is_folder (info)) + if (!info || g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { g_object_set (cell, "text", NULL, @@ -11038,6 +10849,7 @@ list_mtime_data_func (GtkTreeViewColumn *tree_column, gpointer data) { GtkFileChooserDefault *impl; + GTimeVal timeval = { 0, }; time_t time_mtime; gchar *date_str = NULL; gboolean sensitive = TRUE; @@ -11093,7 +10905,7 @@ list_mtime_data_func (GtkTreeViewColumn *tree_column, } else { - const GtkFileInfo *info; + GFileInfo *info; info = get_list_file_info (impl, iter); if (!info) @@ -11105,11 +10917,12 @@ list_mtime_data_func (GtkTreeViewColumn *tree_column, return; } - time_mtime = (time_t) gtk_file_info_get_modification_time (info); + g_file_info_get_modification_time (info, &timeval); + time_mtime = timeval.tv_sec; if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) - sensitive = gtk_file_info_get_is_folder (info); + sensitive = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); } if (G_UNLIKELY (time_mtime == 0)) @@ -11128,7 +10941,7 @@ list_mtime_data_func (GtkTreeViewColumn *tree_column, localtime_r ((time_t *) &time_mtime, &tm_mtime); #else { - struct tm *ptm = localtime ((time_t *) &time_mtime); + struct tm *ptm = localtime ((time_t *) &timeval.tv_sec); if (!ptm) { @@ -11517,7 +11330,7 @@ recent_model_sort_drag_data_get (GtkTreeDragSource *drag_source, { RecentModelSort *model; GtkTreeIter iter, child_iter; - GtkFilePath *file_path; + GFile *file; gchar *uris[2]; model = RECENT_MODEL_SORT (drag_source); @@ -11526,11 +11339,11 @@ recent_model_sort_drag_data_get (GtkTreeDragSource *drag_source, recent_get_valid_child_iter (model->impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (model->impl->recent_model), &child_iter, - RECENT_MODEL_COL_PATH, &file_path, + RECENT_MODEL_COL_FILE, &file, -1); - g_assert (file_path != NULL); + g_assert (file != NULL); - uris[0] = gtk_file_system_path_to_uri (model->impl->file_system, file_path); + uris[0] = g_file_get_uri (file); uris[1] = NULL; gtk_selection_data_set_uris (selection_data, uris); @@ -11602,7 +11415,7 @@ search_model_sort_drag_data_get (GtkTreeDragSource *drag_source, { SearchModelSort *model; GtkTreeIter iter, child_iter; - GtkFilePath *file_path; + GFile *file; gchar *uris[2]; model = SEARCH_MODEL_SORT (drag_source); @@ -11611,11 +11424,11 @@ search_model_sort_drag_data_get (GtkTreeDragSource *drag_source, search_get_valid_child_iter (model->impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (model->impl->search_model), &child_iter, - RECENT_MODEL_COL_PATH, &file_path, + RECENT_MODEL_COL_FILE, &file, -1); - g_assert (file_path != NULL); + g_assert (file != NULL); - uris[0] = gtk_file_system_path_to_uri (model->impl->file_system, file_path); + uris[0] = g_file_get_uri (file); uris[1] = NULL; gtk_selection_data_set_uris (selection_data, uris); diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c index a98041aab..ccee25098 100644 --- a/gtk/gtkfilechooserentry.c +++ b/gtk/gtkfilechooserentry.c @@ -57,14 +57,14 @@ struct _GtkFileChooserEntry GtkFileChooserAction action; GtkFileSystem *file_system; - GtkFilePath *base_folder; + GFile *base_folder; + GFile *current_folder_file; gchar *file_part; gint file_part_pos; /* Folder being loaded or already loaded */ - GtkFilePath *current_folder_path; - GtkFileFolder *current_folder; - GtkFileSystemHandle *load_folder_handle; + GtkFolder *current_folder; + GCancellable *load_folder_cancellable; LoadCompleteAction load_complete_action; @@ -84,7 +84,7 @@ struct _GtkFileChooserEntry enum { DISPLAY_NAME_COLUMN, - PATH_COLUMN, + FILE_COLUMN, N_COLUMNS }; @@ -134,8 +134,8 @@ static gboolean completion_match_func (GtkEntryCompletion *comp, const char *key, GtkTreeIter *iter, gpointer data); -static char *maybe_append_separator_to_path (GtkFileChooserEntry *chooser_entry, - GtkFilePath *path, +static char *maybe_append_separator_to_file (GtkFileChooserEntry *chooser_entry, + GFile *file, gchar *display_name); typedef enum { @@ -145,7 +145,7 @@ typedef enum { static void refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, RefreshMode refresh_mode); -static void finished_loading_cb (GtkFileFolder *folder, +static void finished_loading_cb (GFile *file, gpointer data); static void autocomplete (GtkFileChooserEntry *chooser_entry); static void install_start_autocompletion_idle (GtkFileChooserEntry *chooser_entry); @@ -230,8 +230,15 @@ gtk_file_chooser_entry_finalize (GObject *object) { GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (object); - gtk_file_path_free (chooser_entry->base_folder); - gtk_file_path_free (chooser_entry->current_folder_path); + if (chooser_entry->base_folder) + g_object_unref (chooser_entry->base_folder); + + if (chooser_entry->current_folder) + g_object_unref (chooser_entry->current_folder); + + if (chooser_entry->current_folder_file) + g_object_unref (chooser_entry->current_folder_file); + g_free (chooser_entry->file_part); G_OBJECT_CLASS (_gtk_file_chooser_entry_parent_class)->finalize (object); @@ -256,10 +263,10 @@ gtk_file_chooser_entry_dispose (GObject *object) chooser_entry->completion_store = NULL; } - if (chooser_entry->load_folder_handle) + if (chooser_entry->load_folder_cancellable) { - gtk_file_system_cancel_operation (chooser_entry->load_folder_handle); - chooser_entry->load_folder_handle = NULL; + g_cancellable_cancel (chooser_entry->load_folder_cancellable); + chooser_entry->load_folder_cancellable = NULL; } if (chooser_entry->current_folder) @@ -287,23 +294,23 @@ match_selected_callback (GtkEntryCompletion *completion, GtkFileChooserEntry *chooser_entry) { char *display_name; - GtkFilePath *path; + GFile *file; gint pos; gtk_tree_model_get (model, iter, DISPLAY_NAME_COLUMN, &display_name, - PATH_COLUMN, &path, + FILE_COLUMN, &file, -1); - if (!display_name || !path) + if (!display_name || !file) { /* these shouldn't complain if passed NULL */ - gtk_file_path_free (path); + g_object_unref (file); g_free (display_name); return FALSE; } - display_name = maybe_append_separator_to_path (chooser_entry, path, display_name); + display_name = maybe_append_separator_to_file (chooser_entry, file, display_name); pos = chooser_entry->file_part_pos; @@ -316,7 +323,7 @@ match_selected_callback (GtkEntryCompletion *completion, &pos); gtk_editable_set_position (GTK_EDITABLE (chooser_entry), -1); - gtk_file_path_free (path); + g_object_unref (file); g_free (display_name); return TRUE; @@ -411,36 +418,35 @@ beep (GtkFileChooserEntry *chooser_entry) /* This function will append a directory separator to paths to * display_name iff the path associated with it is a directory. - * maybe_append_separator_to_path will g_free the display_name and + * maybe_append_separator_to_file will g_free the display_name and * return a new one if needed. Otherwise, it will return the old one. * You should be safe calling * - * display_name = maybe_append_separator_to_path (entry, path, display_name); + * display_name = maybe_append_separator_to_file (entry, file, display_name); * ... * g_free (display_name); */ static char * -maybe_append_separator_to_path (GtkFileChooserEntry *chooser_entry, - GtkFilePath *path, +maybe_append_separator_to_file (GtkFileChooserEntry *chooser_entry, + GFile *file, gchar *display_name) { - if (!g_str_has_suffix (display_name, G_DIR_SEPARATOR_S) && path) + if (!g_str_has_suffix (display_name, G_DIR_SEPARATOR_S) && file) { - GtkFileInfo *info; - - info = gtk_file_folder_get_info (chooser_entry->current_folder, - path, NULL); /* NULL-GError */ + GFileInfo *info; + + info = gtk_folder_get_info (chooser_entry->current_folder, file); if (info) { - if (gtk_file_info_get_is_folder (info)) + if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { gchar *tmp = display_name; display_name = g_strconcat (tmp, G_DIR_SEPARATOR_S, NULL); g_free (tmp); } - - gtk_file_info_free (info); + + g_object_unref (info); } } @@ -466,7 +472,7 @@ trim_dir_separator_suffix (const char *str) static gboolean find_common_prefix (GtkFileChooserEntry *chooser_entry, gchar **common_prefix_ret, - GtkFilePath **unique_path_ret, + GFile **unique_file_ret, gboolean *is_complete_not_unique_ret, gboolean *prefix_expands_the_file_part_ret, GError **error) @@ -476,11 +482,11 @@ find_common_prefix (GtkFileChooserEntry *chooser_entry, gboolean parsed; gboolean valid; char *text_up_to_cursor; - GtkFilePath *parsed_folder_path; + GFile *parsed_folder_file; char *parsed_file_part; *common_prefix_ret = NULL; - *unique_path_ret = NULL; + *unique_file_ret = NULL; *is_complete_not_unique_ret = FALSE; *prefix_expands_the_file_part_ret = FALSE; @@ -491,7 +497,7 @@ find_common_prefix (GtkFileChooserEntry *chooser_entry, parsed = gtk_file_system_parse (chooser_entry->file_system, chooser_entry->base_folder, text_up_to_cursor, - &parsed_folder_path, + &parsed_folder_file, &parsed_file_part, error); @@ -500,11 +506,11 @@ find_common_prefix (GtkFileChooserEntry *chooser_entry, if (!parsed) return FALSE; - g_assert (parsed_folder_path != NULL - && chooser_entry->current_folder_path != NULL - && gtk_file_path_compare (parsed_folder_path, chooser_entry->current_folder_path) == 0); + g_assert (parsed_folder_file != NULL + && chooser_entry->current_folder != NULL + && g_file_equal (parsed_folder_file, chooser_entry->current_folder_file)); - gtk_file_path_free (parsed_folder_path); + g_object_unref (parsed_folder_file); /* First pass: find the common prefix */ @@ -513,12 +519,12 @@ find_common_prefix (GtkFileChooserEntry *chooser_entry, while (valid) { gchar *display_name; - GtkFilePath *path; + GFile *file; gtk_tree_model_get (GTK_TREE_MODEL (chooser_entry->completion_store), &iter, DISPLAY_NAME_COLUMN, &display_name, - PATH_COLUMN, &path, + FILE_COLUMN, &file, -1); if (g_str_has_prefix (display_name, parsed_file_part)) @@ -526,7 +532,7 @@ find_common_prefix (GtkFileChooserEntry *chooser_entry, if (!*common_prefix_ret) { *common_prefix_ret = trim_dir_separator_suffix (display_name); - *unique_path_ret = gtk_file_path_copy (path); + *unique_file_ret = g_object_ref (file); } else { @@ -541,13 +547,16 @@ find_common_prefix (GtkFileChooserEntry *chooser_entry, *p = '\0'; - gtk_file_path_free (*unique_path_ret); - *unique_path_ret = NULL; + if (*unique_file_ret) + { + g_object_unref (*unique_file_ret); + *unique_file_ret = NULL; + } } } g_free (display_name); - gtk_file_path_free (path); + g_object_unref (file); valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser_entry->completion_store), &iter); } @@ -629,7 +638,7 @@ append_common_prefix (GtkFileChooserEntry *chooser_entry, gboolean show_errors) { gchar *common_prefix; - GtkFilePath *unique_path; + GFile *unique_file; gboolean is_complete_not_unique; gboolean prefix_expands_the_file_part; GError *error; @@ -642,7 +651,7 @@ append_common_prefix (GtkFileChooserEntry *chooser_entry, return NO_MATCH; error = NULL; - if (!find_common_prefix (chooser_entry, &common_prefix, &unique_path, &is_complete_not_unique, &prefix_expands_the_file_part, &error)) + if (!find_common_prefix (chooser_entry, &common_prefix, &unique_file, &is_complete_not_unique, &prefix_expands_the_file_part, &error)) { if (show_errors) { @@ -657,14 +666,14 @@ append_common_prefix (GtkFileChooserEntry *chooser_entry, have_result = FALSE; - if (unique_path) + if (unique_file) { if (!char_after_cursor_is_directory_separator (chooser_entry)) - common_prefix = maybe_append_separator_to_path (chooser_entry, - unique_path, + common_prefix = maybe_append_separator_to_file (chooser_entry, + unique_file, common_prefix); - gtk_file_path_free (unique_path); + g_object_unref (unique_file); if (common_prefix) { @@ -1036,7 +1045,7 @@ explicitly_complete (GtkFileChooserEntry *chooser_entry) CommonPrefixResult result; g_assert (chooser_entry->current_folder != NULL); - g_assert (gtk_file_folder_is_finished_loading (chooser_entry->current_folder)); + g_assert (gtk_folder_is_finished_loading (chooser_entry->current_folder)); /* FIXME: see what Emacs does in case there is no common prefix, or there is more than one match: * @@ -1088,7 +1097,7 @@ start_explicit_completion (GtkFileChooserEntry *chooser_entry) { refresh_current_folder_and_file_part (chooser_entry, REFRESH_UP_TO_CURSOR_POSITION); - if (!chooser_entry->current_folder_path) + if (!chooser_entry->current_folder_file) { /* Here, no folder path means we couldn't parse what the user typed. */ @@ -1100,7 +1109,7 @@ start_explicit_completion (GtkFileChooserEntry *chooser_entry) } if (chooser_entry->current_folder - && gtk_file_folder_is_finished_loading (chooser_entry->current_folder)) + && gtk_folder_is_finished_loading (chooser_entry->current_folder)) { explicitly_complete (chooser_entry); } @@ -1201,47 +1210,46 @@ discard_completion_store (GtkFileChooserEntry *chooser_entry) static void populate_completion_store (GtkFileChooserEntry *chooser_entry) { - GSList *paths; + GSList *files; GSList *tmp_list; discard_completion_store (chooser_entry); - if (!gtk_file_folder_list_children (chooser_entry->current_folder, &paths, NULL)) /* NULL-GError */ - return; + files = gtk_folder_list_children (chooser_entry->current_folder); chooser_entry->completion_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, - GTK_TYPE_FILE_PATH); + G_TYPE_FILE); - for (tmp_list = paths; tmp_list; tmp_list = tmp_list->next) + for (tmp_list = files; tmp_list; tmp_list = tmp_list->next) { - GtkFileInfo *info; - GtkFilePath *path; + GFileInfo *info; + GFile *file; + + file = tmp_list->data; - path = tmp_list->data; + info = gtk_folder_get_info (chooser_entry->current_folder, file); - info = gtk_file_folder_get_info (chooser_entry->current_folder, - path, - NULL); /* NULL-GError */ if (info) { - gchar *display_name = g_strdup (gtk_file_info_get_display_name (info)); + gchar *display_name = g_strdup (g_file_info_get_display_name (info)); GtkTreeIter iter; - display_name = maybe_append_separator_to_path (chooser_entry, path, display_name); + display_name = maybe_append_separator_to_file (chooser_entry, file, display_name); gtk_list_store_append (chooser_entry->completion_store, &iter); gtk_list_store_set (chooser_entry->completion_store, &iter, DISPLAY_NAME_COLUMN, display_name, - PATH_COLUMN, path, + FILE_COLUMN, file, -1); - gtk_file_info_free (info); + g_object_unref (info); g_free (display_name); } } - gtk_file_paths_free (paths); + g_slist_foreach (files, (GFunc) g_object_unref, NULL); + g_slist_free (files); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (chooser_entry->completion_store), DISPLAY_NAME_COLUMN, GTK_SORT_ASCENDING); @@ -1287,8 +1295,8 @@ finish_folder_load (GtkFileChooserEntry *chooser_entry) /* Callback when the current folder finishes loading */ static void -finished_loading_cb (GtkFileFolder *folder, - gpointer data) +finished_loading_cb (GFile *file, + gpointer data) { GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (data); @@ -1297,18 +1305,18 @@ finished_loading_cb (GtkFileFolder *folder, /* Callback when the current folder's handle gets obtained (not necessarily loaded completely) */ static void -load_directory_get_folder_callback (GtkFileSystemHandle *handle, - GtkFileFolder *folder, - const GError *error, - gpointer data) +load_directory_get_folder_callback (GCancellable *cancellable, + GtkFolder *folder, + const GError *error, + gpointer data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GtkFileChooserEntry *chooser_entry = data; - if (handle != chooser_entry->load_folder_handle) + if (cancellable != chooser_entry->load_folder_cancellable) goto out; - chooser_entry->load_folder_handle = NULL; + chooser_entry->load_folder_cancellable = NULL; if (error) { @@ -1326,19 +1334,22 @@ load_directory_get_folder_callback (GtkFileSystemHandle *handle, pop_up_completion_feedback (chooser_entry, error->message); } - gtk_file_path_free (chooser_entry->current_folder_path); - chooser_entry->current_folder_path = NULL; + if (chooser_entry->current_folder) + { + g_object_unref (chooser_entry->current_folder); + chooser_entry->current_folder = NULL; + } } if (cancelled || error) goto out; g_assert (folder != NULL); - chooser_entry->current_folder = folder; + chooser_entry->current_folder = g_object_ref (folder); discard_completion_store (chooser_entry); - if (gtk_file_folder_is_finished_loading (chooser_entry->current_folder)) + if (gtk_folder_is_finished_loading (chooser_entry->current_folder)) finish_folder_load (chooser_entry); else g_signal_connect (chooser_entry->current_folder, "finished-loading", @@ -1346,37 +1357,37 @@ load_directory_get_folder_callback (GtkFileSystemHandle *handle, out: g_object_unref (chooser_entry); - g_object_unref (handle); + g_object_unref (cancellable); } static void start_loading_current_folder (GtkFileChooserEntry *chooser_entry) { - if (chooser_entry->current_folder_path == NULL || + if (chooser_entry->current_folder_file == NULL || chooser_entry->file_system == NULL) return; g_assert (chooser_entry->current_folder == NULL); - g_assert (chooser_entry->load_folder_handle == NULL); + g_assert (chooser_entry->load_folder_cancellable == NULL); - chooser_entry->load_folder_handle = + chooser_entry->load_folder_cancellable = gtk_file_system_get_folder (chooser_entry->file_system, - chooser_entry->current_folder_path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_FOLDER, + chooser_entry->current_folder_file, + "standard::name,standard::display-name,standard::type", load_directory_get_folder_callback, g_object_ref (chooser_entry)); } static void reload_current_folder (GtkFileChooserEntry *chooser_entry, - GtkFilePath *folder_path, + GFile *folder_file, gboolean force_reload) { gboolean reload = FALSE; - if (chooser_entry->current_folder_path) + if (chooser_entry->current_folder_file) { - if ((folder_path && gtk_file_path_compare (folder_path, chooser_entry->current_folder_path) != 0) + if ((folder_file && !g_file_equal (folder_file, chooser_entry->current_folder_file)) || force_reload) { reload = TRUE; @@ -1386,23 +1397,23 @@ reload_current_folder (GtkFileChooserEntry *chooser_entry, */ if (chooser_entry->current_folder) { - if (chooser_entry->load_folder_handle) + if (chooser_entry->load_folder_cancellable) { - gtk_file_system_cancel_operation (chooser_entry->load_folder_handle); - chooser_entry->load_folder_handle = NULL; + g_cancellable_cancel (chooser_entry->load_folder_cancellable); + chooser_entry->load_folder_cancellable = NULL; } g_object_unref (chooser_entry->current_folder); chooser_entry->current_folder = NULL; } - gtk_file_path_free (chooser_entry->current_folder_path); - chooser_entry->current_folder_path = gtk_file_path_copy (folder_path); + g_object_unref (chooser_entry->current_folder_file); + chooser_entry->current_folder_file = g_object_ref (folder_file); } } else { - chooser_entry->current_folder_path = gtk_file_path_copy (folder_path); + chooser_entry->current_folder_file = (folder_file) ? g_object_ref (folder_file) : NULL; reload = TRUE; } @@ -1417,7 +1428,7 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, GtkEditable *editable; gint end_pos; gchar *text; - GtkFilePath *folder_path; + GFile *folder_file; gchar *file_part; gsize total_len, file_part_len; gint file_part_pos; @@ -1445,9 +1456,9 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, !chooser_entry->base_folder || !gtk_file_system_parse (chooser_entry->file_system, chooser_entry->base_folder, text, - &folder_path, &file_part, NULL)) /* NULL-GError */ + &folder_file, &file_part, NULL)) /* NULL-GError */ { - folder_path = gtk_file_path_copy (chooser_entry->base_folder); + folder_file = (chooser_entry->base_folder) ? g_object_ref (chooser_entry->base_folder) : NULL; file_part = g_strdup (""); file_part_pos = -1; } @@ -1468,15 +1479,17 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, chooser_entry->file_part = file_part; chooser_entry->file_part_pos = file_part_pos; - reload_current_folder (chooser_entry, folder_path, file_part_pos == -1); - gtk_file_path_free (folder_path); + reload_current_folder (chooser_entry, folder_file, file_part_pos == -1); + + if (folder_file) + g_object_unref (folder_file); } static void autocomplete (GtkFileChooserEntry *chooser_entry) { g_assert (chooser_entry->current_folder != NULL); - g_assert (gtk_file_folder_is_finished_loading (chooser_entry->current_folder)); + g_assert (gtk_folder_is_finished_loading (chooser_entry->current_folder)); g_assert (gtk_editable_get_position (GTK_EDITABLE (chooser_entry)) == GTK_ENTRY (chooser_entry)->text_length); append_common_prefix (chooser_entry, TRUE, FALSE); @@ -1495,7 +1508,7 @@ start_autocompletion (GtkFileChooserEntry *chooser_entry) return; } - if (gtk_file_folder_is_finished_loading (chooser_entry->current_folder)) + if (gtk_folder_is_finished_loading (chooser_entry->current_folder)) autocomplete (chooser_entry); else chooser_entry->load_complete_action = LOAD_COMPLETE_AUTOCOMPLETE; @@ -1634,18 +1647,21 @@ _gtk_file_chooser_entry_set_file_system (GtkFileChooserEntry *chooser_entry, /** * _gtk_file_chooser_entry_set_base_folder: * @chooser_entry: a #GtkFileChooserEntry - * @path: path of a folder in the chooser entries current file system. + * @file: file for a folder in the chooser entries current file system. * * Sets the folder with respect to which completions occur. **/ void _gtk_file_chooser_entry_set_base_folder (GtkFileChooserEntry *chooser_entry, - const GtkFilePath *path) + GFile *file) { if (chooser_entry->base_folder) - gtk_file_path_free (chooser_entry->base_folder); + g_object_unref (chooser_entry->base_folder); + + chooser_entry->base_folder = file; - chooser_entry->base_folder = gtk_file_path_copy (path); + if (chooser_entry->base_folder) + g_object_ref (chooser_entry->base_folder); clear_completions (chooser_entry); _gtk_file_chooser_entry_select_filename (chooser_entry); @@ -1663,14 +1679,14 @@ _gtk_file_chooser_entry_set_base_folder (GtkFileChooserEntry *chooser_entry, * path that doesn't point to a folder in the file system, it will * be %NULL. * - * Return value: the path of current folder - this value is owned by the + * Return value: the file for the current folder - this value is owned by the * chooser entry and must not be modified or freed. **/ -const GtkFilePath * +GFile * _gtk_file_chooser_entry_get_current_folder (GtkFileChooserEntry *chooser_entry) { commit_completion_and_refresh (chooser_entry); - return chooser_entry->current_folder_path; + return chooser_entry->current_folder_file; } /** @@ -1679,7 +1695,7 @@ _gtk_file_chooser_entry_get_current_folder (GtkFileChooserEntry *chooser_entry) * * Gets the non-folder portion of whatever the user has entered * into the file selector. What is returned is a UTF-8 string, - * and if a filename path is needed, gtk_file_system_make_path() + * and if a filename path is needed, g_file_get_child_for_display_name() * must be used * * Return value: the entered filename - this value is owned by the @@ -1771,20 +1787,20 @@ _gtk_file_chooser_entry_get_action (GtkFileChooserEntry *chooser_entry) gboolean _gtk_file_chooser_entry_get_is_folder (GtkFileChooserEntry *chooser_entry, - const GtkFilePath *path) + GFile *file) { gboolean retval = FALSE; if (chooser_entry->current_folder) { - GtkFileInfo *file_info; + GFileInfo *file_info; + + file_info = gtk_folder_get_info (chooser_entry->current_folder, file); - file_info = gtk_file_folder_get_info (chooser_entry->current_folder, - path, NULL); if (file_info) { - retval = gtk_file_info_get_is_folder (file_info); - gtk_file_info_free (file_info); + retval = (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY); + g_object_unref (file_info); } } diff --git a/gtk/gtkfilechooserentry.h b/gtk/gtkfilechooserentry.h index 755e04321..c68d0e963 100644 --- a/gtk/gtkfilechooserentry.h +++ b/gtk/gtkfilechooserentry.h @@ -41,13 +41,13 @@ GtkFileChooserAction _gtk_file_chooser_entry_get_action (GtkFileChooserEnt void _gtk_file_chooser_entry_set_file_system (GtkFileChooserEntry *chooser_entry, GtkFileSystem *file_system); void _gtk_file_chooser_entry_set_base_folder (GtkFileChooserEntry *chooser_entry, - const GtkFilePath *path); + GFile *folder); void _gtk_file_chooser_entry_set_file_part (GtkFileChooserEntry *chooser_entry, const gchar *file_part); -const GtkFilePath *_gtk_file_chooser_entry_get_current_folder (GtkFileChooserEntry *chooser_entry); +GFile * _gtk_file_chooser_entry_get_current_folder (GtkFileChooserEntry *chooser_entry); const gchar * _gtk_file_chooser_entry_get_file_part (GtkFileChooserEntry *chooser_entry); gboolean _gtk_file_chooser_entry_get_is_folder (GtkFileChooserEntry *chooser_entry, - const GtkFilePath *path); + GFile *file); void _gtk_file_chooser_entry_select_filename (GtkFileChooserEntry *chooser_entry); G_END_DECLS diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h index 7a1522bd8..d5a19c275 100644 --- a/gtk/gtkfilechooserprivate.h +++ b/gtk/gtkfilechooserprivate.h @@ -47,20 +47,20 @@ struct _GtkFileChooserIface /* Methods */ gboolean (*set_current_folder) (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); - GtkFilePath * (*get_current_folder) (GtkFileChooser *chooser); + GFile * (*get_current_folder) (GtkFileChooser *chooser); void (*set_current_name) (GtkFileChooser *chooser, const gchar *name); - gboolean (*select_path) (GtkFileChooser *chooser, - const GtkFilePath *path, + gboolean (*select_file) (GtkFileChooser *chooser, + GFile *file, GError **error); - void (*unselect_path) (GtkFileChooser *chooser, - const GtkFilePath *path); + void (*unselect_file) (GtkFileChooser *chooser, + GFile *file); void (*select_all) (GtkFileChooser *chooser); void (*unselect_all) (GtkFileChooser *chooser); - GSList * (*get_paths) (GtkFileChooser *chooser); - GtkFilePath * (*get_preview_path) (GtkFileChooser *chooser); + GSList * (*get_files) (GtkFileChooser *chooser); + GFile * (*get_preview_file) (GtkFileChooser *chooser); GtkFileSystem *(*get_file_system) (GtkFileChooser *chooser); void (*add_filter) (GtkFileChooser *chooser, GtkFileFilter *filter); @@ -68,10 +68,10 @@ struct _GtkFileChooserIface GtkFileFilter *filter); GSList * (*list_filters) (GtkFileChooser *chooser); gboolean (*add_shortcut_folder) (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); gboolean (*remove_shortcut_folder) (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); GSList * (*list_shortcut_folders) (GtkFileChooser *chooser); @@ -85,22 +85,22 @@ struct _GtkFileChooserIface }; GtkFileSystem *_gtk_file_chooser_get_file_system (GtkFileChooser *chooser); -gboolean _gtk_file_chooser_set_current_folder_path (GtkFileChooser *chooser, - const GtkFilePath *path, +gboolean _gtk_file_chooser_set_current_folder_file (GtkFileChooser *chooser, + GFile *file, GError **error); -GtkFilePath * _gtk_file_chooser_get_current_folder_path (GtkFileChooser *chooser); -gboolean _gtk_file_chooser_select_path (GtkFileChooser *chooser, - const GtkFilePath *path, +GFile * _gtk_file_chooser_get_current_folder_file (GtkFileChooser *chooser); +gboolean _gtk_file_chooser_select_file (GtkFileChooser *chooser, + GFile *file, GError **error); -void _gtk_file_chooser_unselect_path (GtkFileChooser *chooser, - const GtkFilePath *path); -GSList * _gtk_file_chooser_get_paths (GtkFileChooser *chooser); -GtkFilePath * _gtk_file_chooser_get_preview_path (GtkFileChooser *chooser); +void _gtk_file_chooser_unselect_file (GtkFileChooser *chooser, + GFile *file); +GSList * _gtk_file_chooser_get_files (GtkFileChooser *chooser); +GFile * _gtk_file_chooser_get_preview_file (GtkFileChooser *chooser); gboolean _gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *folder, GError **error); gboolean _gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *folder, GError **error); /* GtkFileChooserDialog private */ @@ -232,15 +232,15 @@ struct _GtkFileChooserDefault /* Handles */ GSList *loading_shortcuts; - GSList *reload_icon_handles; - GtkFileSystemHandle *file_list_drag_data_received_handle; - GtkFileSystemHandle *update_current_folder_handle; - GtkFileSystemHandle *show_and_select_paths_handle; - GtkFileSystemHandle *should_respond_get_info_handle; - GtkFileSystemHandle *file_exists_get_info_handle; - GtkFileSystemHandle *update_from_entry_handle; - GtkFileSystemHandle *shortcuts_activate_iter_handle; - GSList *pending_handles; + GSList *reload_icon_cancellables; + GCancellable *file_list_drag_data_received_cancellable; + GCancellable *update_current_folder_cancellable; + GCancellable *show_and_select_files_cancellable; + GCancellable *should_respond_get_info_cancellable; + GCancellable *file_exists_get_info_cancellable; + GCancellable *update_from_entry_cancellable; + GCancellable *shortcuts_activate_iter_cancellable; + GSList *pending_cancellables; LoadState load_state; ReloadState reload_state; @@ -248,7 +248,7 @@ struct _GtkFileChooserDefault OperationMode operation_mode; - GSList *pending_select_paths; + GSList *pending_select_files; GtkFileFilter *current_filter; GSList *filters; @@ -262,9 +262,9 @@ struct _GtkFileChooserDefault gulong volumes_changed_id; gulong bookmarks_changed_id; - GtkFilePath *current_volume_path; - GtkFilePath *current_folder; - GtkFilePath *preview_path; + GFile *current_volume_file; + GFile *current_folder; + GFile *preview_file; char *preview_display_name; GtkTreeViewColumn *list_name_column; @@ -320,10 +320,10 @@ struct _GtkFileSystemModel GObject parent_instance; GtkFileSystem *file_system; - GtkFileInfoType types; + gchar *attributes; FileModelNode *roots; - GtkFileFolder *root_folder; - GtkFilePath *root_path; + GtkFolder *root_folder; + GFile *root_file; GtkFileSystemModelFilter filter_func; gpointer filter_data; @@ -333,8 +333,8 @@ struct _GtkFileSystemModel gushort max_depth; - GSList *pending_handles; - + GSList *pending_cancellables; + guint show_hidden : 1; guint show_folders : 1; guint show_files : 1; @@ -344,12 +344,12 @@ struct _GtkFileSystemModel struct _FileModelNode { - GtkFilePath *path; + GFile *file; FileModelNode *next; - GtkFileInfo *info; - GtkFileFolder *folder; - + GFileInfo *info; + GtkFolder *folder; + FileModelNode *children; FileModelNode *parent; GtkFileSystemModel *model; diff --git a/gtk/gtkfilechooserutils.c b/gtk/gtkfilechooserutils.c index a7220c196..115cab9aa 100644 --- a/gtk/gtkfilechooserutils.c +++ b/gtk/gtkfilechooserutils.c @@ -28,20 +28,20 @@ #include "gtkalias.h" static gboolean delegate_set_current_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); -static GtkFilePath * delegate_get_current_folder (GtkFileChooser *chooser); +static GFile * delegate_get_current_folder (GtkFileChooser *chooser); static void delegate_set_current_name (GtkFileChooser *chooser, const gchar *name); -static gboolean delegate_select_path (GtkFileChooser *chooser, - const GtkFilePath *path, +static gboolean delegate_select_file (GtkFileChooser *chooser, + GFile *file, GError **error); -static void delegate_unselect_path (GtkFileChooser *chooser, - const GtkFilePath *path); +static void delegate_unselect_file (GtkFileChooser *chooser, + GFile *file); static void delegate_select_all (GtkFileChooser *chooser); static void delegate_unselect_all (GtkFileChooser *chooser); -static GSList * delegate_get_paths (GtkFileChooser *chooser); -static GtkFilePath * delegate_get_preview_path (GtkFileChooser *chooser); +static GSList * delegate_get_files (GtkFileChooser *chooser); +static GFile * delegate_get_preview_file (GtkFileChooser *chooser); static GtkFileSystem *delegate_get_file_system (GtkFileChooser *chooser); static void delegate_add_filter (GtkFileChooser *chooser, GtkFileFilter *filter); @@ -49,10 +49,10 @@ static void delegate_remove_filter (GtkFileChooser *choose GtkFileFilter *filter); static GSList * delegate_list_filters (GtkFileChooser *chooser); static gboolean delegate_add_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); static gboolean delegate_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, + GFile *file, GError **error); static GSList * delegate_list_shortcut_folders (GtkFileChooser *chooser); static void delegate_notify (GObject *object, @@ -136,12 +136,12 @@ _gtk_file_chooser_delegate_iface_init (GtkFileChooserIface *iface) iface->set_current_folder = delegate_set_current_folder; iface->get_current_folder = delegate_get_current_folder; iface->set_current_name = delegate_set_current_name; - iface->select_path = delegate_select_path; - iface->unselect_path = delegate_unselect_path; + iface->select_file = delegate_select_file; + iface->unselect_file = delegate_unselect_file; iface->select_all = delegate_select_all; iface->unselect_all = delegate_unselect_all; - iface->get_paths = delegate_get_paths; - iface->get_preview_path = delegate_get_preview_path; + iface->get_files = delegate_get_files; + iface->get_preview_file = delegate_get_preview_file; iface->get_file_system = delegate_get_file_system; iface->add_filter = delegate_add_filter; iface->remove_filter = delegate_remove_filter; @@ -203,18 +203,18 @@ get_delegate (GtkFileChooser *receiver) } static gboolean -delegate_select_path (GtkFileChooser *chooser, - const GtkFilePath *path, +delegate_select_file (GtkFileChooser *chooser, + GFile *file, GError **error) { - return _gtk_file_chooser_select_path (get_delegate (chooser), path, error); + return _gtk_file_chooser_select_file (get_delegate (chooser), file, error); } static void -delegate_unselect_path (GtkFileChooser *chooser, - const GtkFilePath *path) +delegate_unselect_file (GtkFileChooser *chooser, + GFile *file) { - _gtk_file_chooser_unselect_path (get_delegate (chooser), path); + _gtk_file_chooser_unselect_file (get_delegate (chooser), file); } static void @@ -230,15 +230,15 @@ delegate_unselect_all (GtkFileChooser *chooser) } static GSList * -delegate_get_paths (GtkFileChooser *chooser) +delegate_get_files (GtkFileChooser *chooser) { - return _gtk_file_chooser_get_paths (get_delegate (chooser)); + return _gtk_file_chooser_get_files (get_delegate (chooser)); } -static GtkFilePath * -delegate_get_preview_path (GtkFileChooser *chooser) +static GFile * +delegate_get_preview_file (GtkFileChooser *chooser) { - return _gtk_file_chooser_get_preview_path (get_delegate (chooser)); + return _gtk_file_chooser_get_preview_file (get_delegate (chooser)); } static GtkFileSystem * @@ -268,19 +268,19 @@ delegate_list_filters (GtkFileChooser *chooser) } static gboolean -delegate_add_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +delegate_add_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { - return _gtk_file_chooser_add_shortcut_folder (get_delegate (chooser), path, error); + return _gtk_file_chooser_add_shortcut_folder (get_delegate (chooser), file, error); } static gboolean -delegate_remove_shortcut_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +delegate_remove_shortcut_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { - return _gtk_file_chooser_remove_shortcut_folder (get_delegate (chooser), path, error); + return _gtk_file_chooser_remove_shortcut_folder (get_delegate (chooser), file, error); } static GSList * @@ -290,17 +290,17 @@ delegate_list_shortcut_folders (GtkFileChooser *chooser) } static gboolean -delegate_set_current_folder (GtkFileChooser *chooser, - const GtkFilePath *path, - GError **error) +delegate_set_current_folder (GtkFileChooser *chooser, + GFile *file, + GError **error) { - return _gtk_file_chooser_set_current_folder_path (get_delegate (chooser), path, error); + return _gtk_file_chooser_set_current_folder_file (get_delegate (chooser), file, error); } -static GtkFilePath * +static GFile * delegate_get_current_folder (GtkFileChooser *chooser) { - return _gtk_file_chooser_get_current_folder_path (get_delegate (chooser)); + return _gtk_file_chooser_get_current_folder_file (get_delegate (chooser)); } static void diff --git a/gtk/gtkfilesystem.c b/gtk/gtkfilesystem.c index 2f7dff5c0..095b71229 100644 --- a/gtk/gtkfilesystem.c +++ b/gtk/gtkfilesystem.c @@ -1,48 +1,136 @@ /* GTK - The GIMP Toolkit - * gtkfilesystem.c: Abstract file system interfaces + * gtkfilesystem.c: Filesystem abstraction functions. * Copyright (C) 2003, Red Hat, Inc. + * Copyright (C) 2007-2008 Carlos Garnacho * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * 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 - * Lesser General Public License for more details. + * 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 Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Carlos Garnacho */ -#include -#include +#include +#include +#include + #include "gtkfilesystem.h" -#include "gtkicontheme.h" -#include "gtkmodules.h" -#include "gtkintl.h" -#include "gtkstock.h" -#include "gtkalias.h" +#include "gtkprivate.h" -#include +/* #define DEBUG_MODE */ +#ifdef DEBUG_MODE +#define DEBUG(x...) g_debug (x); +#else +#define DEBUG(x...) +#endif + +#define GTK_FILE_SYSTEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_FILE_SYSTEM, GtkFileSystemPrivate)) +#define GTK_FOLDER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_FOLDER, GtkFolderPrivate)) +#define FILES_PER_QUERY 100 + +/* The pointers we return for a GtkFileSystemVolume are opaque tokens; they are + * really pointers to GDrive, GVolume or GMount objects. We need an extra + * token for the fake "File System" volume. So, we'll return a pointer to + * this particular string. + */ +static const gchar *root_volume_token = N_("File System"); +#define IS_ROOT_VOLUME(volume) ((gpointer) (volume) == (gpointer) root_volume_token) + +enum { + PROP_0, + PROP_FILE, + PROP_ENUMERATOR, + PROP_ATTRIBUTES +}; + +enum { + BOOKMARKS_CHANGED, + VOLUMES_CHANGED, + FS_LAST_SIGNAL +}; + +enum { + FILES_ADDED, + FILES_REMOVED, + FILES_CHANGED, + FINISHED_LOADING, + DELETED, + FOLDER_LAST_SIGNAL +}; + +static guint fs_signals [FS_LAST_SIGNAL] = { 0, }; +static guint folder_signals [FOLDER_LAST_SIGNAL] = { 0, }; + +typedef struct GtkFileSystemPrivate GtkFileSystemPrivate; +typedef struct GtkFolderPrivate GtkFolderPrivate; +typedef struct AsyncFuncData AsyncFuncData; + +struct GtkFileSystemPrivate +{ + GVolumeMonitor *volume_monitor; + + /* This list contains elements that can be + * of type GDrive, GVolume and GMount + */ + GSList *volumes; + + /* This list contains GtkFileSystemBookmark structs */ + GSList *bookmarks; + + GFileMonitor *bookmarks_monitor; +}; + +struct GtkFolderPrivate +{ + GFile *folder_file; + GHashTable *children; + GFileMonitor *directory_monitor; + GFileEnumerator *enumerator; + GCancellable *cancellable; + gchar *attributes; + + guint finished_loading : 1; +}; + +struct AsyncFuncData +{ + GtkFileSystem *file_system; + GFile *file; + GtkFolder *folder; + GCancellable *cancellable; + gchar *attributes; + + gpointer callback; + gpointer data; +}; -struct _GtkFileInfo +struct GtkFileSystemBookmark { - GtkFileTime modification_time; - gint64 size; - gchar *display_name; - gchar *display_key; - gchar *mime_type; - gchar *icon_name; - guint is_folder : 1; - guint is_hidden : 1; + GFile *file; + gchar *label; }; -static void gtk_file_system_base_init (gpointer g_class); -static void gtk_file_folder_base_init (gpointer g_class); +G_DEFINE_TYPE (GtkFileSystem, gtk_file_system, G_TYPE_OBJECT) + +G_DEFINE_TYPE (GtkFolder, gtk_folder, G_TYPE_OBJECT) + + +static void _gtk_folder_set_finished_loading (GtkFolder *folder, + gboolean finished_loading); +static void _gtk_folder_add_file (GtkFolder *folder, + GFile *file, + GFileInfo *info); + GQuark gtk_file_system_error_quark (void) @@ -50,1351 +138,1629 @@ gtk_file_system_error_quark (void) return g_quark_from_static_string ("gtk-file-system-error-quark"); } -/***************************************** - * GtkFileInfo * - *****************************************/ -GType -gtk_file_info_get_type (void) +/* GtkFileSystemBookmark methods */ +void +gtk_file_system_bookmark_free (GtkFileSystemBookmark *bookmark) { - static GType our_type = 0; - - if (our_type == 0) - our_type = g_boxed_type_register_static (I_("GtkFileInfo"), - (GBoxedCopyFunc) gtk_file_info_copy, - (GBoxedFreeFunc) gtk_file_info_free); - - return our_type; + g_object_unref (bookmark->file); + g_free (bookmark->label); + g_slice_free (GtkFileSystemBookmark, bookmark); } -GtkFileInfo * -gtk_file_info_new (void) +/* GtkFileSystem methods */ +static void +volumes_changed (GVolumeMonitor *volume_monitor, + gpointer volume, + gpointer user_data) { - GtkFileInfo *info; - - info = g_new0 (GtkFileInfo, 1); + GtkFileSystem *file_system; - return info; -} + gdk_threads_enter (); -GtkFileInfo * -gtk_file_info_copy (GtkFileInfo *info) -{ - GtkFileInfo *new_info; - - g_return_val_if_fail (info != NULL, NULL); - - new_info = g_memdup (info, sizeof (GtkFileInfo)); - if (new_info->display_name) - new_info->display_name = g_strdup (new_info->display_name); - if (new_info->display_key) - new_info->display_key = g_strdup (new_info->display_key); - if (new_info->mime_type) - new_info->mime_type = g_strdup (new_info->mime_type); - if (new_info->icon_name) - new_info->icon_name = g_strdup (new_info->icon_name); - if (new_info->display_key) - new_info->display_key = g_strdup (new_info->display_key); - - return new_info; + file_system = GTK_FILE_SYSTEM (user_data); + g_signal_emit (file_system, fs_signals[VOLUMES_CHANGED], 0, volume); + gdk_threads_leave (); } -void -gtk_file_info_free (GtkFileInfo *info) +static void +gtk_file_system_dispose (GObject *object) { - g_return_if_fail (info != NULL); + GtkFileSystemPrivate *priv; - g_free (info->display_name); - g_free (info->mime_type); - g_free (info->display_key); - g_free (info->icon_name); - - g_free (info); -} + DEBUG ("dispose"); -G_CONST_RETURN gchar * -gtk_file_info_get_display_name (const GtkFileInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - return info->display_name; -} + priv = GTK_FILE_SYSTEM_GET_PRIVATE (object); -/** - * gtk_file_info_get_display_key: - * @info: a #GtkFileInfo - * - * Returns for the collation key for the display name for @info. - * This is useful when sorting a bunch of #GtkFileInfo structures - * since the collate key will be only computed once. - * - * Return value: The collate key for the display name, or %NULL - * if the display name hasn't been set. - **/ -G_CONST_RETURN gchar * -gtk_file_info_get_display_key (const GtkFileInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); + if (priv->volumes) + { + g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL); + g_slist_free (priv->volumes); + priv->volumes = NULL; + } - if (!info->display_key && info->display_name) + if (priv->volume_monitor) { - /* Since info->display_key is only a cache, we cast off the const - */ - ((GtkFileInfo *)info)->display_key = g_utf8_collate_key_for_filename (info->display_name, -1); + g_signal_handlers_disconnect_by_func (priv->volume_monitor, volumes_changed, object); + g_object_unref (priv->volume_monitor); + priv->volume_monitor = NULL; } - - return info->display_key; + + G_OBJECT_CLASS (gtk_file_system_parent_class)->dispose (object); } -void -gtk_file_info_set_display_name (GtkFileInfo *info, - const gchar *display_name) +static void +gtk_file_system_finalize (GObject *object) { - g_return_if_fail (info != NULL); + GtkFileSystemPrivate *priv; - if (display_name == info->display_name) - return; + DEBUG ("finalize"); + + priv = GTK_FILE_SYSTEM_GET_PRIVATE (object); + + if (priv->bookmarks_monitor) + g_object_unref (priv->bookmarks_monitor); - g_free (info->display_name); - if (info->display_key) + if (priv->bookmarks) { - g_free (info->display_key); - info->display_key = NULL; + g_slist_foreach (priv->bookmarks, (GFunc) gtk_file_system_bookmark_free, NULL); + g_slist_free (priv->bookmarks); } - info->display_name = g_strdup (display_name); + G_OBJECT_CLASS (gtk_file_system_parent_class)->finalize (object); } -gboolean -gtk_file_info_get_is_folder (const GtkFileInfo *info) +static void +gtk_file_system_class_init (GtkFileSystemClass *class) { - g_return_val_if_fail (info != NULL, FALSE); - - return info->is_folder; -} + GObjectClass *object_class = G_OBJECT_CLASS (class); -void -gtk_file_info_set_is_folder (GtkFileInfo *info, - gboolean is_folder) -{ - g_return_if_fail (info != NULL); + object_class->dispose = gtk_file_system_dispose; + object_class->finalize = gtk_file_system_finalize; - info->is_folder = is_folder != FALSE; -} + fs_signals[BOOKMARKS_CHANGED] = + g_signal_new ("bookmarks-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkFileSystemClass, bookmarks_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); -gboolean -gtk_file_info_get_is_hidden (const GtkFileInfo *info) -{ - g_return_val_if_fail (info != NULL, FALSE); - - return info->is_hidden; + fs_signals[VOLUMES_CHANGED] = + g_signal_new ("volumes-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkFileSystemClass, volumes_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_type_class_add_private (object_class, sizeof (GtkFileSystemPrivate)); } -void -gtk_file_info_set_is_hidden (GtkFileInfo *info, - gboolean is_hidden) +static GFile * +get_bookmarks_file (void) { - g_return_if_fail (info != NULL); + GFile *file; + gchar *filename; - info->is_hidden = is_hidden != FALSE; -} + filename = g_build_filename (g_get_home_dir (), ".gtk-bookmarks", NULL); + file = g_file_new_for_path (filename); + g_free (filename); -G_CONST_RETURN gchar * -gtk_file_info_get_mime_type (const GtkFileInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - return info->mime_type; + return file; } -void -gtk_file_info_set_mime_type (GtkFileInfo *info, - const gchar *mime_type) +static GSList * +read_bookmarks (GFile *file) { - g_return_if_fail (info != NULL); - - g_free (info->mime_type); + gchar *contents; + gchar **lines, *space; + GSList *bookmarks = NULL; + gint i; - info->mime_type = g_strdup (mime_type); -} + if (!g_file_load_contents (file, NULL, &contents, + NULL, NULL, NULL)) + return NULL; -GtkFileTime -gtk_file_info_get_modification_time (const GtkFileInfo *info) -{ - g_return_val_if_fail (info != NULL, 0); + lines = g_strsplit (contents, "\n", -1); - return info->modification_time; -} + for (i = 0; lines[i]; i++) + { + GtkFileSystemBookmark *bookmark; -void -gtk_file_info_set_modification_time (GtkFileInfo *info, - GtkFileTime modification_time) -{ - g_return_if_fail (info != NULL); - - info->modification_time = modification_time; -} + if (!*lines[i]) + continue; -gint64 -gtk_file_info_get_size (const GtkFileInfo *info) -{ - g_return_val_if_fail (info != NULL, 0); - - return info->size; -} + bookmark = g_slice_new0 (GtkFileSystemBookmark); -void -gtk_file_info_set_size (GtkFileInfo *info, - gint64 size) -{ - g_return_if_fail (info != NULL); - g_return_if_fail (size >= 0); - - info->size = size; + if ((space = strchr (lines[i], ' ')) != NULL) + { + space[0] = '\0'; + bookmark->label = g_strdup (space + 1); + } + + bookmark->file = g_file_new_for_uri (lines[i]); + bookmarks = g_slist_prepend (bookmarks, bookmark); + } + + bookmarks = g_slist_reverse (bookmarks); + g_strfreev (lines); + g_free (contents); + + return bookmarks; } -void -gtk_file_info_set_icon_name (GtkFileInfo *info, - const gchar *icon_name) +static void +save_bookmarks (GFile *bookmarks_file, + GSList *bookmarks) { - g_return_if_fail (info != NULL); - - g_free (info->icon_name); + GError *error = NULL; + GString *contents; + + contents = g_string_new (""); + + while (bookmarks) + { + GtkFileSystemBookmark *bookmark; + gchar *uri; + + bookmark = bookmarks->data; + uri = g_file_get_uri (bookmark->file); + g_string_append (contents, uri); - info->icon_name = g_strdup (icon_name); + if (bookmark->label) + g_string_append_printf (contents, " %s", bookmark->label); + + g_string_append_c (contents, '\n'); + bookmarks = bookmarks->next; + g_free (uri); + } + + if (!g_file_replace_contents (bookmarks_file, + contents->str, + strlen (contents->str), + NULL, FALSE, 0, NULL, + NULL, &error)) + { + g_critical (error->message); + g_error_free (error); + } + + g_string_free (contents, TRUE); } -G_CONST_RETURN gchar * -gtk_file_info_get_icon_name (const GtkFileInfo *info) +static void +bookmarks_file_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event, + gpointer data) { - g_return_val_if_fail (info != NULL, NULL); - - return info->icon_name; + GtkFileSystemPrivate *priv; + + priv = GTK_FILE_SYSTEM_GET_PRIVATE (data); + + switch (event) + { + case G_FILE_MONITOR_EVENT_CHANGED: + case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: + case G_FILE_MONITOR_EVENT_CREATED: + case G_FILE_MONITOR_EVENT_DELETED: + g_slist_foreach (priv->bookmarks, (GFunc) gtk_file_system_bookmark_free, NULL); + g_slist_free (priv->bookmarks); + + priv->bookmarks = read_bookmarks (file); + + gdk_threads_enter (); + g_signal_emit (data, fs_signals[BOOKMARKS_CHANGED], 0); + gdk_threads_leave (); + break; + default: + /* ignore at the moment */ + break; + } } -GdkPixbuf * -gtk_file_info_render_icon (const GtkFileInfo *info, - GtkWidget *widget, - gint pixel_size, - GError **error) +static void +get_volumes_list (GtkFileSystem *file_system) { - GdkPixbuf *pixbuf = NULL; + GtkFileSystemPrivate *priv; + GList *l, *ll; + GList *drives; + GList *volumes; + GList *mounts; + GDrive *drive; + GVolume *volume; + GMount *mount; - g_return_val_if_fail (info != NULL, NULL); - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system); - if (info->icon_name) + if (priv->volumes) { - if (g_path_is_absolute (info->icon_name)) - pixbuf = gdk_pixbuf_new_from_file_at_size (info->icon_name, - pixel_size, - pixel_size, - NULL); - else - { - GtkIconTheme *icon_theme; + g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL); + g_slist_free (priv->volumes); + priv->volumes = NULL; + } + + /* first go through all connected drives */ + drives = g_volume_monitor_get_connected_drives (priv->volume_monitor); + + for (l = drives; l != NULL; l = l->next) + { + drive = l->data; + volumes = g_drive_get_volumes (drive); - icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget)); - if (gtk_icon_theme_has_icon (icon_theme, info->icon_name)) - pixbuf = gtk_icon_theme_load_icon (icon_theme, info->icon_name, - pixel_size, 0, NULL); + if (volumes) + { + for (ll = volumes; ll != NULL; ll = ll->next) + { + volume = ll->data; + mount = g_volume_get_mount (volume); + + if (mount) + { + /* Show mounted volume */ + priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount)); + g_object_unref (mount); + } + else + { + /* Do show the unmounted volumes in the sidebar; + * this is so the user can mount it (in case automounting + * is off). + * + * Also, even if automounting is enabled, this gives a visual + * cue that the user should remember to yank out the media if + * he just unmounted it. + */ + priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume)); + } + + g_object_unref (volume); + } + } + else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive)) + { + /* If the drive has no mountable volumes and we cannot detect media change.. we + * display the drive in the sidebar so the user can manually poll the drive by + * right clicking and selecting "Rescan..." + * + * This is mainly for drives like floppies where media detection doesn't + * work.. but it's also for human beings who like to turn off media detection + * in the OS to save battery juice. + */ + + priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (drive)); } } - if (!pixbuf) + g_list_free (drives); + + /* add all volumes that is not associated with a drive */ + volumes = g_volume_monitor_get_volumes (priv->volume_monitor); + + for (l = volumes; l != NULL; l = l->next) { - /* load a fallback icon */ - pixbuf = gtk_widget_render_icon (widget, - gtk_file_info_get_is_folder (info) - ? GTK_STOCK_DIRECTORY : GTK_STOCK_FILE, - GTK_ICON_SIZE_MENU, - NULL); - if (!pixbuf && error) - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_FAILED, - _("Could not get a stock icon for %s\n"), - info->icon_name); + volume = l->data; + drive = g_volume_get_drive (volume); + + if (drive) + { + g_object_unref (drive); + continue; + } + + mount = g_volume_get_mount (volume); + + if (mount) + { + /* show this mount */ + priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount)); + g_object_unref (mount); + } + else + { + /* see comment above in why we add an icon for a volume */ + priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume)); + } } - return pixbuf; -} + g_list_free (volumes); -/***************************************** - * GtkFileSystemHandle * - *****************************************/ + /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */ + mounts = g_volume_monitor_get_mounts (priv->volume_monitor); -enum -{ - PROP_0, - PROP_CANCELLED -}; + for (l = mounts; l != NULL; l = l->next) + { + mount = l->data; + volume = g_mount_get_volume (mount); + + if (volume) + { + g_object_unref (volume); + continue; + } + + /* show this mount */ + priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount)); + } -G_DEFINE_TYPE (GtkFileSystemHandle, gtk_file_system_handle, G_TYPE_OBJECT) + g_list_free (mounts); +} static void -gtk_file_system_handle_init (GtkFileSystemHandle *handle) +gtk_file_system_init (GtkFileSystem *file_system) +{ + GtkFileSystemPrivate *priv; + GFile *bookmarks_file; + GError *error = NULL; + + DEBUG ("init"); + + priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system); + + /* Volumes */ + priv->volume_monitor = g_volume_monitor_get (); + + g_signal_connect (priv->volume_monitor, "mount-added", + G_CALLBACK (volumes_changed), file_system); + g_signal_connect (priv->volume_monitor, "mount-removed", + G_CALLBACK (volumes_changed), file_system); + g_signal_connect (priv->volume_monitor, "mount-changed", + G_CALLBACK (volumes_changed), file_system); + g_signal_connect (priv->volume_monitor, "volume-added", + G_CALLBACK (volumes_changed), file_system); + g_signal_connect (priv->volume_monitor, "volume-removed", + G_CALLBACK (volumes_changed), file_system); + g_signal_connect (priv->volume_monitor, "volume-changed", + G_CALLBACK (volumes_changed), file_system); + g_signal_connect (priv->volume_monitor, "drive-connected", + G_CALLBACK (volumes_changed), file_system); + g_signal_connect (priv->volume_monitor, "drive-disconnected", + G_CALLBACK (volumes_changed), file_system); + g_signal_connect (priv->volume_monitor, "drive-changed", + G_CALLBACK (volumes_changed), file_system); + + /* Bookmarks */ + bookmarks_file = get_bookmarks_file (); + priv->bookmarks = read_bookmarks (bookmarks_file); + priv->bookmarks_monitor = g_file_monitor_file (bookmarks_file, + G_FILE_MONITOR_NONE, + NULL, &error); + if (error) + g_warning (error->message); + else + g_signal_connect (priv->bookmarks_monitor, "changed", + G_CALLBACK (bookmarks_file_changed), file_system); + + g_object_unref (bookmarks_file); +} + +/* GtkFileSystem public methods */ +GtkFileSystem * +gtk_file_system_new (void) { - handle->file_system = NULL; - handle->cancelled = FALSE; + return g_object_new (GTK_TYPE_FILE_SYSTEM, NULL); } -static void -gtk_file_system_handle_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +GSList * +gtk_file_system_list_volumes (GtkFileSystem *file_system) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + GtkFileSystemPrivate *priv; + GSList *list; + + DEBUG ("list_volumes"); + + g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); + + priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system); + get_volumes_list (GTK_FILE_SYSTEM (file_system)); + + list = g_slist_copy (priv->volumes); + + /* Prepend root volume */ + list = g_slist_prepend (list, (gpointer) root_volume_token); + + return list; } -static void -gtk_file_system_handle_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +GSList * +gtk_file_system_list_bookmarks (GtkFileSystem *file_system) { - GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (object); + GtkFileSystemPrivate *priv; + GSList *bookmarks, *files = NULL; - switch (prop_id) + DEBUG ("list_bookmarks"); + + priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system); + bookmarks = priv->bookmarks; + + while (bookmarks) { - case PROP_CANCELLED: - g_value_set_boolean (value, handle->cancelled); - break; + GtkFileSystemBookmark *bookmark; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + bookmark = bookmarks->data; + bookmarks = bookmarks->next; + + files = g_slist_prepend (files, g_object_ref (bookmark->file)); } -} -static void -gtk_file_system_handle_class_init (GtkFileSystemHandleClass *klass) -{ - GObjectClass *o_class; - - o_class = (GObjectClass *)klass; - o_class->set_property = gtk_file_system_handle_set_property; - o_class->get_property = gtk_file_system_handle_get_property; - - g_object_class_install_property (o_class, - PROP_CANCELLED, - g_param_spec_boolean ("cancelled", - P_("Cancelled"), - P_("Whether or not the operation has been successfully cancelled"), - FALSE, - G_PARAM_READABLE)); + return g_slist_reverse (files); } -/***************************************** - * GtkFileSystem * - *****************************************/ -GType -gtk_file_system_get_type (void) +gboolean +gtk_file_system_parse (GtkFileSystem *file_system, + GFile *base_file, + const gchar *str, + GFile **folder, + gchar **file_part, + GError **error) { - static GType file_system_type = 0; + GFile *file; + gboolean result = FALSE; + gboolean is_dir = FALSE; + gchar *last_slash = NULL; + + DEBUG ("parse"); + + if (str && *str) + is_dir = (str [strlen (str) - 1] == G_DIR_SEPARATOR); + + last_slash = strrchr (str, G_DIR_SEPARATOR); - if (!file_system_type) + if (str[0] == '~') + file = g_file_parse_name (str); + else + file = g_file_resolve_relative_path (base_file, str); + + if (g_file_equal (base_file, file)) { - const GTypeInfo file_system_info = - { - sizeof (GtkFileSystemIface), /* class_size */ - gtk_file_system_base_init, /* base_init */ - NULL, /* base_finalize */ - }; - - file_system_type = g_type_register_static (G_TYPE_INTERFACE, - I_("GtkFileSystem"), - &file_system_info, 0); - - g_type_interface_add_prerequisite (file_system_type, G_TYPE_OBJECT); + /* this is when user types '.', could be the + * beginning of a hidden file, ./ or ../ + */ + *folder = g_object_ref (file); + *file_part = g_strdup (str); + result = TRUE; } + else if (is_dir) + { + /* it's a dir, or at least it ends with the dir separator */ + *folder = g_object_ref (file); + *file_part = g_strdup (""); + result = TRUE; + } + else + { + GFile *parent_file; + + parent_file = g_file_get_parent (file); - return file_system_type; + if (!parent_file) + { + g_set_error (error, + GTK_FILE_SYSTEM_ERROR, + GTK_FILE_SYSTEM_ERROR_NONEXISTENT, + "Could not get parent file"); + *folder = NULL; + *file_part = NULL; + } + else + { + *folder = parent_file; + result = TRUE; + + if (last_slash) + *file_part = g_strdup (last_slash + 1); + else + *file_part = g_strdup (str); + } + } + + g_object_unref (file); + + return result; } static void -gtk_file_system_base_init (gpointer g_class) +free_async_data (AsyncFuncData *async_data) { - static gboolean initialized = FALSE; - - if (!initialized) - { - GType iface_type = G_TYPE_FROM_INTERFACE (g_class); - - g_signal_new (I_("volumes-changed"), - iface_type, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkFileSystemIface, volumes_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - g_signal_new (I_("bookmarks-changed"), - iface_type, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkFileSystemIface, bookmarks_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - initialized = TRUE; - } + g_object_unref (async_data->file_system); + g_object_unref (async_data->file); + g_object_unref (async_data->cancellable); + + if (async_data->folder) + g_object_unref (async_data->folder); + + g_free (async_data->attributes); + g_free (async_data); } -GSList * -gtk_file_system_list_volumes (GtkFileSystem *file_system) +static void +enumerate_children_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); + GFileEnumerator *enumerator; + AsyncFuncData *async_data; + GtkFolder *folder = NULL; + GFile *file; + GError *error = NULL; + + file = G_FILE (source_object); + async_data = (AsyncFuncData *) user_data; + enumerator = g_file_enumerate_children_finish (file, result, &error); + + if (enumerator) + { + folder = g_object_new (GTK_TYPE_FOLDER, + "file", source_object, + "enumerator", enumerator, + "attributes", async_data->attributes, + NULL); + g_object_unref (enumerator); + } + + gdk_threads_enter (); + ((GtkFileSystemGetFolderCallback) async_data->callback) (async_data->cancellable, + folder, error, async_data->data); + gdk_threads_leave (); + + free_async_data (async_data); - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_volumes (file_system); + if (error) + g_error_free (error); } -GtkFileSystemHandle * +GCancellable * gtk_file_system_get_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, + GFile *file, + const gchar *attributes, GtkFileSystemGetFolderCallback callback, gpointer data) { + GCancellable *cancellable; + AsyncFuncData *async_data; + g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (callback != NULL, NULL); + g_return_val_if_fail (G_IS_FILE (file), NULL); - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_folder (file_system, path, types, callback, data); -} + cancellable = g_cancellable_new (); -GtkFileSystemHandle * -gtk_file_system_get_info (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetInfoCallback callback, - gpointer data) -{ - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (callback != NULL, NULL); + async_data = g_new0 (AsyncFuncData, 1); + async_data->file_system = g_object_ref (file_system); + async_data->file = g_object_ref (file); + async_data->cancellable = g_object_ref (cancellable); + async_data->attributes = g_strdup (attributes); - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_info (file_system, path, types, callback, data); + async_data->callback = callback; + async_data->data = data; + + g_file_enumerate_children_async (file, + attributes, + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + cancellable, + enumerate_children_callback, + async_data); + return cancellable; } -GtkFileSystemHandle * -gtk_file_system_create_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileSystemCreateFolderCallback callback, - gpointer data) +static void +query_info_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (callback != NULL, NULL); + AsyncFuncData *async_data; + GError *error = NULL; + GFileInfo *file_info; + GFile *file; - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->create_folder (file_system, path, callback, data); -} + DEBUG ("query_info_callback"); -void -gtk_file_system_cancel_operation (GtkFileSystemHandle *handle) -{ - g_return_if_fail (GTK_IS_FILE_SYSTEM_HANDLE (handle)); + file = G_FILE (source_object); + async_data = (AsyncFuncData *) user_data; + file_info = g_file_query_info_finish (file, result, &error); - GTK_FILE_SYSTEM_GET_IFACE (handle->file_system)->cancel_operation (handle); + if (async_data->callback) + { + gdk_threads_enter (); + ((GtkFileSystemGetInfoCallback) async_data->callback) (async_data->cancellable, + file_info, error, async_data->data); + gdk_threads_leave (); + } + + if (file_info) + g_object_unref (file_info); + + if (error) + g_error_free (error); + + free_async_data (async_data); } -/** - * gtk_file_system_get_volume_for_path: - * @file_system: a #GtkFileSystem - * @path: a #GtkFilePath - * - * Queries the file system volume that corresponds to a specific path. - * There might not be a volume for all paths (consinder for instance remote - * shared), so this can return NULL. - * - * Return value: the #GtkFileSystemVolume that corresponds to the specified - * @path, or NULL if there is no such volume. You should free this value with - * gtk_file_system_volume_free(). - **/ -GtkFileSystemVolume * -gtk_file_system_get_volume_for_path (GtkFileSystem *file_system, - const GtkFilePath *path) +GCancellable * +gtk_file_system_get_info (GtkFileSystem *file_system, + GFile *file, + const gchar *attributes, + GtkFileSystemGetInfoCallback callback, + gpointer data) { + GCancellable *cancellable; + AsyncFuncData *async_data; + g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (G_IS_FILE (file), NULL); - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_volume_for_path (file_system, path); -} + cancellable = g_cancellable_new (); -/** - * gtk_file_system_volume_free: - * @file_system: a #GtkFileSystem - * @volume: a #GtkFileSystemVolume - * - * Frees a #GtkFileSystemVolume structure as returned by - * gtk_file_system_list_volumes(). - **/ -void -gtk_file_system_volume_free (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) -{ - g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system)); - g_return_if_fail (volume != NULL); + async_data = g_new0 (AsyncFuncData, 1); + async_data->file_system = g_object_ref (file_system); + async_data->file = g_object_ref (file); + async_data->cancellable = g_object_ref (cancellable); + + async_data->callback = callback; + async_data->data = data; - GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_free (file_system, volume); + g_file_query_info_async (file, + attributes, + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + cancellable, + query_info_callback, + async_data); + + return cancellable; } -/** - * gtk_file_system_volume_get_base_path: - * @file_system: a #GtkFileSystem - * @volume: a #GtkFileSystemVolume - * - * Queries the base path for a volume. For example, a CD-ROM device may yield a - * path of "/mnt/cdrom". - * - * Return value: a #GtkFilePath with the base mount path of the specified - * @volume. - **/ -GtkFilePath * -gtk_file_system_volume_get_base_path (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) +static void +drive_poll_for_media_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (volume != NULL, NULL); + AsyncFuncData *async_data; + GError *error = NULL; + + g_drive_poll_for_media_finish (G_DRIVE (source_object), result, &error); + async_data = (AsyncFuncData *) user_data; - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_base_path (file_system, volume); + gdk_threads_enter (); + ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, + (GtkFileSystemVolume *) source_object, + error, async_data->data); + gdk_threads_leave (); + + if (error) + g_error_free (error); } -/** - * gtk_file_system_volume_get_is_mounted: - * @file_system: a #GtkFileSystem - * @volume: a #GtkFileSystemVolume - * - * Queries whether a #GtkFileSystemVolume is mounted or not. If it is not, it - * can be mounted with gtk_file_system_volume_mount(). - * - * Return value: TRUE if the @volume is mounted, FALSE otherwise. - **/ -gboolean -gtk_file_system_volume_get_is_mounted (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) +static void +volume_mount_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE); - g_return_val_if_fail (volume != NULL, FALSE); + AsyncFuncData *async_data; + GError *error = NULL; + + g_volume_mount_finish (G_VOLUME (source_object), result, &error); + async_data = (AsyncFuncData *) user_data; - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_is_mounted (file_system, volume); + gdk_threads_enter (); + ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, + (GtkFileSystemVolume *) source_object, + error, async_data->data); + gdk_threads_leave (); + + if (error) + g_error_free (error); } -/** - * gtk_file_system_volume_mount: - * @file_system: a #GtkFileSystem - * @volume: a #GtkFileSystemVolume - * @error: location to store error, or %NULL - * - * Tries to mount an unmounted volume. This may cause the "volumes-changed" - * signal in the @file_system to be emitted. - * - * Return value: TRUE if the @volume was mounted successfully, FALSE otherwise. - **/ -/* FIXME XXX: update documentation above */ -GtkFileSystemHandle * -gtk_file_system_volume_mount (GtkFileSystem *file_system, +GCancellable * +gtk_file_system_mount_volume (GtkFileSystem *file_system, GtkFileSystemVolume *volume, + GMountOperation *mount_operation, GtkFileSystemVolumeMountCallback callback, gpointer data) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (volume != NULL, NULL); - g_return_val_if_fail (callback != NULL, NULL); + GCancellable *cancellable; + AsyncFuncData *async_data; + gboolean handled = FALSE; + + DEBUG ("volume_mount"); + + cancellable = g_cancellable_new (); + + async_data = g_new0 (AsyncFuncData, 1); + async_data->file_system = g_object_ref (file_system); + async_data->cancellable = g_object_ref (cancellable); + + async_data->callback = callback; + async_data->data = data; - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_mount (file_system, volume, callback, data); + if (G_IS_DRIVE (volume)) + { + /* this path happens for drives that are not polled by the OS and where the last media + * check indicated that no media was available. So the thing to do here is to + * invoke poll_for_media() on the drive + */ + g_drive_poll_for_media (G_DRIVE (volume), cancellable, drive_poll_for_media_cb, async_data); + handled = TRUE; + } + else if (G_IS_VOLUME (volume)) + { + g_volume_mount (G_VOLUME (volume), G_MOUNT_MOUNT_NONE, mount_operation, cancellable, volume_mount_cb, async_data); + handled = TRUE; + } + + if (!handled) + free_async_data (async_data); + + return cancellable; } -/** - * gtk_file_system_volume_get_display_name: - * @file_system: a #GtkFileSystem - * @volume: a #GtkFileSystemVolume - * - * Queries the human-readable name for a @volume. This string can be displayed - * in a list of volumes that can be accessed, for example. - * - * Return value: A string with the human-readable name for a #GtkFileSystemVolume. - **/ -char * -gtk_file_system_volume_get_display_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) +static void +enclosing_volume_mount_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (volume != NULL, NULL); + GtkFileSystemVolume *volume; + AsyncFuncData *async_data; + GError *error = NULL; + + async_data = (AsyncFuncData *) user_data; + g_file_mount_enclosing_volume_finish (G_FILE (source_object), result, &error); + volume = gtk_file_system_get_volume_for_file (async_data->file_system, G_FILE (source_object)); - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_display_name (file_system, volume); + gdk_threads_enter (); + ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, volume, + error, async_data->data); + gdk_threads_leave (); + + if (error) + g_error_free (error); } -/** - * gtk_file_system_volume_render_icon: - * @file_system: a #GtkFileSystem - * @volume: a #GtkFileSystemVolume - * @widget: Reference widget to render icons. - * @pixel_size: Size of the icon. - * @error: location to store error, or %NULL - * - * Renders an icon suitable for a file #GtkFileSystemVolume. - * - * Return value: A #GdkPixbuf containing an icon, or NULL if the icon could not - * be rendered. In the latter case, the @error value will be set as - * appropriate. - **/ -GdkPixbuf * -gtk_file_system_volume_render_icon (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GtkWidget *widget, - gint pixel_size, - GError **error) +GCancellable * +gtk_file_system_mount_enclosing_volume (GtkFileSystem *file_system, + GFile *file, + GMountOperation *mount_operation, + GtkFileSystemVolumeMountCallback callback, + gpointer data) { - gchar *icon_name; - GdkPixbuf *pixbuf = NULL; + GCancellable *cancellable; + AsyncFuncData *async_data; g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (volume != NULL, NULL); - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - g_return_val_if_fail (pixel_size > 0, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - icon_name = gtk_file_system_volume_get_icon_name (file_system, volume, - error); - if (icon_name) - { - GtkIconTheme *icon_theme; + g_return_val_if_fail (G_IS_FILE (file), NULL); - icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget)); - if (gtk_icon_theme_has_icon (icon_theme, icon_name)) - pixbuf = gtk_icon_theme_load_icon (icon_theme, - icon_name, pixel_size, 0, NULL); - g_free (icon_name); - } + DEBUG ("mount_enclosing_volume"); - if (!pixbuf) - pixbuf = gtk_widget_render_icon (widget, - GTK_STOCK_HARDDISK, - GTK_ICON_SIZE_MENU, - NULL); + cancellable = g_cancellable_new (); - return pixbuf; -} + async_data = g_new0 (AsyncFuncData, 1); + async_data->file_system = g_object_ref (file_system); + async_data->file = g_object_ref (file); + async_data->cancellable = g_object_ref (cancellable); -/** - * gtk_file_system_volume_get_icon_name: - * @file_system: a #GtkFileSystem - * @volume: a #GtkFileSystemVolume - * @error: location to store error, or %NULL - * - * Gets an icon name suitable for a #GtkFileSystemVolume. - * - * Return value: An icon name which can be used for rendering an icon for - * this volume, or %NULL if no icon name could be found. In the latter - * case, the @error value will be set as appropriate. - **/ -gchar * -gtk_file_system_volume_get_icon_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GError **error) -{ - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (volume != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); + async_data->callback = callback; + async_data->data = data; - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_icon_name (file_system, - volume, - error); + g_file_mount_enclosing_volume (file, + G_MOUNT_MOUNT_NONE, + mount_operation, + cancellable, + enclosing_volume_mount_cb, + async_data); + return cancellable; } -/** - * gtk_file_system_get_parent: - * @file_system: a #GtkFileSystem - * @path: base path name - * @parent: location to store parent path name - * @error: location to store error, or %NULL - * - * Gets the name of the parent folder of a path. If the path has no parent, as when - * you request the parent of a file system root, then @parent will be set to %NULL. - * - * Return value: %TRUE if the operation was successful: @parent will be set to - * the name of the @path's parent, or to %NULL if @path is already a file system - * root. If the operation fails, this function returns %FALSE, sets @parent to - * NULL, and sets the @error value if it is specified. - **/ gboolean -gtk_file_system_get_parent (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFilePath **parent, - GError **error) +gtk_file_system_insert_bookmark (GtkFileSystem *file_system, + GFile *file, + gint position, + GError **error) { - gboolean result; - - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE); - g_return_val_if_fail (path != NULL, FALSE); - g_return_val_if_fail (parent != NULL, FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + GtkFileSystemPrivate *priv; + GSList *bookmarks; + GtkFileSystemBookmark *bookmark; + gboolean result = TRUE; + GFile *bookmarks_file; - *parent = NULL; + priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system); + bookmarks = priv->bookmarks; - result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_parent (file_system, path, parent, error); - g_assert (result || *parent == NULL); + while (bookmarks) + { + bookmark = bookmarks->data; + bookmarks = bookmarks->next; - return result; -} + if (g_file_equal (bookmark->file, file)) + { + /* File is already in bookmarks */ + result = FALSE; + break; + } + } -GtkFilePath * -gtk_file_system_make_path (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *display_name, - GError **error) -{ - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (base_path != NULL, NULL); - g_return_val_if_fail (display_name != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); + if (!result) + { + gchar *uri = g_file_get_uri (file); + + g_set_error (error, + GTK_FILE_SYSTEM_ERROR, + GTK_FILE_SYSTEM_ERROR_ALREADY_EXISTS, + "%s already exists in the bookmarks list", + uri); + + g_free (uri); + + return FALSE; + } + + bookmark = g_slice_new0 (GtkFileSystemBookmark); + bookmark->file = g_object_ref (file); + + priv->bookmarks = g_slist_insert (priv->bookmarks, bookmark, position); - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->make_path (file_system, base_path, display_name, error); + bookmarks_file = get_bookmarks_file (); + save_bookmarks (bookmarks_file, priv->bookmarks); + g_object_unref (bookmarks_file); + + g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0); + + return TRUE; } -/** - * gtk_file_system_parse: - * @file_system: a #GtkFileSystem - * @base_path: reference folder with respect to which relative - * paths should be interpreted. - * @str: the string to parse - * @folder: location to store folder portion of result, or %NULL - * @file_part: location to store file portion of result, or %NULL - * @error: location to store error, or %NULL - * - * Given a string entered by a user, parse it (possibly using - * heuristics) into a folder path and a UTF-8 encoded - * filename part. (Suitable for passing to gtk_file_system_make_path()) - * - * Note that the returned filename point may point to a subfolder - * of the returned folder. Adding a trailing path separator is needed - * to enforce the interpretation as a folder name. - * - * If parsing fails because the syntax of @str is not understood, - * and error of type GTK_FILE_SYSTEM_ERROR_BAD_FILENAME will - * be set in @error and %FALSE returned. - * - * If parsing fails because a path was encountered that doesn't - * exist on the filesystem, then an error of type - * %GTK_FILE_SYSTEM_ERROR_NONEXISTENT will be set in @error - * and %FALSE returned. (This only applies to parsing relative paths, - * not to interpretation of @file_part. No check is made as - * to whether @file_part exists.) - * - * Return value: %TRUE if the parsing succeeds, otherwise, %FALSE. - **/ gboolean -gtk_file_system_parse (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *str, - GtkFilePath **folder, - gchar **file_part, - GError **error) +gtk_file_system_remove_bookmark (GtkFileSystem *file_system, + GFile *file, + GError **error) { - GtkFilePath *tmp_folder = NULL; - gchar *tmp_file_part = NULL; - gboolean result; - - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE); - g_return_val_if_fail (base_path != NULL, FALSE); - g_return_val_if_fail (str != NULL, FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->parse (file_system, base_path, str, - &tmp_folder, &tmp_file_part, - error); - g_assert (result || (tmp_folder == NULL && tmp_file_part == NULL)); - - if (folder) - *folder = tmp_folder; - else - gtk_file_path_free (tmp_folder); + GtkFileSystemPrivate *priv; + GtkFileSystemBookmark *bookmark; + GSList *bookmarks; + gboolean result = FALSE; + GFile *bookmarks_file; - if (file_part) - *file_part = tmp_file_part; - else - g_free (tmp_file_part); + priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system); - return result; -} + if (!priv->bookmarks) + return FALSE; + bookmarks = priv->bookmarks; -gchar * -gtk_file_system_path_to_uri (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (path != NULL, NULL); - - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_uri (file_system, path); + while (bookmarks) + { + bookmark = bookmarks->data; + + if (g_file_equal (bookmark->file, file)) + { + result = TRUE; + priv->bookmarks = g_slist_remove_link (priv->bookmarks, bookmarks); + gtk_file_system_bookmark_free (bookmark); + g_slist_free_1 (bookmarks); + break; + } + + bookmarks = bookmarks->next; + } + + if (!result) + { + gchar *uri = g_file_get_uri (file); + + g_set_error (error, + GTK_FILE_SYSTEM_ERROR, + GTK_FILE_SYSTEM_ERROR_NONEXISTENT, + "%s does not exist in the bookmarks list", + uri); + + g_free (uri); + + return FALSE; + } + + bookmarks_file = get_bookmarks_file (); + save_bookmarks (bookmarks_file, priv->bookmarks); + g_object_unref (bookmarks_file); + + g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0); + + return TRUE; } gchar * -gtk_file_system_path_to_filename (GtkFileSystem *file_system, - const GtkFilePath *path) +gtk_file_system_get_bookmark_label (GtkFileSystem *file_system, + GFile *file) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (path != NULL, NULL); - - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_filename (file_system, path); -} + GtkFileSystemPrivate *priv; + GSList *bookmarks; + gchar *label = NULL; -GtkFilePath * -gtk_file_system_uri_to_path (GtkFileSystem *file_system, - const gchar *uri) -{ - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (uri != NULL, NULL); - - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->uri_to_path (file_system, uri); -} + DEBUG ("get_bookmark_label"); -GtkFilePath * -gtk_file_system_filename_to_path (GtkFileSystem *file_system, - const gchar *filename) -{ - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (filename != NULL, NULL); + priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system); + bookmarks = priv->bookmarks; - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->filename_to_path (file_system, filename); -} + while (bookmarks) + { + GtkFileSystemBookmark *bookmark; -/** - * gtk_file_system_path_is_local: - * @filesystem: a #GtkFileSystem - * @path: A #GtkFilePath from that filesystem - * - * Checks whether a #GtkFilePath is local; that is whether - * gtk_file_system_path_to_filename would return non-%NULL. - * - * Return value: %TRUE if the path is loca - **/ -gboolean -gtk_file_system_path_is_local (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - gchar *filename; - gboolean result; - - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE); - g_return_val_if_fail (path != NULL, FALSE); + bookmark = bookmarks->data; + bookmarks = bookmarks->next; - filename = gtk_file_system_path_to_filename (file_system, path); - result = filename != NULL; - g_free (filename); + if (g_file_equal (file, bookmark->file)) + { + label = g_strdup (bookmark->label); + break; + } + } - return result; + return label; } -/** - * gtk_file_system_insert_bookmark: - * @file_system: a #GtkFileSystem - * @path: path of the bookmark to add - * @position: index in the bookmarks list at which the @path should be inserted; use 0 - * for the beginning, and -1 or the number of bookmarks itself for the end of the list. - * @error: location to store error, or %NULL - * - * Adds a path for a folder to the user's bookmarks list. If the operation - * succeeds, the "bookmarks_changed" signal will be emitted. Bookmark paths are - * unique; if you try to insert a @path that already exists, the operation will - * fail and the @error will be set to #GTK_FILE_SYSTEM_ERROR_ALREADY_EXISTS. To - * reorder the list of bookmarks, use gtk_file_system_remove_bookmark() to - * remove the path in question, and call gtk_file_system_insert_bookmark() with - * the new position for the path. - * - * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter case, - * the @error value will be set. - **/ -gboolean -gtk_file_system_insert_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - gint position, - GError **error) +void +gtk_file_system_set_bookmark_label (GtkFileSystem *file_system, + GFile *file, + const gchar *label) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE); - g_return_val_if_fail (path != NULL, FALSE); + GtkFileSystemPrivate *priv; + gboolean changed = FALSE; + GFile *bookmarks_file; + GSList *bookmarks; + + DEBUG ("set_bookmark_label"); - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->insert_bookmark (file_system, path, position, error); + priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system); + bookmarks = priv->bookmarks; + + while (bookmarks) + { + GtkFileSystemBookmark *bookmark; + + bookmark = bookmarks->data; + bookmarks = bookmarks->next; + + if (g_file_equal (file, bookmark->file)) + { + g_free (bookmark->file); + bookmark->label = g_strdup (label); + changed = TRUE; + break; + } + } + + bookmarks_file = get_bookmarks_file (); + save_bookmarks (bookmarks_file, priv->bookmarks); + g_object_unref (bookmarks_file); + + if (changed) + g_signal_emit_by_name (file_system, "bookmarks-changed", 0); } -/** - * gtk_file_system_remove_bookmark: - * @file_system: a #GtkFileSystem - * @path: path of the bookmark to remove - * @error: location to store error, or %NULL - * - * Removes a bookmark folder from the user's bookmarks list. If the operation - * succeeds, the "bookmarks_changed" signal will be emitted. If you try to remove - * a @path which does not exist in the bookmarks list, the operation will fail - * and the @error will be set to GTK_FILE_SYSTEM_ERROR_NONEXISTENT. - * - * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter - * case, the @error value will be set. - **/ -gboolean -gtk_file_system_remove_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - GError **error) +GtkFileSystemVolume * +gtk_file_system_get_volume_for_file (GtkFileSystem *file_system, + GFile *file) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE); - g_return_val_if_fail (path != NULL, FALSE); + GtkFileSystemPrivate *priv; + GMount *mount; + + DEBUG ("get_volume_for_file"); - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->remove_bookmark (file_system, path, error); + priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system); + mount = g_file_find_enclosing_mount (file, NULL, NULL); + + if (!mount && g_file_is_native (file)) + return (GtkFileSystemVolume *) root_volume_token; + + return (GtkFileSystemVolume *) mount; } -/** - * gtk_file_system_list_bookmarks: - * @file_system: a #GtkFileSystem - * - * Queries the list of bookmarks in the file system. - * - * Return value: A list of #GtkFilePath, or NULL if there are no configured - * bookmarks. You should use gtk_file_paths_free() to free this list. - * - * See also: gtk_file_system_get_supports_bookmarks() - **/ -GSList * -gtk_file_system_list_bookmarks (GtkFileSystem *file_system) +/* GtkFolder methods */ +static void +gtk_folder_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); + GtkFolderPrivate *priv; - return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_bookmarks (file_system); + priv = GTK_FOLDER_GET_PRIVATE (object); + + switch (prop_id) + { + case PROP_FILE: + priv->folder_file = g_value_dup_object (value); + break; + case PROP_ENUMERATOR: + priv->enumerator = g_value_dup_object (value); + break; + case PROP_ATTRIBUTES: + priv->attributes = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } -/** - * gtk_file_system_get_bookmark_label: - * @file_system: a #GtkFileSystem - * @path: path of the bookmark - * - * Gets the label to display for a bookmark, or %NULL. - * - * Returns: the label for the bookmark @path - * - * Since: 2.8 - */ -gchar * -gtk_file_system_get_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path) +static void +gtk_folder_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - GtkFileSystemIface *iface; - - g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (path != NULL, NULL); + GtkFolderPrivate *priv; - iface = GTK_FILE_SYSTEM_GET_IFACE (file_system); - if (iface->get_bookmark_label) - return iface->get_bookmark_label (file_system, path); + priv = GTK_FOLDER_GET_PRIVATE (object); - return NULL; + switch (prop_id) + { + case PROP_FILE: + g_value_set_object (value, priv->folder_file); + break; + case PROP_ENUMERATOR: + g_value_set_object (value, priv->enumerator); + break; + case PROP_ATTRIBUTES: + g_value_set_string (value, priv->attributes); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } -/** - * gtk_file_system_set_bookmark_label: - * @file_system: a #GtkFileSystem - * @path: path of the bookmark - * @label: the label for the bookmark, or %NULL to display - * the path itself - * - * Sets the label to display for a bookmark. - * - * Since: 2.8 - */ -void -gtk_file_system_set_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path, - const gchar *label) +static void +query_created_file_info_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - GtkFileSystemIface *iface; + GFile *file = G_FILE (source_object); + GError *error = NULL; + GFileInfo *info; + GtkFolder *folder; + GSList *files; + + info = g_file_query_info_finish (file, result, &error); - g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system)); - g_return_if_fail (path != NULL); + if (error) + { + g_error_free (error); + return; + } - iface = GTK_FILE_SYSTEM_GET_IFACE (file_system); - if (iface->set_bookmark_label) - iface->set_bookmark_label (file_system, path, label); + folder = GTK_FOLDER (user_data); + _gtk_folder_add_file (folder, file, info); + + files = g_slist_prepend (NULL, file); + g_signal_emit (folder, folder_signals[FILES_ADDED], 0, files); + g_slist_free (files); + + g_object_unref (info); } -/***************************************** - * GtkFileFolder * - *****************************************/ -GType -gtk_file_folder_get_type (void) +static void +directory_monitor_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event, + gpointer data) { - static GType file_folder_type = 0; + GtkFolderPrivate *priv; + GtkFolder *folder; + GSList *files; - if (!file_folder_type) + folder = GTK_FOLDER (data); + priv = GTK_FOLDER_GET_PRIVATE (folder); + files = g_slist_prepend (NULL, file); + + gdk_threads_enter (); + + switch (event) { - const GTypeInfo file_folder_info = - { - sizeof (GtkFileFolderIface), /* class_size */ - gtk_file_folder_base_init, /* base_init */ - NULL, /* base_finalize */ - }; - - file_folder_type = g_type_register_static (G_TYPE_INTERFACE, - I_("GtkFileFolder"), - &file_folder_info, 0); - - g_type_interface_add_prerequisite (file_folder_type, G_TYPE_OBJECT); + case G_FILE_MONITOR_EVENT_CREATED: + g_file_query_info_async (file, + priv->attributes, + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + priv->cancellable, + query_created_file_info_callback, + folder); + break; + case G_FILE_MONITOR_EVENT_DELETED: + if (g_file_equal (file, priv->folder_file)) + g_signal_emit (folder, folder_signals[DELETED], 0); + else + g_signal_emit (folder, folder_signals[FILES_REMOVED], 0, files); + break; + default: + break; } - return file_folder_type; + gdk_threads_leave (); + + g_slist_free (files); } static void -gtk_file_folder_base_init (gpointer g_class) +enumerator_files_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - static gboolean initialized = FALSE; - - if (!initialized) + GFileEnumerator *enumerator; + GtkFolderPrivate *priv; + GtkFolder *folder; + GError *error = NULL; + GSList *files = NULL; + GList *file_infos, *f; + + enumerator = G_FILE_ENUMERATOR (source_object); + file_infos = g_file_enumerator_next_files_finish (enumerator, result, &error); + + if (error) + { + g_warning (error->message); + g_error_free (error); + return; + } + + folder = GTK_FOLDER (user_data); + priv = GTK_FOLDER_GET_PRIVATE (folder); + + if (!file_infos) + { + g_file_enumerator_close_async (enumerator, + G_PRIORITY_DEFAULT, + NULL, NULL, NULL); + + _gtk_folder_set_finished_loading (folder, TRUE); + return; + } + + g_file_enumerator_next_files_async (enumerator, FILES_PER_QUERY, + G_PRIORITY_DEFAULT, + priv->cancellable, + enumerator_files_callback, + folder); + + for (f = file_infos; f; f = f->next) { - GType iface_type = G_TYPE_FROM_INTERFACE (g_class); - - g_signal_new (I_("deleted"), - iface_type, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkFileFolderIface, deleted), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - g_signal_new (I_("files-added"), - iface_type, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkFileFolderIface, files_added), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - g_signal_new (I_("files-changed"), - iface_type, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkFileFolderIface, files_changed), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - g_signal_new (I_("files-removed"), - iface_type, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkFileFolderIface, files_removed), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - g_signal_new (I_("finished-loading"), - iface_type, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkFileFolderIface, finished_loading), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - initialized = TRUE; + GFileInfo *info; + GFile *child_file; + + info = f->data; + child_file = g_file_get_child (priv->folder_file, g_file_info_get_name (info)); + _gtk_folder_add_file (folder, child_file, info); + files = g_slist_prepend (files, child_file); } + + gdk_threads_enter (); + g_signal_emit (folder, folder_signals[FILES_ADDED], 0, files); + gdk_threads_leave (); + + g_list_foreach (file_infos, (GFunc) g_object_unref, NULL); + g_list_free (file_infos); + + g_slist_foreach (files, (GFunc) g_object_unref, NULL); + g_slist_free (files); } -gboolean -gtk_file_folder_list_children (GtkFileFolder *folder, - GSList **children, - GError **error) +static void +gtk_folder_constructed (GObject *object) { - gboolean result; - GSList *tmp_children = NULL; - - g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + GtkFolderPrivate *priv; + GError *error = NULL; - result = GTK_FILE_FOLDER_GET_IFACE (folder)->list_children (folder, &tmp_children, error); - g_assert (result || tmp_children == NULL); + priv = GTK_FOLDER_GET_PRIVATE (object); + priv->directory_monitor = g_file_monitor_directory (priv->folder_file, G_FILE_MONITOR_NONE, NULL, &error); - if (children) - *children = tmp_children; + if (error) + g_warning (error->message); else - gtk_file_paths_free (tmp_children); + g_signal_connect (priv->directory_monitor, "changed", + G_CALLBACK (directory_monitor_changed), object); - return result; + g_file_enumerator_next_files_async (priv->enumerator, + FILES_PER_QUERY, + G_PRIORITY_DEFAULT, + priv->cancellable, + enumerator_files_callback, + object); + /* This isn't needed anymore */ + g_object_unref (priv->enumerator); + priv->enumerator = NULL; } -GtkFileInfo * -gtk_file_folder_get_info (GtkFileFolder *folder, - const GtkFilePath *path, - GError **error) +static void +gtk_folder_finalize (GObject *object) { - g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); + GtkFolderPrivate *priv; - return GTK_FILE_FOLDER_GET_IFACE (folder)->get_info (folder, path, error); -} + priv = GTK_FOLDER_GET_PRIVATE (object); -gboolean -gtk_file_folder_is_finished_loading (GtkFileFolder *folder) -{ - GtkFileFolderIface *iface; + g_hash_table_unref (priv->children); - g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), TRUE); + if (priv->folder_file) + g_object_unref (priv->folder_file); - iface = GTK_FILE_FOLDER_GET_IFACE (folder); - if (!iface->is_finished_loading) - return TRUE; - else - return iface->is_finished_loading (folder); -} + if (priv->directory_monitor) + g_object_unref (priv->directory_monitor); + g_cancellable_cancel (priv->cancellable); + g_object_unref (priv->cancellable); + g_free (priv->attributes); -/***************************************** - * GtkFilePath modules * - *****************************************/ + G_OBJECT_CLASS (gtk_folder_parent_class)->finalize (object); +} -/* We make these real functions in case either copy or free are implemented as macros - */ -static gpointer -gtk_file_path_real_copy (gpointer boxed) -{ - return gtk_file_path_copy ((GtkFilePath *) boxed); +static void +gtk_folder_class_init (GtkFolderClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->set_property = gtk_folder_set_property; + object_class->get_property = gtk_folder_get_property; + object_class->constructed = gtk_folder_constructed; + object_class->finalize = gtk_folder_finalize; + + g_object_class_install_property (object_class, + PROP_FILE, + g_param_spec_object ("file", + "File", + "GFile for the folder", + G_TYPE_FILE, + GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, + PROP_ENUMERATOR, + g_param_spec_object ("enumerator", + "Enumerator", + "GFileEnumerator to list files", + G_TYPE_FILE_ENUMERATOR, + GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, + PROP_ATTRIBUTES, + g_param_spec_string ("attributes", + "Attributes", + "Attributes to query for", + NULL, + GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + folder_signals[FILES_ADDED] = + g_signal_new ("files-added", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkFolderClass, files_added), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + folder_signals[FILES_REMOVED] = + g_signal_new ("files-removed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkFolderClass, files_removed), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + folder_signals[FILES_CHANGED] = + g_signal_new ("files-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkFolderClass, files_changed), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + folder_signals[FINISHED_LOADING] = + g_signal_new ("finished-loading", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkFolderClass, finished_loading), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + folder_signals[DELETED] = + g_signal_new ("deleted", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkFolderClass, deleted), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_type_class_add_private (object_class, sizeof (GtkFolderPrivate)); } static void -gtk_file_path_real_free (gpointer boxed) +gtk_folder_init (GtkFolder *folder) { - gtk_file_path_free (boxed); + GtkFolderPrivate *priv; + + priv = GTK_FOLDER_GET_PRIVATE (folder); + + priv->children = g_hash_table_new_full (g_file_hash, + (GEqualFunc) g_file_equal, + (GDestroyNotify) g_object_unref, + (GDestroyNotify) g_object_unref); + priv->cancellable = g_cancellable_new (); } -GType -gtk_file_path_get_type (void) +static void +_gtk_folder_set_finished_loading (GtkFolder *folder, + gboolean finished_loading) { - static GType our_type = 0; - - if (our_type == 0) - our_type = g_boxed_type_register_static (I_("GtkFilePath"), - (GBoxedCopyFunc) gtk_file_path_real_copy, - (GBoxedFreeFunc) gtk_file_path_real_free); - - return our_type; -} + GtkFolderPrivate *priv; + priv = GTK_FOLDER_GET_PRIVATE (folder); + priv->finished_loading = (finished_loading == TRUE); -GSList * -gtk_file_paths_sort (GSList *paths) -{ -#ifndef G_OS_WIN32 - return g_slist_sort (paths, (GCompareFunc)strcmp); -#else - return g_slist_sort (paths, (GCompareFunc)_gtk_file_system_win32_path_compare); -#endif + gdk_threads_enter (); + g_signal_emit (folder, folder_signals[FINISHED_LOADING], 0); + gdk_threads_leave (); } -/** - * gtk_file_paths_copy: - * @paths: A #GSList of #GtkFilePath structures. - * - * Copies a list of #GtkFilePath structures. - * - * Return value: A copy of @paths. Since the contents of the list are copied as - * well, you should use gtk_file_paths_free() to free the result. - **/ -GSList * -gtk_file_paths_copy (GSList *paths) +static void +_gtk_folder_add_file (GtkFolder *folder, + GFile *file, + GFileInfo *info) { - GSList *head, *tail, *l; + GtkFolderPrivate *priv; - head = tail = NULL; + priv = GTK_FOLDER_GET_PRIVATE (folder); - for (l = paths; l; l = l->next) - { - GtkFilePath *path; - GSList *node; + g_hash_table_insert (priv->children, + g_object_ref (file), + g_object_ref (info)); +} - path = l->data; - node = g_slist_alloc (); +GSList * +gtk_folder_list_children (GtkFolder *folder) +{ + GtkFolderPrivate *priv; + GList *files, *elem; + GSList *children = NULL; - if (tail) - tail->next = node; - else - head = node; + priv = GTK_FOLDER_GET_PRIVATE (folder); + files = g_hash_table_get_keys (priv->children); + children = NULL; - node->data = gtk_file_path_copy (path); - tail = node; - } + for (elem = files; elem; elem = elem->next) + children = g_slist_prepend (children, g_object_ref (elem->data)); + + g_list_free (files); - return head; + return children; } -void -gtk_file_paths_free (GSList *paths) +GFileInfo * +gtk_folder_get_info (GtkFolder *folder, + GFile *file) { - GSList *tmp_list; + GtkFolderPrivate *priv; + GFileInfo *info; + + priv = GTK_FOLDER_GET_PRIVATE (folder); + info = g_hash_table_lookup (priv->children, file); - for (tmp_list = paths; tmp_list; tmp_list = tmp_list->next) - gtk_file_path_free (tmp_list->data); + if (!info) + return NULL; - g_slist_free (paths); + return g_object_ref (info); } -/***************************************** - * GtkFileSystem modules * - *****************************************/ +gboolean +gtk_folder_is_finished_loading (GtkFolder *folder) +{ + GtkFolderPrivate *priv; -typedef struct _GtkFileSystemModule GtkFileSystemModule; -typedef struct _GtkFileSystemModuleClass GtkFileSystemModuleClass; + priv = GTK_FOLDER_GET_PRIVATE (folder); + + return priv->finished_loading; +} -struct _GtkFileSystemModule +/* GtkFileSystemVolume public methods */ +gchar * +gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume) { - GTypeModule parent_instance; - - GModule *library; + DEBUG ("volume_get_display_name"); - void (*init) (GTypeModule *module); - void (*exit) (void); - GtkFileSystem * (*create) (void); + if (IS_ROOT_VOLUME (volume)) + return g_strdup (_(root_volume_token)); + if (G_IS_DRIVE (volume)) + return g_drive_get_name (G_DRIVE (volume)); + else if (G_IS_MOUNT (volume)) + return g_mount_get_name (G_MOUNT (volume)); + else if (G_IS_VOLUME (volume)) + return g_volume_get_name (G_VOLUME (volume)); - gchar *path; -}; + return NULL; +} -struct _GtkFileSystemModuleClass +gboolean +gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume) { - GTypeModuleClass parent_class; -}; + gboolean mounted; -G_DEFINE_TYPE (GtkFileSystemModule, _gtk_file_system_module, G_TYPE_TYPE_MODULE) -#define GTK_TYPE_FILE_SYSTEM_MODULE (_gtk_file_system_module_get_type ()) -#define GTK_FILE_SYSTEM_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), GTK_TYPE_FILE_SYSTEM_MODULE, GtkFileSystemModule)) + DEBUG ("volume_is_mounted"); + if (IS_ROOT_VOLUME (volume)) + return TRUE; -static GSList *loaded_file_systems; + mounted = FALSE; -static gboolean -gtk_file_system_module_load (GTypeModule *module) -{ - GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module); - - fs_module->library = g_module_open (fs_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); - if (!fs_module->library) - { - g_warning (g_module_error()); - return FALSE; - } - - /* extract symbols from the lib */ - if (!g_module_symbol (fs_module->library, "fs_module_init", - (gpointer *)&fs_module->init) || - !g_module_symbol (fs_module->library, "fs_module_exit", - (gpointer *)&fs_module->exit) || - !g_module_symbol (fs_module->library, "fs_module_create", - (gpointer *)&fs_module->create)) + if (G_IS_MOUNT (volume)) + mounted = TRUE; + else if (G_IS_VOLUME (volume)) { - g_warning (g_module_error()); - g_module_close (fs_module->library); - - return FALSE; + GMount *mount; + + mount = g_volume_get_mount (G_VOLUME (volume)); + + if (mount) + { + mounted = TRUE; + g_object_unref (mount); + } } - - /* call the filesystems's init function to let it */ - /* setup anything it needs to set up. */ - fs_module->init (module); - return TRUE; + return mounted; } -static void -gtk_file_system_module_unload (GTypeModule *module) +GFile * +gtk_file_system_volume_get_root (GtkFileSystemVolume *volume) { - GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module); - - fs_module->exit(); + GFile *file = NULL; - g_module_close (fs_module->library); - fs_module->library = NULL; + DEBUG ("volume_get_base"); - fs_module->init = NULL; - fs_module->exit = NULL; - fs_module->create = NULL; -} + if (IS_ROOT_VOLUME (volume)) + return g_file_new_for_uri ("file:///"); -/* This only will ever be called if an error occurs during - * initialization - */ -static void -gtk_file_system_module_finalize (GObject *object) -{ - GtkFileSystemModule *module = GTK_FILE_SYSTEM_MODULE (object); + if (G_IS_MOUNT (volume)) + file = g_mount_get_root (G_MOUNT (volume)); + else if (G_IS_VOLUME (volume)) + { + GMount *mount; - g_free (module->path); + mount = g_volume_get_mount (G_VOLUME (volume)); - G_OBJECT_CLASS (_gtk_file_system_module_parent_class)->finalize (object); + if (mount) + { + file = g_mount_get_root (mount); + g_object_unref (mount); + } + } + + return file; } -static void -_gtk_file_system_module_class_init (GtkFileSystemModuleClass *class) +static GdkPixbuf * +get_pixbuf_from_gicon (GIcon *icon, + GtkWidget *widget, + gint icon_size, + GError **error) { - GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class); - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - - module_class->load = gtk_file_system_module_load; - module_class->unload = gtk_file_system_module_unload; + GdkScreen *screen; + GtkIconTheme *icon_theme; + GtkIconInfo *icon_info; + GdkPixbuf *pixbuf; + + screen = gtk_widget_get_screen (GTK_WIDGET (widget)); + icon_theme = gtk_icon_theme_get_for_screen (screen); + + icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme, + icon, + icon_size, + 0); + + if (!icon_info) + return NULL; + + pixbuf = gtk_icon_info_load_icon (icon_info, error); + gtk_icon_info_free (icon_info); - gobject_class->finalize = gtk_file_system_module_finalize; + return pixbuf; } -static void -_gtk_file_system_module_init (GtkFileSystemModule *fs_module) +static GIcon * +get_icon_for_special_directory (GFile *file) { -} + const gchar *special_dir; + GFile *special_file; + special_dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP); + special_file = g_file_new_for_path (special_dir); -static GtkFileSystem * -_gtk_file_system_module_create (GtkFileSystemModule *fs_module) -{ - GtkFileSystem *fs; - - if (g_type_module_use (G_TYPE_MODULE (fs_module))) + if (g_file_equal (file, special_file)) + { + g_object_unref (special_file); + return g_themed_icon_new ("gnome-fs-desktop"); + } + + g_object_unref (special_file); + special_dir = g_get_home_dir (); + special_file = g_file_new_for_path (special_dir); + + if (g_file_equal (file, special_file)) { - fs = fs_module->create (); - g_type_module_unuse (G_TYPE_MODULE (fs_module)); - return fs; + g_object_unref (special_file); + return g_themed_icon_new ("gnome-fs-home"); } + + g_object_unref (special_file); + return NULL; } - -GtkFileSystem * -gtk_file_system_create (const char *file_system_name) +GdkPixbuf * +gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume, + GtkWidget *widget, + gint icon_size, + GError **error) { - GSList *l; - char *module_path; - GtkFileSystemModule *fs_module; - GtkFileSystem *fs; + GIcon *icon = NULL; - for (l = loaded_file_systems; l != NULL; l = l->next) + DEBUG ("volume_get_icon_name"); + + if (IS_ROOT_VOLUME (volume)) + icon = g_themed_icon_new ("gnome-dev-harddisk"); + else if (G_IS_DRIVE (volume)) + icon = g_drive_get_icon (G_DRIVE (volume)); + else if (G_IS_VOLUME (volume)) + icon = g_volume_get_icon (G_VOLUME (volume)); + else if (G_IS_MOUNT (volume)) { - fs_module = l->data; - - if (strcmp (G_TYPE_MODULE (fs_module)->name, file_system_name) == 0) - return _gtk_file_system_module_create (fs_module); + GMount *mount = G_MOUNT (volume); + GFile *file; + + file = g_mount_get_root (mount); + icon = get_icon_for_special_directory (file); + + if (!icon) + icon = g_mount_get_icon (mount); } - fs = NULL; - if (g_module_supported ()) - { - module_path = _gtk_find_module (file_system_name, "filesystems"); + if (!icon) + return NULL; - if (module_path) - { - fs_module = g_object_new (GTK_TYPE_FILE_SYSTEM_MODULE, NULL); + return get_pixbuf_from_gicon (icon, widget, icon_size, error); +} - g_type_module_set_name (G_TYPE_MODULE (fs_module), file_system_name); - fs_module->path = g_strdup (module_path); +void +gtk_file_system_volume_free (GtkFileSystemVolume *volume) +{ + /* Root volume doesn't need to be freed */ + if (IS_ROOT_VOLUME (volume)) + return; - loaded_file_systems = g_slist_prepend (loaded_file_systems, - fs_module); + if (G_IS_MOUNT (volume) || + G_IS_VOLUME (volume) || + G_IS_DRIVE (volume)) + g_object_unref (volume); +} - fs = _gtk_file_system_module_create (fs_module); - } - - g_free (module_path); +/* GFileInfo helper functions */ +GdkPixbuf * +gtk_file_info_render_icon (GFileInfo *info, + GtkWidget *widget, + gint icon_size) +{ + GIcon *icon; + GdkPixbuf *pixbuf = NULL; + gchar *thumbnail_path; + + thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH); + + if (thumbnail_path) + pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path, + icon_size, icon_size, + NULL); + + if (!pixbuf) + { + icon = g_file_info_get_icon (info); + + if (icon) + pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL); } - - return fs; -} -#define __GTK_FILE_SYSTEM_C__ -#include "gtkaliasdef.c" + return pixbuf; +} diff --git a/gtk/gtkfilesystem.h b/gtk/gtkfilesystem.h index 18aa58485..8c40816cd 100644 --- a/gtk/gtkfilesystem.h +++ b/gtk/gtkfilesystem.h @@ -1,5 +1,5 @@ /* GTK - The GIMP Toolkit - * gtkfilesystem.h: Abstract file system interfaces + * gtkfilesystem.h: Filesystem abstraction functions. * Copyright (C) 2003, Red Hat, Inc. * * This library is free software; you can redistribute it and/or @@ -21,43 +21,25 @@ #ifndef __GTK_FILE_SYSTEM_H__ #define __GTK_FILE_SYSTEM_H__ -/* This is a "semi-private" header; it is meant only for - * alternate GtkFileChooser backend modules; no stability guarantees - * are made at this point - */ -#ifndef GTK_FILE_SYSTEM_ENABLE_UNSUPPORTED -#error "GtkFileSystem is not supported API for general use" -#endif - +#include #include #include /* For icon handling */ G_BEGIN_DECLS -typedef gint64 GtkFileTime; - -typedef struct _GtkFileFolder GtkFileFolder; -typedef struct _GtkFileFolderIface GtkFileFolderIface; -typedef struct _GtkFileInfo GtkFileInfo; -typedef struct _GtkFileSystem GtkFileSystem; -typedef struct _GtkFileSystemIface GtkFileSystemIface; -typedef struct _GtkFileSystemVolume GtkFileSystemVolume; +#define GTK_TYPE_FILE_SYSTEM (gtk_file_system_get_type ()) +#define GTK_FILE_SYSTEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_FILE_SYSTEM, GtkFileSystem)) +#define GTK_FILE_SYSTEM_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GTK_TYPE_FILE_SYSTEM, GtkFileSystemClass)) +#define GTK_IS_FILE_SYSTEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_FILE_SYSTEM)) +#define GTK_IS_FILE_SYSTEM_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GTK_TYPE_FILE_SYSTEM)) +#define GTK_FILE_SYSTEM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_FILE_SYSTEM, GtkFileSystemClass)) -typedef struct _GtkFilePath GtkFilePath; - -/* Mask of information about a file, for monitoring and - * gtk_file_system_get_info() - */ -typedef enum { - GTK_FILE_INFO_DISPLAY_NAME = 1 << 0, - GTK_FILE_INFO_IS_FOLDER = 1 << 1, - GTK_FILE_INFO_IS_HIDDEN = 1 << 2, - GTK_FILE_INFO_MIME_TYPE = 1 << 3, - GTK_FILE_INFO_MODIFICATION_TIME = 1 << 4, - GTK_FILE_INFO_SIZE = 1 << 5, - GTK_FILE_INFO_ICON = 1 << 6, - GTK_FILE_INFO_ALL = (1 << 7) - 1 -} GtkFileInfoType; +#define GTK_TYPE_FOLDER (gtk_folder_get_type ()) +#define GTK_FOLDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_FOLDER, GtkFolder)) +#define GTK_FOLDER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GTK_TYPE_FOLDER, GtkFolderClass)) +#define GTK_IS_FOLDER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_FOLDER)) +#define GTK_IS_FOLDER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GTK_TYPE_FOLDER)) +#define GTK_FOLDER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_FOLDER, GtkFolderClass)) /* GError enumeration for GtkFileSystem */ @@ -76,372 +58,137 @@ typedef enum GQuark gtk_file_system_error_quark (void); -/* Boxed-type for gtk_file_folder_get_info() results - */ -#define GTK_TYPE_FILE_INFO (gtk_file_info_get_type ()) - -GType gtk_file_info_get_type (void) G_GNUC_CONST; - -GtkFileInfo *gtk_file_info_new (void); -GtkFileInfo *gtk_file_info_copy (GtkFileInfo *info); -void gtk_file_info_free (GtkFileInfo *info); - - -G_CONST_RETURN gchar *gtk_file_info_get_display_name (const GtkFileInfo *info); -G_CONST_RETURN gchar *gtk_file_info_get_display_key (const GtkFileInfo *info); -void gtk_file_info_set_display_name (GtkFileInfo *info, - const gchar *display_name); -gboolean gtk_file_info_get_is_folder (const GtkFileInfo *info); -void gtk_file_info_set_is_folder (GtkFileInfo *info, - gboolean is_folder); -gboolean gtk_file_info_get_is_hidden (const GtkFileInfo *info); -void gtk_file_info_set_is_hidden (GtkFileInfo *info, - gboolean is_hidden); -G_CONST_RETURN gchar *gtk_file_info_get_mime_type (const GtkFileInfo *info); -void gtk_file_info_set_mime_type (GtkFileInfo *info, - const gchar *mime_type); -GtkFileTime gtk_file_info_get_modification_time (const GtkFileInfo *info); -void gtk_file_info_set_modification_time (GtkFileInfo *info, - GtkFileTime modification_time); -gint64 gtk_file_info_get_size (const GtkFileInfo *info); -void gtk_file_info_set_size (GtkFileInfo *info, - gint64 size); - -void gtk_file_info_set_icon_name (GtkFileInfo *info, - const gchar *con_name); -G_CONST_RETURN gchar *gtk_file_info_get_icon_name (const GtkFileInfo *info); -GdkPixbuf *gtk_file_info_render_icon (const GtkFileInfo *info, - GtkWidget *widget, - gint pixel_size, - GError **error); - -/* GtkFileSystemHandle - */ - -#define GTK_TYPE_FILE_SYSTEM_HANDLE (gtk_file_system_handle_get_type ()) -#define GTK_FILE_SYSTEM_HANDLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_SYSTEM_HANDLE, GtkFileSystemHandle)) -#define GTK_IS_FILE_SYSTEM_HANDLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_SYSTEM_HANDLE)) -#define GTK_FILE_SYSTEM_HANDLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SYSTEM_HANDLE, GtkFileSystemHandleUnixClass)) -#define GTK_IS_FILE_SYSTEM_HANDLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SYSTEM_HANDLE)) -#define GTK_FILE_SYSTEM_HANDLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_SYSTEM_HANDLE, GtkFileSystemHandleClass)) - -typedef struct _GtkFileSystemHandle GtkFileSystemHandle; -typedef struct _GtkFileSystemHandleClass GtkFileSystemHandleClass; +typedef struct GtkFileSystemClass GtkFileSystemClass; +typedef struct GtkFileSystem GtkFileSystem; +typedef struct GtkFolderClass GtkFolderClass; +typedef struct GtkFolder GtkFolder; +typedef struct GtkFileSystemVolume GtkFileSystemVolume; /* opaque struct */ +typedef struct GtkFileSystemBookmark GtkFileSystemBookmark; /* opaque struct */ -struct _GtkFileSystemHandle +struct GtkFileSystemClass { - GObject parent_instance; - - GtkFileSystem *file_system; + GObjectClass parent_class; - guint cancelled : 1; + void (*bookmarks_changed) (GtkFileSystem *file_system); + void (*volumes_changed) (GtkFileSystem *file_system); }; -struct _GtkFileSystemHandleClass +struct GtkFileSystem { - GObjectClass parent_class; + GObject parent_object; }; -GType gtk_file_system_handle_get_type (void); - -/* The base GtkFileSystem interface - */ -#define GTK_TYPE_FILE_SYSTEM (gtk_file_system_get_type ()) -#define GTK_FILE_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_SYSTEM, GtkFileSystem)) -#define GTK_IS_FILE_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_SYSTEM)) -#define GTK_FILE_SYSTEM_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GTK_TYPE_FILE_SYSTEM, GtkFileSystemIface)) - -/* Callbacks for the asynchronous GtkFileSystem operations - */ - -typedef void (* GtkFileSystemGetInfoCallback) (GtkFileSystemHandle *handle, - const GtkFileInfo *file_info, - const GError *error, - gpointer data); -typedef void (* GtkFileSystemGetFolderCallback) (GtkFileSystemHandle *handle, - GtkFileFolder *folder, - const GError *error, - gpointer data); -typedef void (* GtkFileSystemCreateFolderCallback) (GtkFileSystemHandle *handle, - const GtkFilePath *path, - const GError *error, - gpointer data); -typedef void (* GtkFileSystemVolumeMountCallback) (GtkFileSystemHandle *handle, - GtkFileSystemVolume *volume, - const GError *error, - gpointer data); - -/* - */ - -struct _GtkFileSystemIface +struct GtkFolderClass { - GTypeInterface base_iface; - - /* Methods - */ - GSList * (*list_volumes) (GtkFileSystem *file_system); - GtkFileSystemVolume * (*get_volume_for_path) (GtkFileSystem *file_system, - const GtkFilePath *path); - - GtkFileSystemHandle * (*get_folder) (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetFolderCallback callback, - gpointer data); - GtkFileSystemHandle * (*get_info) (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetInfoCallback callback, - gpointer data); - GtkFileSystemHandle * (*create_folder) (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileSystemCreateFolderCallback callback, - gpointer data); - - void (*cancel_operation) (GtkFileSystemHandle *handle); - - /* Volumes - */ - void (*volume_free) (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); - GtkFilePath * (*volume_get_base_path) (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); - gboolean (*volume_get_is_mounted) (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); - GtkFileSystemHandle * (*volume_mount) (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GtkFileSystemVolumeMountCallback callback, - gpointer data); - char * (*volume_get_display_name) (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); - gchar * (*volume_get_icon_name) (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GError **error); - - /* Path Manipulation - */ - gboolean (*get_parent) (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFilePath **parent, - GError **error); - GtkFilePath * (*make_path) (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *display_name, - GError **error); - gboolean (*parse) (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *str, - GtkFilePath **folder, - gchar **file_part, - GError **error); - gchar * (*path_to_uri) (GtkFileSystem *file_system, - const GtkFilePath *path); - gchar * (*path_to_filename) (GtkFileSystem *file_system, - const GtkFilePath *path); - GtkFilePath *(*uri_to_path) (GtkFileSystem *file_system, - const gchar *uri); - GtkFilePath *(*filename_to_path) (GtkFileSystem *file_system, - const gchar *path); - - /* Bookmarks - */ - gboolean (*insert_bookmark) (GtkFileSystem *file_system, - const GtkFilePath *path, - gint position, - GError **error); - gboolean (*remove_bookmark) (GtkFileSystem *file_system, - const GtkFilePath *path, - GError **error); - GSList * (*list_bookmarks) (GtkFileSystem *file_system); - - /* Signals - */ - void (*volumes_changed) (GtkFileSystem *file_system); - void (*bookmarks_changed) (GtkFileSystem *file_system); + GObjectClass parent_class; - /* Bookmark labels - */ - gchar * (*get_bookmark_label) (GtkFileSystem *file_system, - const GtkFilePath *path); - void (*set_bookmark_label) (GtkFileSystem *file_system, - const GtkFilePath *path, - const gchar *label); + void (*files_added) (GtkFolder *folder, + GList *paths); + void (*files_removed) (GtkFolder *folder, + GList *paths); + void (*files_changed) (GtkFolder *folder, + GList *paths); + void (*finished_loading) (GtkFolder *folder); + void (*deleted) (GtkFolder *folder); }; -GType gtk_file_system_get_type (void) G_GNUC_CONST; - -GSList * gtk_file_system_list_volumes (GtkFileSystem *file_system); - -GtkFileSystemVolume *gtk_file_system_get_volume_for_path (GtkFileSystem *file_system, - const GtkFilePath *path); - -void gtk_file_system_volume_free (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -GtkFilePath * gtk_file_system_volume_get_base_path (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -gboolean gtk_file_system_volume_get_is_mounted (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -GtkFileSystemHandle *gtk_file_system_volume_mount (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GtkFileSystemVolumeMountCallback callback, - gpointer data); -char * gtk_file_system_volume_get_display_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -GdkPixbuf * gtk_file_system_volume_render_icon (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GtkWidget *widget, - gint pixel_size, - GError **error); -gchar * gtk_file_system_volume_get_icon_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GError **error); - -gboolean gtk_file_system_get_parent (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFilePath **parent, - GError **error); -GtkFileSystemHandle *gtk_file_system_get_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetFolderCallback callback, - gpointer data); -GtkFileSystemHandle *gtk_file_system_get_info (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetInfoCallback callback, - gpointer data); -GtkFileSystemHandle *gtk_file_system_create_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileSystemCreateFolderCallback callback, - gpointer data); -void gtk_file_system_cancel_operation (GtkFileSystemHandle *handle); -GtkFilePath * gtk_file_system_make_path (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *display_name, - GError **error); -gboolean gtk_file_system_parse (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *str, - GtkFilePath **folder, - gchar **file_part, - GError **error); - -gchar * gtk_file_system_path_to_uri (GtkFileSystem *file_system, - const GtkFilePath *path); -gchar * gtk_file_system_path_to_filename (GtkFileSystem *file_system, - const GtkFilePath *path); -GtkFilePath *gtk_file_system_uri_to_path (GtkFileSystem *file_system, - const gchar *uri); -GtkFilePath *gtk_file_system_filename_to_path (GtkFileSystem *file_system, - const gchar *filename); - -gboolean gtk_file_system_path_is_local (GtkFileSystem *filesystem, - const GtkFilePath *path); - -gboolean gtk_file_system_insert_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - gint position, - GError **error); -gboolean gtk_file_system_remove_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - GError **error); -GSList *gtk_file_system_list_bookmarks (GtkFileSystem *file_system); - -gchar *gtk_file_system_get_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path); -void gtk_file_system_set_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path, - const gchar *label); - -/* - * Detailed information about a particular folder - */ -#define GTK_TYPE_FILE_FOLDER (gtk_file_folder_get_type ()) -#define GTK_FILE_FOLDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_FOLDER, GtkFileFolder)) -#define GTK_IS_FILE_FOLDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_FOLDER)) -#define GTK_FILE_FOLDER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GTK_TYPE_FILE_FOLDER, GtkFileFolderIface)) - -struct _GtkFileFolderIface +struct GtkFolder { - GTypeInterface base_iface; - - /* Methods - */ - GtkFileInfo * (*get_info) (GtkFileFolder *folder, - const GtkFilePath *path, - GError **error); - gboolean (*list_children) (GtkFileFolder *folder, - GSList **children, - GError **error); - - /* ??? refresh() ??? */ - - /* Signals - */ - void (*deleted) (GtkFileFolder *monitor); - void (*files_added) (GtkFileFolder *monitor, - GSList *paths); - void (*files_changed) (GtkFileFolder *monitor, - GSList *paths); - void (*files_removed) (GtkFileFolder *monitor, - GSList *paths); - - /* Method / signal */ - gboolean (*is_finished_loading) (GtkFileFolder *folder); - void (*finished_loading) (GtkFileFolder *folder); + GObject parent_object; }; -GType gtk_file_folder_get_type (void) G_GNUC_CONST; -gboolean gtk_file_folder_list_children (GtkFileFolder *folder, - GSList **children, - GError **error); -GtkFileInfo *gtk_file_folder_get_info (GtkFileFolder *folder, - const GtkFilePath *path, - GError **error); - -gboolean gtk_file_folder_is_finished_loading (GtkFileFolder *folder); - - -/* GtkFilePath */ -#define GTK_TYPE_FILE_PATH (gtk_file_path_get_type ()) - -GType gtk_file_path_get_type (void) G_GNUC_CONST; -#ifdef __GNUC__ -#define gtk_file_path_new_dup(str) \ - ({ const gchar *__s = (str); (GtkFilePath *)g_strdup(__s); }) -#define gtk_file_path_new_steal(str) \ - ({ gchar *__s = (str); (GtkFilePath *)__s; }) -#define gtk_file_path_get_string(path) \ - ({ const GtkFilePath *__p = (path); (const gchar *)__p; }) -#define gtk_file_path_free(path) \ - ({ GtkFilePath *__p = (path); g_free (__p); }) -#else /* __GNUC__ */ -#define gtk_file_path_new_dup(str) ((GtkFilePath *)g_strdup(str)) -#define gtk_file_path_new_steal(str) ((GtkFilePath *)(str)) -#define gtk_file_path_get_string(str) ((const gchar *)(str)) -#define gtk_file_path_free(path) g_free (path) -#endif/* __GNUC__ */ - -#define gtk_file_path_copy(path) gtk_file_path_new_dup (gtk_file_path_get_string(path)) -#ifdef G_OS_WIN32 -int _gtk_file_system_win32_path_compare (const gchar *path1, - const gchar *path2); -#define gtk_file_path_compare(path1,path2) \ - _gtk_file_system_win32_path_compare (gtk_file_path_get_string (path1), \ - gtk_file_path_get_string (path2)) -#else -#define gtk_file_path_compare(path1,path2) strcmp (gtk_file_path_get_string (path1), \ - gtk_file_path_get_string (path2)) -#endif - -GSList *gtk_file_paths_sort (GSList *paths); -GSList *gtk_file_paths_copy (GSList *paths); -void gtk_file_paths_free (GSList *paths); - -/* GtkFileSystem modules support */ - -GtkFileSystem *gtk_file_system_create (const char *file_system_name); +typedef void (* GtkFileSystemGetFolderCallback) (GCancellable *cancellable, + GtkFolder *folder, + const GError *error, + gpointer data); +typedef void (* GtkFileSystemGetInfoCallback) (GCancellable *cancellable, + GFileInfo *file_info, + const GError *error, + gpointer data); +typedef void (* GtkFileSystemVolumeMountCallback) (GCancellable *cancellable, + GtkFileSystemVolume *volume, + const GError *error, + gpointer data); + +/* GtkFileSystem methods */ +GType gtk_file_system_get_type (void) G_GNUC_CONST; + +GtkFileSystem * gtk_file_system_new (void); + +GSList * gtk_file_system_list_volumes (GtkFileSystem *file_system); +GSList * gtk_file_system_list_bookmarks (GtkFileSystem *file_system); + +gboolean gtk_file_system_parse (GtkFileSystem *file_system, + GFile *base_file, + const gchar *str, + GFile **folder, + gchar **file_part, + GError **error); + +GCancellable * gtk_file_system_get_folder (GtkFileSystem *file_system, + GFile *file, + const gchar *attributes, + GtkFileSystemGetFolderCallback callback, + gpointer data); +GCancellable * gtk_file_system_get_info (GtkFileSystem *file_system, + GFile *file, + const gchar *attributes, + GtkFileSystemGetInfoCallback callback, + gpointer data); +GCancellable * gtk_file_system_mount_volume (GtkFileSystem *file_system, + GtkFileSystemVolume *volume, + GMountOperation *mount_operation, + GtkFileSystemVolumeMountCallback callback, + gpointer data); +GCancellable * gtk_file_system_mount_enclosing_volume (GtkFileSystem *file_system, + GFile *file, + GMountOperation *mount_operation, + GtkFileSystemVolumeMountCallback callback, + gpointer data); + +gboolean gtk_file_system_insert_bookmark (GtkFileSystem *file_system, + GFile *file, + gint position, + GError **error); +gboolean gtk_file_system_remove_bookmark (GtkFileSystem *file_system, + GFile *file, + GError **error); + +gchar * gtk_file_system_get_bookmark_label (GtkFileSystem *file_system, + GFile *file); +void gtk_file_system_set_bookmark_label (GtkFileSystem *file_system, + GFile *file, + const gchar *label); + +GtkFileSystemVolume * gtk_file_system_get_volume_for_file (GtkFileSystem *file_system, + GFile *file); + +/* GtkFolder functions */ +GSList * gtk_folder_list_children (GtkFolder *folder); +GFileInfo * gtk_folder_get_info (GtkFolder *folder, + GFile *file); + +gboolean gtk_folder_is_finished_loading (GtkFolder *folder); + + +/* GtkFileSystemVolume methods */ +gchar * gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume); +gboolean gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume); +GFile * gtk_file_system_volume_get_root (GtkFileSystemVolume *volume); +GdkPixbuf * gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume, + GtkWidget *widget, + gint icon_size, + GError **error); + +void gtk_file_system_volume_free (GtkFileSystemVolume *volume); + +/* GtkFileSystemBookmark methods */ +void gtk_file_system_bookmark_free (GtkFileSystemBookmark *bookmark); + +/* GFileInfo helper functions */ +GdkPixbuf * gtk_file_info_render_icon (GFileInfo *info, + GtkWidget *widget, + gint icon_size); G_END_DECLS diff --git a/gtk/gtkfilesystemmodel.c b/gtk/gtkfilesystemmodel.c index 11ee1d2fd..4cca6dc94 100644 --- a/gtk/gtkfilesystemmodel.c +++ b/gtk/gtkfilesystemmodel.c @@ -93,7 +93,7 @@ static gboolean drag_source_drag_data_get (GtkTreeDragSource *drag_source, GtkSelectionData *selection_data); static FileModelNode *file_model_node_new (GtkFileSystemModel *model, - const GtkFilePath *path); + GFile *file); static void file_model_node_free (FileModelNode *node); static void file_model_node_ref (FileModelNode *node); static void file_model_node_unref (GtkFileSystemModel *model, @@ -103,7 +103,7 @@ static void file_model_node_idle_clear (FileModelNode *node); static void file_model_node_idle_clear_cancel (FileModelNode *node); static void file_model_node_child_unref (FileModelNode *parent); -static const GtkFileInfo *file_model_node_get_info (GtkFileSystemModel *model, +static GFileInfo * file_model_node_get_info (GtkFileSystemModel *model, FileModelNode *node); static gboolean file_model_node_is_visible (GtkFileSystemModel *model, FileModelNode *node); @@ -112,27 +112,27 @@ static void file_model_node_clear (GtkFileSystemModel *mode static FileModelNode * file_model_node_get_children (GtkFileSystemModel *model, FileModelNode *node); -static void deleted_callback (GtkFileFolder *folder, +static void deleted_callback (GFile *folder, FileModelNode *node); -static void files_added_callback (GtkFileFolder *folder, +static void files_added_callback (GFile *folder, GSList *paths, FileModelNode *node); -static void files_changed_callback (GtkFileFolder *folder, +static void files_changed_callback (GFile *folder, GSList *paths, FileModelNode *node); -static void files_removed_callback (GtkFileFolder *folder, +static void files_removed_callback (GFile *folder, GSList *paths, FileModelNode *node); -static void root_deleted_callback (GtkFileFolder *folder, +static void root_deleted_callback (GFile *folder, GtkFileSystemModel *model); -static void root_files_added_callback (GtkFileFolder *folder, +static void root_files_added_callback (GFile *folder, GSList *paths, GtkFileSystemModel *model); -static void root_files_changed_callback (GtkFileFolder *folder, +static void root_files_changed_callback (GFile *folder, GSList *paths, GtkFileSystemModel *model); -static void root_files_removed_callback (GtkFileFolder *folder, +static void root_files_removed_callback (GFile *folder, GSList *paths, GtkFileSystemModel *model); @@ -206,8 +206,8 @@ gtk_file_system_model_finalize (GObject *object) if (model->root_folder) g_object_unref (model->root_folder); - if (model->root_path) - gtk_file_path_free (model->root_path); + if (model->root_file) + g_object_unref (model->root_file); if (model->file_system) g_object_unref (model->file_system); @@ -220,6 +220,8 @@ gtk_file_system_model_finalize (GObject *object) children = next; } + g_free (model->attributes); + G_OBJECT_CLASS (_gtk_file_system_model_parent_class)->finalize (object); } @@ -229,14 +231,14 @@ gtk_file_system_model_dispose (GObject *object) { GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (object); - if (model->pending_handles) + if (model->pending_cancellables) { GSList *l; - for (l = model->pending_handles; l; l = l->next) - gtk_file_system_cancel_operation (l->data); - g_slist_free (model->pending_handles); - model->pending_handles = NULL; + for (l = model->pending_cancellables; l; l = l->next) + g_cancellable_cancel (l->data); + g_slist_free (model->pending_cancellables); + model->pending_cancellables = NULL; } G_OBJECT_CLASS (_gtk_file_system_model_parent_class)->dispose (object); @@ -279,7 +281,7 @@ gtk_file_system_model_get_column_type (GtkTreeModel *tree_model, switch (index) { case GTK_FILE_SYSTEM_MODEL_INFO: - return GTK_TYPE_FILE_INFO; + return G_TYPE_FILE_INFO; case GTK_FILE_SYSTEM_MODEL_DISPLAY_NAME: return G_TYPE_STRING; default: @@ -358,7 +360,7 @@ gtk_file_system_model_get_value (GtkTreeModel *tree_model, { GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model); FileModelNode *node = iter->user_data; - const GtkFileInfo *info; + GFileInfo *info; switch (column) { @@ -368,8 +370,7 @@ gtk_file_system_model_get_value (GtkTreeModel *tree_model, else info = file_model_node_get_info (model, node); - g_value_init (value, GTK_TYPE_FILE_INFO); - g_value_set_boxed (value, info); + g_value_set_object (value, info); break; case GTK_FILE_SYSTEM_MODEL_DISPLAY_NAME: { @@ -379,9 +380,9 @@ gtk_file_system_model_get_value (GtkTreeModel *tree_model, g_value_set_static_string (value, ""); else { - const GtkFileInfo *info = file_model_node_get_info (model, node); + GFileInfo *info = file_model_node_get_info (model, node); - g_value_set_string (value, gtk_file_info_get_display_name (info)); + g_value_set_string (value, g_file_info_get_display_name (info)); } } break; @@ -442,8 +443,8 @@ gtk_file_system_model_iter_has_child (GtkTreeModel *tree_model, return FALSE; else { - const GtkFileInfo *info = file_model_node_get_info (model, node); - return gtk_file_info_get_is_folder (info); + GFileInfo *info = file_model_node_get_info (model, node); + return (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); } } @@ -565,7 +566,7 @@ drag_source_drag_data_get (GtkTreeDragSource *drag_source, { GtkFileSystemModel *model; GtkTreeIter iter; - const GtkFilePath *file_path; + GFile *file; char *uris[2]; model = GTK_FILE_SYSTEM_MODEL (drag_source); @@ -573,10 +574,10 @@ drag_source_drag_data_get (GtkTreeDragSource *drag_source, if (!gtk_file_system_model_get_iter (GTK_TREE_MODEL (model), &iter, path)) return FALSE; - file_path = _gtk_file_system_model_get_path (model, &iter); - g_assert (file_path != NULL); + file = _gtk_file_system_model_get_file (model, &iter); + g_assert (file != NULL); - uris[0] = gtk_file_system_path_to_uri (model->file_system, file_path); + uris[0] = g_file_get_uri (file); uris[1] = NULL; gtk_selection_data_set_uris (selection_data, uris); @@ -588,43 +589,36 @@ drag_source_drag_data_get (GtkTreeDragSource *drag_source, /* Callback used when the root folder finished loading */ static void -root_folder_finished_loading_cb (GtkFileFolder *folder, +root_folder_finished_loading_cb (GFile *folder, GtkFileSystemModel *model) { g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0); } static void -got_root_folder_cb (GtkFileSystemHandle *handle, - GtkFileFolder *folder, - const GError *error, - gpointer data) +got_root_folder_cb (GCancellable *cancellable, + GtkFolder *folder, + const GError *error, + gpointer data) { - GSList *roots = NULL; - GSList *tmp_list; - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GtkFileSystemModel *model = data; + GSList *tmp_list; - tmp_list = g_slist_find (model->pending_handles, handle); + tmp_list = g_slist_find (model->pending_cancellables, cancellable); if (!tmp_list) goto out; - model->pending_handles = g_slist_delete_link (model->pending_handles, - tmp_list); + model->pending_cancellables = g_slist_delete_link (model->pending_cancellables, + tmp_list); if (cancelled || !folder) goto out; - model->root_folder = folder; - - if (gtk_file_folder_is_finished_loading (model->root_folder)) - g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0); - else - g_signal_connect_object (model->root_folder, "finished-loading", - G_CALLBACK (root_folder_finished_loading_cb), model, 0); - - gtk_file_folder_list_children (model->root_folder, &roots, NULL); + model->root_folder = g_object_ref (folder); + g_signal_connect_object (model->root_folder, "finished-loading", + G_CALLBACK (root_folder_finished_loading_cb), model, 0); g_signal_connect_object (model->root_folder, "deleted", G_CALLBACK (root_deleted_callback), model, 0); g_signal_connect_object (model->root_folder, "files-added", @@ -634,54 +628,26 @@ got_root_folder_cb (GtkFileSystemHandle *handle, g_signal_connect_object (model->root_folder, "files-removed", G_CALLBACK (root_files_removed_callback), model, 0); - roots = gtk_file_paths_sort (roots); - - for (tmp_list = roots; tmp_list; tmp_list = tmp_list->next) - { - FileModelNode *node = file_model_node_new (model, tmp_list->data); - gtk_file_path_free (tmp_list->data); - node->is_visible = file_model_node_is_visible (model, node); - node->next = model->roots; - node->depth = 0; - model->roots = node; - - if (node->is_visible) - { - GtkTreeIter iter; - GtkTreePath *path; - - iter.user_data = node; - path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); - gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter); - gtk_tree_path_free (path); - } - } - g_slist_free (roots); - out: g_object_unref (model); - g_object_unref (handle); + g_object_unref (cancellable); } /** * _gtk_file_system_model_new: * @file_system: an object implementing #GtkFileSystem - * @root_path: the path of root of the file system to display - * @max_depth: the maximum depth from the children of @root_path + * @root_file: the root file path to show. + * @max_depth: the maximum depth from the children of @root_file * or the roots of the file system to display in * the file selector). A depth of 0 displays - * only the immediate children of @root_path, + * only the immediate children of @root_file, * or the roots of the filesystem. -1 for no * maximum depth. - * @types: a bitmask indicating the types of information - * that is desired about the files. This will - * determine what information is returned by - * _gtk_file_system_model_get_info(). * @error: location to store error, or %NULL. * * Creates a new #GtkFileSystemModel object. The #GtkFileSystemModel * object wraps a #GtkFileSystem interface as a #GtkTreeModel. - * Using the @root_path and @max_depth parameters, the tree model + * Using the @root_file and @max_depth parameters, the tree model * can be restricted to a subportion of the entire file system. * * Return value: the newly created #GtkFileSystemModel object, or NULL if there @@ -689,22 +655,18 @@ out: **/ GtkFileSystemModel * _gtk_file_system_model_new (GtkFileSystem *file_system, - const GtkFilePath *root_path, + GFile *root_file, gint max_depth, - GtkFileInfoType types, + const gchar *attributes, GError **error) { GtkFileSystemModel *model; - GtkFileSystemHandle *handle; + GCancellable *cancellable; g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL); - g_return_val_if_fail (root_path != NULL, NULL); + g_return_val_if_fail (G_IS_FILE (root_file), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); - /* First, start loading the root folder */ - - types |= GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_IS_HIDDEN; - /* Then, actually create the model and the root nodes */ model = g_object_new (GTK_TYPE_FILE_SYSTEM_MODEL, NULL); @@ -714,16 +676,17 @@ _gtk_file_system_model_new (GtkFileSystem *file_system, else model->max_depth = MIN (max_depth, G_MAXUSHORT); - model->types = types; + model->attributes = g_strdup (attributes); model->root_folder = NULL; - model->root_path = gtk_file_path_copy (root_path); + model->root_file = g_object_ref (root_file); model->roots = NULL; - handle = gtk_file_system_get_folder (file_system, root_path, types, - got_root_folder_cb, - g_object_ref (model)); - if (!handle) + cancellable = gtk_file_system_get_folder (file_system, root_file, + attributes, + got_root_folder_cb, + g_object_ref (model)); + if (!cancellable) { /* In this case got_root_folder_cb() will never be called, so we * need to unref model twice. @@ -739,7 +702,7 @@ _gtk_file_system_model_new (GtkFileSystem *file_system, return NULL; } - model->pending_handles = g_slist_append (model->pending_handles, handle); + model->pending_cancellables = g_slist_append (model->pending_cancellables, cancellable); return model; } @@ -885,12 +848,12 @@ _gtk_file_system_model_set_show_files (GtkFileSystemModel *model, * @model: a #GtkFileSystemModel * @iter: a #GtkTreeIter pointing to a row of @model * - * Gets the #GtkFileInfo structure for a particular row + * Gets the #GFileInfo structure for a particular row * of @model. The information included in this structure * is determined by the @types parameter to * _gtk_file_system_model_new(). * - * Return value: a #GtkFileInfo structure. This structure + * Return value: a #GFileInfo structure. This structure * is owned by @model and must not be modified or freed. * If you want to save the information for later use, * you must make a copy, since the structure may be @@ -899,7 +862,7 @@ _gtk_file_system_model_set_show_files (GtkFileSystemModel *model, * corresponds to the row that this function returned, the * return value will be NULL. **/ -const GtkFileInfo * +GFileInfo * _gtk_file_system_model_get_info (GtkFileSystemModel *model, GtkTreeIter *iter) { @@ -913,19 +876,19 @@ _gtk_file_system_model_get_info (GtkFileSystemModel *model, } /** - * _gtk_file_system_model_get_path: + * _gtk_file_system_model_get_file: * @model: a #GtkFileSystemModel * @iter: a #GtkTreeIter pointing to a row of @model * * Gets the path for a particular row in @model. * - * Return value: the path. This string is owned by @model and + * Return value: the file. This object is owned by @model and * or freed. If you want to save the path for later use, - * you must make a copy, since the string may be freed + * you must take a ref, since the object may be freed * on later changes to the file system. **/ -const GtkFilePath * -_gtk_file_system_model_get_path (GtkFileSystemModel *model, +GFile * +_gtk_file_system_model_get_file (GtkFileSystemModel *model, GtkTreeIter *iter) { FileModelNode *node = iter->user_data; @@ -934,9 +897,9 @@ _gtk_file_system_model_get_path (GtkFileSystemModel *model, return NULL; if (node->is_dummy) - return node->parent->path; + return node->parent->file; else - return node->path; + return node->file; } static void @@ -951,7 +914,7 @@ unref_node_and_parents (GtkFileSystemModel *model, static FileModelNode * find_child_node (GtkFileSystemModel *model, FileModelNode *parent_node, - const GtkFilePath *path) + GFile *file) { FileModelNode *children; @@ -963,8 +926,8 @@ find_child_node (GtkFileSystemModel *model, while (children) { if (children->is_visible && - children->path && - gtk_file_path_compare (children->path, path) == 0) + children->file && + g_file_equal (children->file, file)) return children; children = children->next; @@ -1002,7 +965,7 @@ struct RefPathData GtkFileSystemModel *model; FileModelNode *node; FileModelNode *parent_node; - GSList *paths; + GSList *files; GSList *cleanups; GtkFileSystemModelPathFunc func; gpointer user_data; @@ -1010,18 +973,18 @@ struct RefPathData /* FIXME: maybe we have to wait on finished-loading? */ static void -ref_path_cb (GtkFileSystemHandle *handle, - GtkFileFolder *folder, - const GError *error, - gpointer data) +ref_path_cb (GCancellable *cancellable, + GtkFolder *folder, + const GError *error, + gpointer data) { struct RefPathData *info = data; - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); - if (!g_slist_find (info->model->pending_handles, handle)) + if (!g_slist_find (info->model->pending_cancellables, cancellable)) goto out; - info->model->pending_handles = g_slist_remove (info->model->pending_handles, handle); + info->model->pending_cancellables = g_slist_remove (info->model->pending_cancellables, cancellable); /* Note that !folder means that the child node was already * found, without using get_folder. @@ -1031,8 +994,8 @@ ref_path_cb (GtkFileSystemHandle *handle, if (folder) info->cleanups = g_slist_prepend (info->cleanups, folder); - else if (g_slist_length (info->paths) == 1 - && gtk_file_path_compare (info->node->path, info->paths->data) == 0) + else if (g_slist_length (info->files) == 1 + && g_file_equal (info->node->file, info->files->data)) { /* Done, now call the function */ if (info->node) @@ -1051,7 +1014,7 @@ ref_path_cb (GtkFileSystemHandle *handle, goto out; } - info->node = find_child_node (info->model, info->parent_node, info->paths->data); + info->node = find_child_node (info->model, info->parent_node, info->files->data); if (info->node) file_model_node_ref (info->node); else @@ -1059,10 +1022,10 @@ ref_path_cb (GtkFileSystemHandle *handle, goto out; } - gtk_file_path_free (info->paths->data); - info->paths = g_slist_remove (info->paths, info->paths->data); + g_object_unref (info->files); + info->files = g_slist_remove (info->files, info->files->data); - if (g_slist_length (info->paths) < 1) + if (g_slist_length (info->files) < 1) { /* Done, now call the function */ if (info->node) @@ -1086,19 +1049,19 @@ ref_path_cb (GtkFileSystemHandle *handle, if (info->parent_node->loaded) { - info->node = find_child_node (info->model, info->parent_node, info->paths->data); + info->node = find_child_node (info->model, info->parent_node, info->files->data); ref_path_cb (NULL, NULL, NULL, info); } else { - GtkFileSystemHandle *handle; - - handle = gtk_file_system_get_folder (info->model->file_system, - info->paths->data, - info->model->types, - ref_path_cb, data); - info->model->pending_handles = - g_slist_append (info->model->pending_handles, handle); + GCancellable *cancellable; + + cancellable = gtk_file_system_get_folder (info->model->file_system, + info->files->data, + info->model->attributes, + ref_path_cb, data); + info->model->pending_cancellables = + g_slist_append (info->model->pending_cancellables, cancellable); } return; @@ -1107,13 +1070,13 @@ ref_path_cb (GtkFileSystemHandle *handle, out: if (info->node) unref_node_and_parents (info->model, info->node); - gtk_file_paths_free (info->paths); + g_object_unref (info->files); g_slist_foreach (info->cleanups, (GFunc)g_object_unref, NULL); g_slist_free (info->cleanups); g_object_unref (info->model); g_free (info); - g_object_unref (handle); + g_object_unref (cancellable); } /** @@ -1141,49 +1104,54 @@ out: */ void _gtk_file_system_model_path_do (GtkFileSystemModel *model, - const GtkFilePath *path, + GFile *file, GtkFileSystemModelPathFunc func, gpointer user_data) { - GtkFilePath *parent_path; - GSList *paths = NULL; + GFile *parent_file; + GSList *files = NULL; FileModelNode *node; struct RefPathData *info; - if (gtk_file_path_compare (path, model->root_path) == 0 || - !gtk_file_system_get_parent (model->file_system, path, &parent_path, NULL) || - parent_path == NULL) + if (g_file_equal (file, model->root_file)) return; - paths = g_slist_prepend (paths, gtk_file_path_copy (path)); - while (gtk_file_path_compare (parent_path, model->root_path) != 0) + parent_file = g_file_get_parent (file); + + if (!parent_file) + return; + + files = g_slist_prepend (files, g_object_ref (file)); + while (!g_file_equal (parent_file, model->root_file)) { - paths = g_slist_prepend (paths, parent_path); - if (!gtk_file_system_get_parent (model->file_system, parent_path, &parent_path, NULL) || - parent_path == NULL) + files = g_slist_prepend (files, parent_file); + parent_file = g_file_get_parent (parent_file); + if (!parent_file) { - gtk_file_paths_free (paths); + g_slist_foreach (files, (GFunc) g_object_unref, NULL); + g_slist_free (files); return; } } - if (g_slist_length (paths) < 1) + if (g_slist_length (files) < 1) return; /* Now we have all paths, except the root path */ - node = find_child_node (model, NULL, paths->data); + node = find_child_node (model, NULL, files->data); if (!node) { - gtk_file_paths_free (paths); + g_slist_foreach (files, (GFunc) g_object_unref, NULL); + g_slist_free (files); return; } file_model_node_ref (node); - gtk_file_path_free (paths->data); - paths = g_slist_remove (paths, paths->data); + g_object_unref (files->data); + files = g_slist_remove (files, files->data); - if (g_slist_length (paths) < 1) + if (g_slist_length (files) < 1) { /* Done, now call the function */ if (node) @@ -1203,7 +1171,7 @@ _gtk_file_system_model_path_do (GtkFileSystemModel *model, else { info = g_new0 (struct RefPathData, 1); - info->paths = paths; + info->files = files; info->model = g_object_ref (model); info->func = func; info->user_data = user_data; @@ -1212,17 +1180,18 @@ _gtk_file_system_model_path_do (GtkFileSystemModel *model, if (info->node->loaded) { info->parent_node = info->node; - info->node = find_child_node (model, info->parent_node, info->paths->data); + info->node = find_child_node (model, info->parent_node, info->files->data); ref_path_cb (NULL, NULL, NULL, info); } else { - GtkFileSystemHandle *handle; + GCancellable *cancellable; - handle = gtk_file_system_get_folder (model->file_system, - paths->data, model->types, - ref_path_cb, info); - model->pending_handles = g_slist_append (model->pending_handles, handle); + cancellable = gtk_file_system_get_folder (model->file_system, + files->data, + model->attributes, + ref_path_cb, info); + model->pending_cancellables = g_slist_append (model->pending_cancellables, cancellable); } } } @@ -1294,12 +1263,12 @@ _gtk_file_system_model_remove_editable (GtkFileSystemModel *model) static FileModelNode * file_model_node_new (GtkFileSystemModel *model, - const GtkFilePath *path) + GFile *file) { FileModelNode *node = g_new0 (FileModelNode, 1); node->model = model; - node->path = path ? gtk_file_path_copy (path) : NULL; + node->file = file ? g_object_ref (file) : NULL; return node; } @@ -1309,16 +1278,16 @@ file_model_node_free (FileModelNode *node) { file_model_node_clear (node->model, node); - if (node->path) - gtk_file_path_free (node->path); + if (node->file) + g_object_unref (node->file); if (node->info) - gtk_file_info_free (node->info); + g_object_unref (node->info); g_free (node); } -static const GtkFileInfo * +static GFileInfo * file_model_node_get_info (GtkFileSystemModel *model, FileModelNode *node) { @@ -1326,14 +1295,13 @@ file_model_node_get_info (GtkFileSystemModel *model, { if (node->is_dummy) { - node->info = gtk_file_info_new (); - gtk_file_info_set_display_name (node->info, _("(Empty)")); + node->info = g_file_info_new (); + g_file_info_set_display_name (node->info, _("(Empty)")); } else if (node->parent || model->root_folder) { - node->info = gtk_file_folder_get_info (node->parent ? node->parent->folder : model->root_folder, - node->path, - NULL); /* NULL-GError */ + node->info = gtk_folder_get_info ((node->parent != NULL) ? node->parent->folder : model->root_folder, + node->file); } else g_assert_not_reached (); @@ -1350,7 +1318,8 @@ file_model_node_is_visible (GtkFileSystemModel *model, !model->show_hidden || model->filter_func) { - const GtkFileInfo *info = file_model_node_get_info (model, node); + GFileInfo *info = file_model_node_get_info (model, node); + gboolean is_folder; if (!info) { @@ -1359,15 +1328,17 @@ file_model_node_is_visible (GtkFileSystemModel *model, return FALSE; } + is_folder = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); + if (model->show_folders != model->show_files && - model->show_folders != gtk_file_info_get_is_folder (info)) + model->show_folders != is_folder) return FALSE; - if (!model->show_hidden && gtk_file_info_get_is_hidden (info)) + if (!model->show_hidden && g_file_info_get_is_hidden (info)) return FALSE; if (model->filter_func && - !model->filter_func (model, node->path, info, model->filter_data)) + !model->filter_func (model, node->file, info, model->filter_data)) return FALSE; } @@ -1400,7 +1371,7 @@ file_model_node_clear (GtkFileSystemModel *model, /* Unreffing node->folder may cause roots_changed, * so we need to be careful about ordering. */ - GtkFileFolder *folder = node->folder; + GtkFolder *folder = node->folder; node->folder = NULL; g_signal_handlers_disconnect_by_func (folder, G_CALLBACK (deleted_callback), node); @@ -1504,22 +1475,22 @@ struct GetChildrenData }; static void -get_children_get_folder_cb (GtkFileSystemHandle *handle, - GtkFileFolder *folder, - const GError *error, - gpointer callback_data) +get_children_get_folder_cb (GCancellable *cancellable, + GtkFolder *folder, + const GError *error, + gpointer callback_data) { - GSList *child_paths, *tmp_list; - gboolean has_children = FALSE; - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); struct GetChildrenData *data = callback_data; + FileModelNode *child_node; + GSList *tmp_list; - tmp_list = g_slist_find (data->model->pending_handles, handle); + tmp_list = g_slist_find (data->model->pending_cancellables, cancellable); if (!tmp_list) goto out; - data->model->pending_handles = g_slist_delete_link (data->model->pending_handles, tmp_list); + data->model->pending_cancellables = g_slist_delete_link (data->model->pending_cancellables, tmp_list); if (cancelled || !folder) { @@ -1538,37 +1509,6 @@ get_children_get_folder_cb (GtkFileSystemHandle *handle, data->node->folder = folder; data->node->load_pending = FALSE; - if (gtk_file_folder_list_children (folder, &child_paths, NULL)) /* NULL-GError */ - { - child_paths = gtk_file_paths_sort (child_paths); - - for (tmp_list = child_paths; tmp_list; tmp_list = tmp_list->next) - { - FileModelNode *child_node = file_model_node_new (data->model, tmp_list->data); - gtk_file_path_free (tmp_list->data); - child_node->next = data->node->children; - child_node->parent = data->node; - child_node->depth = data->node->depth + 1; - child_node->is_visible = file_model_node_is_visible (data->model, child_node); - - if (child_node->is_visible) - { - GtkTreeIter iter; - GtkTreePath *path; - - has_children = TRUE; - - iter.user_data = child_node; - path = gtk_tree_model_get_path (GTK_TREE_MODEL (data->model), &iter); - gtk_tree_model_row_inserted (GTK_TREE_MODEL (data->model), path, &iter); - gtk_tree_path_free (path); - } - - data->node->children = child_node; - } - g_slist_free (child_paths); - } - g_signal_connect (data->node->folder, "deleted", G_CALLBACK (deleted_callback), data->node); g_signal_connect (data->node->folder, "files-added", @@ -1580,19 +1520,16 @@ get_children_get_folder_cb (GtkFileSystemHandle *handle, data->node->loaded = TRUE; - if (!has_children) - { - /* The hard case ... we claimed this folder had children, but actually - * it didn't. We have to add a dummy child, possibly to remove later. - */ - FileModelNode *child_node = file_model_node_new (data->model, NULL); - child_node->is_visible = TRUE; - child_node->parent = data->node; - child_node->is_dummy = TRUE; + /* We claimed this folder had children, so we + * have to add a dummy child, possibly to remove later. + */ + child_node = file_model_node_new (data->model, NULL); + child_node->is_visible = TRUE; + child_node->parent = data->node; + child_node->is_dummy = TRUE; - data->node->children = child_node; - data->node->has_dummy = TRUE; - } + data->node->children = child_node; + data->node->has_dummy = TRUE; g_object_set_data (G_OBJECT (data->node->folder), I_("model-node"), data->node); @@ -1600,7 +1537,7 @@ out: g_object_unref (data->model); g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static FileModelNode * @@ -1612,65 +1549,91 @@ file_model_node_get_children (GtkFileSystemModel *model, if (!node->loaded && !node->load_pending) { - const GtkFileInfo *info = file_model_node_get_info (model, node); + GFileInfo *info = file_model_node_get_info (model, node); gboolean has_children = FALSE; - gboolean is_folder = node->depth < model->max_depth && gtk_file_info_get_is_folder (info); + gboolean is_folder = (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); file_model_node_idle_clear_cancel (node); - if (is_folder) + if (node->depth < model->max_depth && is_folder) { struct GetChildrenData *data; - GtkFileSystemHandle *handle; + GCancellable *cancellable; data = g_new (struct GetChildrenData, 1); data->model = g_object_ref (model); data->node = node; - handle = + cancellable = gtk_file_system_get_folder (model->file_system, - node->path, - model->types, + node->file, + model->attributes, get_children_get_folder_cb, data); - model->pending_handles = g_slist_append (model->pending_handles, handle); + model->pending_cancellables = g_slist_append (model->pending_cancellables, cancellable); node->load_pending = TRUE; - } - if (is_folder && !has_children) - { - /* The hard case ... we claimed this folder had children, but actually - * it didn't. We have to add a dummy child, possibly to remove later. - */ - FileModelNode *child_node = file_model_node_new (model, NULL); - child_node->is_visible = TRUE; - child_node->parent = node; - child_node->is_dummy = TRUE; - - node->children = child_node; - node->has_dummy = TRUE; + if (!has_children) + { + /* The hard case ... we claimed this folder had children, but actually + * it didn't. We have to add a dummy child, possibly to remove later. + */ + FileModelNode *child_node = file_model_node_new (model, NULL); + child_node->is_visible = TRUE; + child_node->parent = node; + child_node->is_dummy = TRUE; + + node->children = child_node; + node->has_dummy = TRUE; + } } } return node->children; } +static gint +file_compare_func (GFile *file1, + GFile *file2) +{ + gchar *uri1, *uri2; + gint result; + + uri1 = g_file_get_uri (file1); + uri2 = g_file_get_uri (file2); + + result = g_strcmp0 (uri1, uri2); + + g_free (uri1); + g_free (uri2); + + return result; +} + +static GSList * +sort_file_list (GSList *list) +{ + GSList *copy; + + copy = g_slist_copy (list); + return g_slist_sort (copy, (GCompareFunc) file_compare_func); +} + static void do_files_added (GtkFileSystemModel *model, FileModelNode *parent_node, - GSList *paths) + GSList *files) { GtkTreeModel *tree_model = GTK_TREE_MODEL (model); FileModelNode *children; FileModelNode *prev = NULL; GtkTreeIter iter; GtkTreePath *path; - GSList *sorted_paths; - GSList *tmp_list; + GSList *sorted_files, *tmp_list; + + sorted_files = sort_file_list (files); - sorted_paths = gtk_file_paths_sort (g_slist_copy (paths)); - if (parent_node) { iter.user_data = parent_node; @@ -1692,12 +1655,12 @@ do_files_added (GtkFileSystemModel *model, gtk_tree_path_next (path); } - for (tmp_list = sorted_paths; tmp_list; tmp_list = tmp_list->next) + for (tmp_list = sorted_files; tmp_list; tmp_list = tmp_list->next) { - const GtkFilePath *file_path = tmp_list->data; - + GFile *file = tmp_list->data; + while (children && - (!children->path || gtk_file_path_compare (children->path, file_path) < 0)) + (!children->file || !g_file_equal (children->file, file))) { prev = children; if (children->is_visible) @@ -1707,7 +1670,7 @@ do_files_added (GtkFileSystemModel *model, } if (children && - children->path && gtk_file_path_compare (children->path, file_path) == 0) + children->file && g_file_equal (children->file, file)) { /* Shouldn't happen */ } @@ -1715,7 +1678,7 @@ do_files_added (GtkFileSystemModel *model, { FileModelNode *new; - new = file_model_node_new (model, file_path); + new = file_model_node_new (model, file); if (children) new->next = children; @@ -1772,23 +1735,23 @@ do_files_added (GtkFileSystemModel *model, } gtk_tree_path_free (path); - g_slist_free (sorted_paths); + g_slist_free (sorted_files); } static void do_files_changed (GtkFileSystemModel *model, FileModelNode *parent_node, - GSList *paths) + GSList *files) { GtkTreeModel *tree_model = GTK_TREE_MODEL (model); FileModelNode *children; GtkTreeIter iter; GtkTreePath *path; - GSList *sorted_paths; + GSList *sorted_files; GSList *tmp_list; - sorted_paths = gtk_file_paths_sort (g_slist_copy (paths)); - + sorted_files = sort_file_list (files); + if (parent_node) { iter.user_data = parent_node; @@ -1809,12 +1772,12 @@ do_files_changed (GtkFileSystemModel *model, gtk_tree_path_next (path); } - for (tmp_list = sorted_paths; tmp_list; tmp_list = tmp_list->next) + for (tmp_list = sorted_files; tmp_list; tmp_list = tmp_list->next) { - const GtkFilePath *file_path = tmp_list->data; - + GFile *file = tmp_list->data; + while (children && - (!children->path || gtk_file_path_compare (children->path, file_path) < 0)) + (!children->file || !g_file_equal (children->file, file))) { if (children->is_visible) gtk_tree_path_next (path); @@ -1823,7 +1786,7 @@ do_files_changed (GtkFileSystemModel *model, } if (children && - children->path && gtk_file_path_compare (children->path, file_path) == 0) + children->file && g_file_equal (children->file, file)) { gtk_tree_model_row_changed (tree_model, path, &iter); } @@ -1834,26 +1797,26 @@ do_files_changed (GtkFileSystemModel *model, } gtk_tree_path_free (path); - g_slist_free (sorted_paths); + g_slist_free (sorted_files); } static void do_files_removed (GtkFileSystemModel *model, FileModelNode *parent_node, - GSList *paths) + GSList *files) { GtkTreeModel *tree_model = GTK_TREE_MODEL (model); FileModelNode *children; FileModelNode *prev = NULL; GtkTreeIter iter; GtkTreePath *path; - GSList *sorted_paths; + GSList *sorted_files; GSList *tmp_list; FileModelNode *tmp_child; gint n_visible; - sorted_paths = gtk_file_paths_sort (g_slist_copy (paths)); - + sorted_files = sort_file_list (files); + if (parent_node) { iter.user_data = parent_node; @@ -1885,12 +1848,12 @@ do_files_removed (GtkFileSystemModel *model, gtk_tree_path_next (path); } - for (tmp_list = sorted_paths; tmp_list; tmp_list = tmp_list->next) + for (tmp_list = sorted_files; tmp_list; tmp_list = tmp_list->next) { - const GtkFilePath *file_path = tmp_list->data; - + GFile *file = tmp_list->data; + while (children && - (!children->path || gtk_file_path_compare (children->path, file_path) < 0)) + (!children->file || !g_file_equal (children->file, file))) { prev = children; if (children->is_visible) @@ -1900,7 +1863,7 @@ do_files_removed (GtkFileSystemModel *model, } if (children && - children->path && gtk_file_path_compare (children->path, file_path) == 0) + children->file && g_file_equal (children->file, file)) { FileModelNode *next = children->next; @@ -1948,65 +1911,65 @@ do_files_removed (GtkFileSystemModel *model, } gtk_tree_path_free (path); - g_slist_free (sorted_paths); + g_slist_free (sorted_files); } static void -deleted_callback (GtkFileFolder *folder, - FileModelNode *node) +deleted_callback (GFile *folder, + FileModelNode *node) { } static void -files_added_callback (GtkFileFolder *folder, - GSList *paths, - FileModelNode *node) +files_added_callback (GFile *folder, + GSList *files, + FileModelNode *node) { - do_files_added (node->model, node, paths); + do_files_added (node->model, node, files); } static void -files_changed_callback (GtkFileFolder *folder, - GSList *paths, - FileModelNode *node) +files_changed_callback (GFile *folder, + GSList *files, + FileModelNode *node) { - do_files_changed (node->model, node, paths); + do_files_changed (node->model, node, files); } static void -files_removed_callback (GtkFileFolder *folder, - GSList *paths, - FileModelNode *node) +files_removed_callback (GFile *folder, + GSList *files, + FileModelNode *node) { - do_files_removed (node->model, node, paths); + do_files_removed (node->model, node, files); } static void -root_deleted_callback (GtkFileFolder *folder, +root_deleted_callback (GFile *folder, GtkFileSystemModel *model) { } static void -root_files_added_callback (GtkFileFolder *folder, - GSList *paths, +root_files_added_callback (GFile *folder, + GSList *files, GtkFileSystemModel *model) { - do_files_added (model, NULL, paths); + do_files_added (model, NULL, files); } static void -root_files_changed_callback (GtkFileFolder *folder, - GSList *paths, +root_files_changed_callback (GFile *folder, + GSList *files, GtkFileSystemModel *model) { - do_files_changed (model, NULL, paths); + do_files_changed (model, NULL, files); } static void -root_files_removed_callback (GtkFileFolder *folder, - GSList *paths, +root_files_removed_callback (GFile *folder, + GSList *files, GtkFileSystemModel *model) { - do_files_removed (model, NULL, paths); + do_files_removed (model, NULL, files); } diff --git a/gtk/gtkfilesystemmodel.h b/gtk/gtkfilesystemmodel.h index c2fa493db..664aaf2b3 100644 --- a/gtk/gtkfilesystemmodel.h +++ b/gtk/gtkfilesystemmodel.h @@ -42,13 +42,13 @@ typedef enum { } GtkFileSystemModelColumns; GtkFileSystemModel *_gtk_file_system_model_new (GtkFileSystem *file_system, - const GtkFilePath *root_path, + GFile *root_file, gint max_depth, - GtkFileInfoType types, + const gchar *attributes, GError **error); -const GtkFileInfo * _gtk_file_system_model_get_info (GtkFileSystemModel *model, +GFileInfo * _gtk_file_system_model_get_info (GtkFileSystemModel *model, GtkTreeIter *iter); -const GtkFilePath * _gtk_file_system_model_get_path (GtkFileSystemModel *model, +GFile * _gtk_file_system_model_get_file (GtkFileSystemModel *model, GtkTreeIter *iter); void _gtk_file_system_model_set_show_hidden (GtkFileSystemModel *model, gboolean show_hidden); @@ -58,8 +58,8 @@ void _gtk_file_system_model_set_show_files (GtkFileSystemModel gboolean show_files); typedef gboolean (*GtkFileSystemModelFilter) (GtkFileSystemModel *model, - GtkFilePath *path, - const GtkFileInfo *info, + GFile *file, + GFileInfo *info, gpointer user_data); void _gtk_file_system_model_set_filter (GtkFileSystemModel *model, @@ -72,7 +72,7 @@ typedef void (*GtkFileSystemModelPathFunc) (GtkFileSystemModel *model, gpointer user_data); void _gtk_file_system_model_path_do (GtkFileSystemModel *model, - const GtkFilePath *path, + GFile *file, GtkFileSystemModelPathFunc func, gpointer user_data); diff --git a/gtk/gtkfilesystemunix.c b/gtk/gtkfilesystemunix.c deleted file mode 100644 index 31387cbf7..000000000 --- a/gtk/gtkfilesystemunix.c +++ /dev/null @@ -1,2730 +0,0 @@ -/* GTK - The GIMP Toolkit - * gtkfilesystemunix.c: Default implementation of GtkFileSystem for UNIX-like systems - * Copyright (C) 2003, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* #define this if you want the program to crash when a file system gets - * finalized while async handles are still outstanding. - */ -#undef HANDLE_ME_HARDER - -#include - -#include "gtkfilesystem.h" -#include "gtkfilesystemunix.h" -#include "gtkicontheme.h" -#include "gtkintl.h" -#include "gtkstock.h" -#include "gtkalias.h" - -#define XDG_PREFIX _gtk_xdg -#include "xdgmime/xdgmime.h" - -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include - -#define BOOKMARKS_FILENAME ".gtk-bookmarks" - -#define HIDDEN_FILENAME ".hidden" - -#define FOLDER_CACHE_LIFETIME 2 /* seconds */ - -typedef struct _GtkFileSystemUnixClass GtkFileSystemUnixClass; - -#define GTK_FILE_SYSTEM_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SYSTEM_UNIX, GtkFileSystemUnixClass)) -#define GTK_IS_FILE_SYSTEM_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SYSTEM_UNIX)) -#define GTK_FILE_SYSTEM_UNIX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_SYSTEM_UNIX, GtkFileSystemUnixClass)) - -struct _GtkFileSystemUnixClass -{ - GObjectClass parent_class; -}; - -struct _GtkFileSystemUnix -{ - GObject parent_instance; - - GHashTable *folder_hash; - - /* For /afs and /net */ - struct stat afs_statbuf; - struct stat net_statbuf; - - GHashTable *handles; - - guint execute_callbacks_idle_id; - GSList *callbacks; - - guint have_afs : 1; - guint have_net : 1; -}; - -/* Icon type, supplemented by MIME type - */ -typedef enum { - ICON_UNDECIDED, /* Only used while we have not yet computed the icon in a struct stat_info_entry */ - ICON_NONE, /* "Could not compute the icon type" */ - ICON_REGULAR, /* Use mime type for icon */ - ICON_BLOCK_DEVICE, - ICON_BROKEN_SYMBOLIC_LINK, - ICON_CHARACTER_DEVICE, - ICON_DIRECTORY, - ICON_EXECUTABLE, - ICON_FIFO, - ICON_SOCKET -} IconType; - - -#define GTK_TYPE_FILE_FOLDER_UNIX (_gtk_file_folder_unix_get_type ()) -#define GTK_FILE_FOLDER_UNIX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_FOLDER_UNIX, GtkFileFolderUnix)) -#define GTK_IS_FILE_FOLDER_UNIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_FOLDER_UNIX)) -#define GTK_FILE_FOLDER_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_FOLDER_UNIX, GtkFileFolderUnixClass)) -#define GTK_IS_FILE_FOLDER_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_FOLDER_UNIX)) -#define GTK_FILE_FOLDER_UNIX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_FOLDER_UNIX, GtkFileFolderUnixClass)) - -typedef struct _GtkFileFolderUnix GtkFileFolderUnix; -typedef struct _GtkFileFolderUnixClass GtkFileFolderUnixClass; - -struct _GtkFileFolderUnixClass -{ - GObjectClass parent_class; -}; - -struct _GtkFileFolderUnix -{ - GObject parent_instance; - - GtkFileSystemUnix *system_unix; - GtkFileInfoType types; - gchar *filename; - GHashTable *stat_info; - guint load_folder_id; - guint have_stat : 1; - guint have_mime_type : 1; - guint is_network_dir : 1; - guint have_hidden : 1; - guint is_finished_loading : 1; - time_t asof; -}; - -struct stat_info_entry { - struct stat statbuf; - char *mime_type; - IconType icon_type; - gboolean hidden; -}; - -static const GtkFileInfoType STAT_NEEDED_MASK = (GTK_FILE_INFO_IS_FOLDER | - GTK_FILE_INFO_MODIFICATION_TIME | - GTK_FILE_INFO_SIZE | - GTK_FILE_INFO_ICON); - -static void gtk_file_system_unix_iface_init (GtkFileSystemIface *iface); -static void gtk_file_system_unix_dispose (GObject *object); -static void gtk_file_system_unix_finalize (GObject *object); - -static GSList * gtk_file_system_unix_list_volumes (GtkFileSystem *file_system); -static GtkFileSystemVolume *gtk_file_system_unix_get_volume_for_path (GtkFileSystem *file_system, - const GtkFilePath *path); - -static GtkFileSystemHandle *gtk_file_system_unix_get_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetFolderCallback callback, - gpointer data); -static GtkFileSystemHandle *gtk_file_system_unix_get_info (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetInfoCallback callback, - gpointer data); -static GtkFileSystemHandle *gtk_file_system_unix_create_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileSystemCreateFolderCallback callback, - gpointer data); -static void gtk_file_system_unix_cancel_operation (GtkFileSystemHandle *handle); - -static void gtk_file_system_unix_volume_free (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -static GtkFilePath *gtk_file_system_unix_volume_get_base_path (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -static gboolean gtk_file_system_unix_volume_get_is_mounted (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -static GtkFileSystemHandle *gtk_file_system_unix_volume_mount (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GtkFileSystemVolumeMountCallback callback, - gpointer data); -static gchar * gtk_file_system_unix_volume_get_display_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -static gchar * gtk_file_system_unix_volume_get_icon_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GError **error); - -static gboolean gtk_file_system_unix_get_parent (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFilePath **parent, - GError **error); -static GtkFilePath * gtk_file_system_unix_make_path (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *display_name, - GError **error); -static gboolean gtk_file_system_unix_parse (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *str, - GtkFilePath **folder, - gchar **file_part, - GError **error); - -static gchar * gtk_file_system_unix_path_to_uri (GtkFileSystem *file_system, - const GtkFilePath *path); -static gchar * gtk_file_system_unix_path_to_filename (GtkFileSystem *file_system, - const GtkFilePath *path); -static GtkFilePath *gtk_file_system_unix_uri_to_path (GtkFileSystem *file_system, - const gchar *uri); -static GtkFilePath *gtk_file_system_unix_filename_to_path (GtkFileSystem *file_system, - const gchar *filename); - - -static gboolean gtk_file_system_unix_insert_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - gint position, - GError **error); -static gboolean gtk_file_system_unix_remove_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - GError **error); -static GSList * gtk_file_system_unix_list_bookmarks (GtkFileSystem *file_system); -static gchar * gtk_file_system_unix_get_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path); -static void gtk_file_system_unix_set_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path, - const gchar *label); - -static void gtk_file_folder_unix_iface_init (GtkFileFolderIface *iface); -static void gtk_file_folder_unix_finalize (GObject *object); - -static GtkFileInfo *gtk_file_folder_unix_get_info (GtkFileFolder *folder, - const GtkFilePath *path, - GError **error); -static gboolean gtk_file_folder_unix_list_children (GtkFileFolder *folder, - GSList **children, - GError **error); - -static gboolean gtk_file_folder_unix_is_finished_loading (GtkFileFolder *folder); - -static GtkFilePath *filename_to_path (const gchar *filename); - -static gboolean filename_is_root (const char *filename); - -static gboolean get_is_hidden_for_file (const char *filename, - const char *basename); -static gboolean file_is_hidden (GtkFileFolderUnix *folder_unix, - const char *basename); - -static GtkFileInfo *file_info_for_root_with_error (const char *root_name, - GError **error); -static gboolean stat_with_error (const char *filename, - struct stat *statbuf, - GError **error); -static GtkFileInfo *create_file_info (GtkFileFolderUnix *folder_unix, - const char *filename, - const char *basename, - GtkFileInfoType types, - struct stat *statbuf, - const char *mime_type); - -static gboolean execute_callbacks (gpointer data); - -static gboolean fill_in_names (GtkFileFolderUnix *folder_unix, - GError **error); -static void fill_in_stats (GtkFileFolderUnix *folder_unix); -static void fill_in_mime_type (GtkFileFolderUnix *folder_unix); -static void fill_in_hidden (GtkFileFolderUnix *folder_unix); - -static gboolean cb_fill_in_stats (gpointer key, - gpointer value, - gpointer user_data); -static gboolean cb_fill_in_mime_type (gpointer key, - gpointer value, - gpointer user_data); - -static char * get_parent_dir (const char *filename); - -/* - * GtkFileSystemUnix - */ -G_DEFINE_TYPE_WITH_CODE (GtkFileSystemUnix, gtk_file_system_unix, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_SYSTEM, - gtk_file_system_unix_iface_init)) - -/* - * GtkFileFolderUnix - */ -G_DEFINE_TYPE_WITH_CODE (GtkFileFolderUnix, _gtk_file_folder_unix, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_FOLDER, - gtk_file_folder_unix_iface_init)) - - -/** - * gtk_file_system_unix_new: - * - * Creates a new #GtkFileSystemUnix object. #GtkFileSystemUnix - * implements the #GtkFileSystem interface with direct access to - * the filesystem using Unix/Linux API calls - * - * Return value: the new #GtkFileSystemUnix object - **/ -GtkFileSystem * -gtk_file_system_unix_new (void) -{ - return g_object_new (GTK_TYPE_FILE_SYSTEM_UNIX, NULL); -} - -static void -gtk_file_system_unix_class_init (GtkFileSystemUnixClass *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - - gobject_class->dispose = gtk_file_system_unix_dispose; - gobject_class->finalize = gtk_file_system_unix_finalize; -} - -static void -gtk_file_system_unix_iface_init (GtkFileSystemIface *iface) -{ - iface->list_volumes = gtk_file_system_unix_list_volumes; - iface->get_volume_for_path = gtk_file_system_unix_get_volume_for_path; - iface->get_folder = gtk_file_system_unix_get_folder; - iface->get_info = gtk_file_system_unix_get_info; - iface->create_folder = gtk_file_system_unix_create_folder; - iface->cancel_operation = gtk_file_system_unix_cancel_operation; - iface->volume_free = gtk_file_system_unix_volume_free; - iface->volume_get_base_path = gtk_file_system_unix_volume_get_base_path; - iface->volume_get_is_mounted = gtk_file_system_unix_volume_get_is_mounted; - iface->volume_mount = gtk_file_system_unix_volume_mount; - iface->volume_get_display_name = gtk_file_system_unix_volume_get_display_name; - iface->volume_get_icon_name = gtk_file_system_unix_volume_get_icon_name; - iface->get_parent = gtk_file_system_unix_get_parent; - iface->make_path = gtk_file_system_unix_make_path; - iface->parse = gtk_file_system_unix_parse; - iface->path_to_uri = gtk_file_system_unix_path_to_uri; - iface->path_to_filename = gtk_file_system_unix_path_to_filename; - iface->uri_to_path = gtk_file_system_unix_uri_to_path; - iface->filename_to_path = gtk_file_system_unix_filename_to_path; - iface->insert_bookmark = gtk_file_system_unix_insert_bookmark; - iface->remove_bookmark = gtk_file_system_unix_remove_bookmark; - iface->list_bookmarks = gtk_file_system_unix_list_bookmarks; - iface->get_bookmark_label = gtk_file_system_unix_get_bookmark_label; - iface->set_bookmark_label = gtk_file_system_unix_set_bookmark_label; -} - -static void -gtk_file_system_unix_init (GtkFileSystemUnix *system_unix) -{ - system_unix->folder_hash = g_hash_table_new (g_str_hash, g_str_equal); - - if (stat ("/afs", &system_unix->afs_statbuf) == 0) - system_unix->have_afs = TRUE; - else - system_unix->have_afs = FALSE; - - if (stat ("/net", &system_unix->net_statbuf) == 0) - system_unix->have_net = TRUE; - else - system_unix->have_net = FALSE; - - system_unix->handles = g_hash_table_new (g_direct_hash, g_direct_equal); - - system_unix->execute_callbacks_idle_id = 0; - system_unix->callbacks = NULL; -} - -static void -check_handle_fn (gpointer key, gpointer value, gpointer data) -{ - GtkFileSystemHandle *handle; - int *num_live_handles; - - handle = key; - num_live_handles = data; - - (*num_live_handles)++; - - g_warning ("file_system_unix=%p still has handle=%p at finalization which is %s!", - handle->file_system, - handle, - handle->cancelled ? "CANCELLED" : "NOT CANCELLED"); -} - -static void -check_handles_at_finalization (GtkFileSystemUnix *system_unix) -{ - int num_live_handles; - - num_live_handles = 0; - - g_hash_table_foreach (system_unix->handles, check_handle_fn, &num_live_handles); -#ifdef HANDLE_ME_HARDER - g_assert (num_live_handles == 0); -#endif - - g_hash_table_destroy (system_unix->handles); - system_unix->handles = NULL; -} - -#define GTK_TYPE_FILE_SYSTEM_HANDLE_UNIX (_gtk_file_system_handle_unix_get_type ()) - -typedef struct _GtkFileSystemHandle GtkFileSystemHandleUnix; -typedef struct _GtkFileSystemHandleClass GtkFileSystemHandleUnixClass; - -G_DEFINE_TYPE (GtkFileSystemHandleUnix, _gtk_file_system_handle_unix, GTK_TYPE_FILE_SYSTEM_HANDLE) - -static void -_gtk_file_system_handle_unix_init (GtkFileSystemHandleUnix *handle) -{ -} - -static void -_gtk_file_system_handle_unix_finalize (GObject *object) -{ - GtkFileSystemHandleUnix *handle; - GtkFileSystemUnix *system_unix; - - handle = (GtkFileSystemHandleUnix *)object; - - system_unix = GTK_FILE_SYSTEM_UNIX (GTK_FILE_SYSTEM_HANDLE (handle)->file_system); - - g_assert (g_hash_table_lookup (system_unix->handles, handle) != NULL); - g_hash_table_remove (system_unix->handles, handle); - - if (G_OBJECT_CLASS (_gtk_file_system_handle_unix_parent_class)->finalize) - G_OBJECT_CLASS (_gtk_file_system_handle_unix_parent_class)->finalize (object); -} - -static void -_gtk_file_system_handle_unix_class_init (GtkFileSystemHandleUnixClass *class) -{ - GObjectClass *gobject_class = (GObjectClass *) class; - - gobject_class->finalize = _gtk_file_system_handle_unix_finalize; -} - -static void -gtk_file_system_unix_dispose (GObject *object) -{ - GtkFileSystemUnix *system_unix; - - system_unix = GTK_FILE_SYSTEM_UNIX (object); - - if (system_unix->execute_callbacks_idle_id) - { - g_source_remove (system_unix->execute_callbacks_idle_id); - system_unix->execute_callbacks_idle_id = 0; - - /* call pending callbacks */ - execute_callbacks (system_unix); - } - - G_OBJECT_CLASS (gtk_file_system_unix_parent_class)->dispose (object); -} - -static void -gtk_file_system_unix_finalize (GObject *object) -{ - GtkFileSystemUnix *system_unix; - - system_unix = GTK_FILE_SYSTEM_UNIX (object); - - check_handles_at_finalization (system_unix); - - /* FIXME: assert that the hash is empty? */ - g_hash_table_destroy (system_unix->folder_hash); - - G_OBJECT_CLASS (gtk_file_system_unix_parent_class)->finalize (object); -} - -/* Returns our single root volume */ -static GtkFileSystemVolume * -get_root_volume (void) -{ - return (GtkFileSystemVolume *) gtk_file_path_new_dup ("/"); -} - -static GSList * -gtk_file_system_unix_list_volumes (GtkFileSystem *file_system) -{ - return g_slist_append (NULL, get_root_volume ()); -} - -static GtkFileSystemVolume * -gtk_file_system_unix_get_volume_for_path (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - return get_root_volume (); -} - -static char * -remove_trailing_slash (const char *filename) -{ - int len; - - len = strlen (filename); - - if (len > 1 && filename[len - 1] == '/') - return g_strndup (filename, len - 1); - else - return g_memdup (filename, len + 1); -} - -/* Delay callback dispatching - */ - -enum callback_types -{ - CALLBACK_GET_INFO, - CALLBACK_GET_FOLDER, - CALLBACK_CREATE_FOLDER, - CALLBACK_VOLUME_MOUNT -}; - -static void queue_callback (GtkFileSystemUnix *system_unix, enum callback_types type, gpointer data); - -struct get_info_callback -{ - GtkFileSystemGetInfoCallback callback; - GtkFileSystemHandle *handle; - GtkFileInfo *file_info; - GError *error; - gpointer data; -}; - -static inline void -dispatch_get_info_callback (struct get_info_callback *info) -{ - (* info->callback) (info->handle, info->file_info, info->error, info->data); - - if (info->file_info) - gtk_file_info_free (info->file_info); - - if (info->error) - g_error_free (info->error); - - g_object_unref (info->handle); - - g_free (info); -} - -static inline void -queue_get_info_callback (GtkFileSystemGetInfoCallback callback, - GtkFileSystemHandle *handle, - GtkFileInfo *file_info, - GError *error, - gpointer data) -{ - struct get_info_callback *info; - - info = g_new (struct get_info_callback, 1); - info->callback = callback; - info->handle = handle; - info->file_info = file_info; - info->error = error; - info->data = data; - - queue_callback (GTK_FILE_SYSTEM_UNIX (handle->file_system), CALLBACK_GET_INFO, info); -} - - -struct get_folder_callback -{ - GtkFileSystemGetFolderCallback callback; - GtkFileSystemHandle *handle; - GtkFileFolder *folder; - GError *error; - gpointer data; -}; - -static inline void -dispatch_get_folder_callback (struct get_folder_callback *info) -{ - (* info->callback) (info->handle, info->folder, info->error, info->data); - - if (info->error) - g_error_free (info->error); - - g_object_unref (info->handle); - - g_free (info); -} - -static inline void -queue_get_folder_callback (GtkFileSystemGetFolderCallback callback, - GtkFileSystemHandle *handle, - GtkFileFolder *folder, - GError *error, - gpointer data) -{ - struct get_folder_callback *info; - - info = g_new (struct get_folder_callback, 1); - info->callback = callback; - info->handle = handle; - info->folder = folder; - info->error = error; - info->data = data; - - queue_callback (GTK_FILE_SYSTEM_UNIX (handle->file_system), CALLBACK_GET_FOLDER, info); -} - - -struct create_folder_callback -{ - GtkFileSystemCreateFolderCallback callback; - GtkFileSystemHandle *handle; - GtkFilePath *path; - GError *error; - gpointer data; -}; - -static inline void -dispatch_create_folder_callback (struct create_folder_callback *info) -{ - (* info->callback) (info->handle, info->path, info->error, info->data); - - if (info->error) - g_error_free (info->error); - - if (info->path) - gtk_file_path_free (info->path); - - g_object_unref (info->handle); - - g_free (info); -} - -static inline void -queue_create_folder_callback (GtkFileSystemCreateFolderCallback callback, - GtkFileSystemHandle *handle, - const GtkFilePath *path, - GError *error, - gpointer data) -{ - struct create_folder_callback *info; - - info = g_new (struct create_folder_callback, 1); - info->callback = callback; - info->handle = handle; - info->path = gtk_file_path_copy (path); - info->error = error; - info->data = data; - - queue_callback (GTK_FILE_SYSTEM_UNIX (handle->file_system), CALLBACK_CREATE_FOLDER, info); -} - - -struct volume_mount_callback -{ - GtkFileSystemVolumeMountCallback callback; - GtkFileSystemHandle *handle; - GtkFileSystemVolume *volume; - GError *error; - gpointer data; -}; - -static inline void -dispatch_volume_mount_callback (struct volume_mount_callback *info) -{ - (* info->callback) (info->handle, info->volume, info->error, info->data); - - if (info->error) - g_error_free (info->error); - - g_object_unref (info->handle); - - g_free (info); -} - -static inline void -queue_volume_mount_callback (GtkFileSystemVolumeMountCallback callback, - GtkFileSystemHandle *handle, - GtkFileSystemVolume *volume, - GError *error, - gpointer data) -{ - struct volume_mount_callback *info; - - info = g_new (struct volume_mount_callback, 1); - info->callback = callback; - info->handle = handle; - info->volume = volume; - info->error = error; - info->data = data; - - queue_callback (GTK_FILE_SYSTEM_UNIX (handle->file_system), CALLBACK_VOLUME_MOUNT, info); -} - - -struct callback_info -{ - enum callback_types type; - - union - { - struct get_info_callback *get_info; - struct get_folder_callback *get_folder; - struct create_folder_callback *create_folder; - struct volume_mount_callback *volume_mount; - } info; -}; - - - -static gboolean -execute_callbacks (gpointer data) -{ - GSList *l; - gboolean unref_file_system = TRUE; - GtkFileSystemUnix *system_unix = GTK_FILE_SYSTEM_UNIX (data); - - if (!system_unix->execute_callbacks_idle_id) - unref_file_system = FALSE; - else - g_object_ref (system_unix); - - for (l = system_unix->callbacks; l; l = l->next) - { - struct callback_info *info = l->data; - - switch (info->type) - { - case CALLBACK_GET_INFO: - dispatch_get_info_callback (info->info.get_info); - break; - - case CALLBACK_GET_FOLDER: - dispatch_get_folder_callback (info->info.get_folder); - break; - - case CALLBACK_CREATE_FOLDER: - dispatch_create_folder_callback (info->info.create_folder); - break; - - case CALLBACK_VOLUME_MOUNT: - dispatch_volume_mount_callback (info->info.volume_mount); - break; - } - - g_free (info); - } - - g_slist_free (system_unix->callbacks); - system_unix->callbacks = NULL; - - if (unref_file_system) - g_object_unref (system_unix); - - system_unix->execute_callbacks_idle_id = 0; - - return FALSE; -} - -static void -queue_callback (GtkFileSystemUnix *system_unix, - enum callback_types type, - gpointer data) -{ - struct callback_info *info; - - info = g_new (struct callback_info, 1); - info->type = type; - - switch (type) - { - case CALLBACK_GET_INFO: - info->info.get_info = data; - break; - - case CALLBACK_GET_FOLDER: - info->info.get_folder = data; - break; - - case CALLBACK_CREATE_FOLDER: - info->info.create_folder = data; - break; - - case CALLBACK_VOLUME_MOUNT: - info->info.volume_mount = data; - break; - } - - system_unix->callbacks = g_slist_append (system_unix->callbacks, info); - - if (!system_unix->execute_callbacks_idle_id) - system_unix->execute_callbacks_idle_id = gdk_threads_add_idle (execute_callbacks, system_unix); -} - -static GtkFileSystemHandle * -create_handle (GtkFileSystem *file_system) -{ - GtkFileSystemUnix *system_unix; - GtkFileSystemHandle *handle; - - system_unix = GTK_FILE_SYSTEM_UNIX (file_system); - - handle = g_object_new (GTK_TYPE_FILE_SYSTEM_HANDLE_UNIX, NULL); - handle->file_system = file_system; - - g_assert (g_hash_table_lookup (system_unix->handles, handle) == NULL); - g_hash_table_insert (system_unix->handles, handle, handle); - - return handle; -} - - - -static GtkFileSystemHandle * -gtk_file_system_unix_get_info (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetInfoCallback callback, - gpointer data) -{ - GError *error = NULL; - GtkFileSystemUnix *system_unix; - GtkFileSystemHandle *handle; - const char *filename; - GtkFileInfo *info; - gchar *basename; - struct stat statbuf; - const char *mime_type; - - system_unix = GTK_FILE_SYSTEM_UNIX (file_system); - handle = create_handle (file_system); - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (filename), NULL); - - if (!stat_with_error (filename, &statbuf, &error)) - { - g_object_ref (handle); - queue_get_info_callback (callback, handle, NULL, error, data); - return handle; - } - - if ((types & GTK_FILE_INFO_MIME_TYPE) != 0) - mime_type = xdg_mime_get_mime_type_for_file (filename, &statbuf); - else - mime_type = NULL; - - basename = g_path_get_basename (filename); - - info = create_file_info (NULL, filename, basename, types, &statbuf, - mime_type); - g_free (basename); - g_object_ref (handle); - queue_get_info_callback (callback, handle, info, NULL, data); - - return handle; -} - -static gboolean -load_folder (gpointer data) -{ - GtkFileFolderUnix *folder_unix = data; - GSList *children; - - if ((folder_unix->types & STAT_NEEDED_MASK) != 0) - fill_in_stats (folder_unix); - - if ((folder_unix->types & GTK_FILE_INFO_MIME_TYPE) != 0) - fill_in_mime_type (folder_unix); - - if (gtk_file_folder_unix_list_children (GTK_FILE_FOLDER (folder_unix), &children, NULL)) - { - folder_unix->is_finished_loading = TRUE; - g_signal_emit_by_name (folder_unix, "files-added", children); - gtk_file_paths_free (children); - } - - folder_unix->load_folder_id = 0; - - g_signal_emit_by_name (folder_unix, "finished-loading", 0); - - return FALSE; -} - -static GtkFileSystemHandle * -gtk_file_system_unix_get_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetFolderCallback callback, - gpointer data) -{ - GError *error = NULL; - GtkFileSystemUnix *system_unix; - GtkFileFolderUnix *folder_unix; - GtkFileSystemHandle *handle; - const char *filename; - char *filename_copy; - gboolean set_asof = FALSE; - - system_unix = GTK_FILE_SYSTEM_UNIX (file_system); - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (filename), NULL); - - handle = create_handle (file_system); - - filename_copy = remove_trailing_slash (filename); - folder_unix = g_hash_table_lookup (system_unix->folder_hash, filename_copy); - - if (folder_unix) - { - g_free (filename_copy); - if (folder_unix->stat_info && - time (NULL) - folder_unix->asof >= FOLDER_CACHE_LIFETIME) - { -#if 0 - g_print ("Cleaning out cached directory %s\n", filename); -#endif - g_hash_table_destroy (folder_unix->stat_info); - folder_unix->stat_info = NULL; - folder_unix->have_mime_type = FALSE; - folder_unix->have_stat = FALSE; - folder_unix->have_hidden = FALSE; - folder_unix->is_finished_loading = FALSE; - set_asof = TRUE; - } - - g_object_ref (folder_unix); - folder_unix->types |= types; - types = folder_unix->types; - } - else - { - struct stat statbuf; - int result; - int code; - int my_errno; - - code = my_errno = 0; /* shut up GCC */ - - result = stat (filename, &statbuf); - - if (result == 0) - { - if (!S_ISDIR (statbuf.st_mode)) - { - result = -1; - code = GTK_FILE_SYSTEM_ERROR_NOT_FOLDER; - my_errno = ENOTDIR; - } - } - else - { - my_errno = errno; - - if (my_errno == ENOENT) - code = GTK_FILE_SYSTEM_ERROR_NONEXISTENT; - else - code = GTK_FILE_SYSTEM_ERROR_FAILED; - } - - if (result != 0) - { - gchar *display_name = g_filename_display_name (filename); - g_set_error (&error, - GTK_FILE_SYSTEM_ERROR, - code, - _("Error getting information for '%s': %s"), - display_name, - g_strerror (my_errno)); - - g_object_ref (handle); - queue_get_folder_callback (callback, handle, NULL, error, data); - - g_free (display_name); - g_free (filename_copy); - return handle; - } - - folder_unix = g_object_new (GTK_TYPE_FILE_FOLDER_UNIX, NULL); - folder_unix->system_unix = system_unix; - folder_unix->filename = filename_copy; - folder_unix->types = types; - folder_unix->stat_info = NULL; - folder_unix->load_folder_id = 0; - folder_unix->have_mime_type = FALSE; - folder_unix->have_stat = FALSE; - folder_unix->have_hidden = FALSE; - folder_unix->is_finished_loading = FALSE; - set_asof = TRUE; - - if ((system_unix->have_afs && - system_unix->afs_statbuf.st_dev == statbuf.st_dev && - system_unix->afs_statbuf.st_ino == statbuf.st_ino) || - (system_unix->have_net && - system_unix->net_statbuf.st_dev == statbuf.st_dev && - system_unix->net_statbuf.st_ino == statbuf.st_ino)) - folder_unix->is_network_dir = TRUE; - else - folder_unix->is_network_dir = FALSE; - - g_hash_table_insert (system_unix->folder_hash, - folder_unix->filename, - folder_unix); - } - - if (set_asof) - folder_unix->asof = time (NULL); - - g_object_ref (handle); - queue_get_folder_callback (callback, handle, GTK_FILE_FOLDER (folder_unix), NULL, data); - - /* Start loading the folder contents in an idle */ - if (!folder_unix->load_folder_id) - folder_unix->load_folder_id = - gdk_threads_add_idle ((GSourceFunc) load_folder, folder_unix); - - return handle; -} - -static GtkFileSystemHandle * -gtk_file_system_unix_create_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileSystemCreateFolderCallback callback, - gpointer data) -{ - GError *error = NULL; - GtkFileSystemUnix *system_unix; - GtkFileSystemHandle *handle; - const char *filename; - gboolean result; - char *parent, *tmp; - int save_errno = errno; - - system_unix = GTK_FILE_SYSTEM_UNIX (file_system); - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (filename), NULL); - - handle = create_handle (file_system); - - tmp = remove_trailing_slash (filename); - errno = 0; - result = mkdir (tmp, 0777) == 0; - save_errno = errno; - g_free (tmp); - - if (!result) - { - gchar *display_name = g_filename_display_name (filename); - g_set_error (&error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_NONEXISTENT, - _("Error creating folder '%s': %s"), - display_name, - g_strerror (save_errno)); - - g_object_ref (handle); - queue_create_folder_callback (callback, handle, path, error, data); - - g_free (display_name); - return handle; - } - - g_object_ref (handle); - queue_create_folder_callback (callback, handle, path, NULL, data); - - parent = get_parent_dir (filename); - if (parent) - { - GtkFileFolderUnix *folder_unix; - - folder_unix = g_hash_table_lookup (system_unix->folder_hash, parent); - if (folder_unix) - { - GSList *paths; - char *basename; - struct stat_info_entry *entry; - - /* Make sure the new folder exists in the parent's folder */ - entry = g_new0 (struct stat_info_entry, 1); - if (folder_unix->is_network_dir) - { - entry->statbuf.st_mode = S_IFDIR; - entry->mime_type = g_strdup ("x-directory/normal"); - } - - basename = g_path_get_basename (filename); - g_hash_table_insert (folder_unix->stat_info, - basename, - entry); - - if (folder_unix->have_stat) - { - /* Cheating */ - if ((folder_unix->types & STAT_NEEDED_MASK) != 0) - cb_fill_in_stats (basename, entry, folder_unix); - - if ((folder_unix->types & GTK_FILE_INFO_MIME_TYPE) != 0) - cb_fill_in_mime_type (basename, entry, folder_unix); - } - - paths = g_slist_append (NULL, (GtkFilePath *) path); - g_signal_emit_by_name (folder_unix, "files-added", paths); - g_slist_free (paths); - } - - g_free (parent); - } - - return handle; -} - -static void -gtk_file_system_unix_cancel_operation (GtkFileSystemHandle *handle) -{ - /* We don't set "cancelled" to TRUE here, since the actual operation - * is executed in the function itself and not in a callback. So - * the operations can never be cancelled (since they will be already - * completed at this point. - */ -} - -static void -gtk_file_system_unix_volume_free (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) -{ - GtkFilePath *path; - - path = (GtkFilePath *) volume; - gtk_file_path_free (path); -} - -static GtkFilePath * -gtk_file_system_unix_volume_get_base_path (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) -{ - return gtk_file_path_new_dup ("/"); -} - -static gboolean -gtk_file_system_unix_volume_get_is_mounted (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) -{ - return TRUE; -} - -static GtkFileSystemHandle * -gtk_file_system_unix_volume_mount (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GtkFileSystemVolumeMountCallback callback, - gpointer data) -{ - GError *error = NULL; - GtkFileSystemHandle *handle = create_handle (file_system); - - g_set_error (&error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_FAILED, - _("This file system does not support mounting")); - - g_object_ref (handle); - queue_volume_mount_callback (callback, handle, volume, error, data); - - return handle; -} - -static gchar * -gtk_file_system_unix_volume_get_display_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) -{ - return g_strdup (_("File System")); /* Same as Nautilus */ -} - -static IconType -get_icon_type_from_stat (struct stat *statp) -{ - if (S_ISBLK (statp->st_mode)) - return ICON_BLOCK_DEVICE; - else if (S_ISLNK (statp->st_mode)) - return ICON_BROKEN_SYMBOLIC_LINK; /* See get_icon_type */ - else if (S_ISCHR (statp->st_mode)) - return ICON_CHARACTER_DEVICE; - else if (S_ISDIR (statp->st_mode)) - return ICON_DIRECTORY; -#ifdef S_ISFIFO - else if (S_ISFIFO (statp->st_mode)) - return ICON_FIFO; -#endif -#ifdef S_ISSOCK - else if (S_ISSOCK (statp->st_mode)) - return ICON_SOCKET; -#endif - else - return ICON_REGULAR; -} - -static IconType -get_icon_type (const char *filename, - GError **error) -{ - struct stat statbuf; - - /* If stat fails, try to fall back to lstat to catch broken links - */ - if (stat (filename, &statbuf) != 0) - { - if (errno != ENOENT || lstat (filename, &statbuf) != 0) - { - int save_errno = errno; - gchar *display_name = g_filename_display_name (filename); - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_NONEXISTENT, - _("Error getting information for '%s': %s"), - display_name, - g_strerror (save_errno)); - g_free (display_name); - - return ICON_NONE; - } - } - - return get_icon_type_from_stat (&statbuf); -} - -/* Renders a fallback icon from the stock system */ -static const gchar * -get_fallback_icon_name (IconType icon_type) -{ - const char *stock_name; - - switch (icon_type) - { - case ICON_BLOCK_DEVICE: - stock_name = GTK_STOCK_HARDDISK; - break; - - case ICON_DIRECTORY: - stock_name = GTK_STOCK_DIRECTORY; - break; - - case ICON_EXECUTABLE: - stock_name = GTK_STOCK_EXECUTE; - break; - - default: - stock_name = GTK_STOCK_FILE; - break; - } - - return stock_name; -} - -static gchar * -gtk_file_system_unix_volume_get_icon_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GError **error) -{ - /* FIXME: maybe we just always want to return GTK_STOCK_HARDDISK here? - * or the new tango icon name? - */ - return g_strdup ("gnome-dev-harddisk"); -} - -static char * -get_parent_dir (const char *filename) -{ - int len; - - len = strlen (filename); - - /* Ignore trailing slashes */ - if (len > 1 && filename[len - 1] == '/') - { - char *tmp, *parent; - - tmp = g_strndup (filename, len - 1); - - parent = g_path_get_dirname (tmp); - g_free (tmp); - - return parent; - } - else - return g_path_get_dirname (filename); -} - -static gboolean -gtk_file_system_unix_get_parent (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFilePath **parent, - GError **error) -{ - const char *filename; - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, FALSE); - g_return_val_if_fail (g_path_is_absolute (filename), FALSE); - - if (filename_is_root (filename)) - { - *parent = NULL; - } - else - { - gchar *parent_filename = get_parent_dir (filename); - *parent = filename_to_path (parent_filename); - g_free (parent_filename); - } - - return TRUE; -} - -static GtkFilePath * -gtk_file_system_unix_make_path (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *display_name, - GError **error) -{ - const char *base_filename; - gchar *filename; - gchar *full_filename; - GError *tmp_error = NULL; - GtkFilePath *result; - - base_filename = gtk_file_path_get_string (base_path); - g_return_val_if_fail (base_filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (base_filename), NULL); - - if (strchr (display_name, G_DIR_SEPARATOR)) - { - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_BAD_FILENAME, - _("The name \"%s\" is not valid because it contains the character \"%s\". " - "Please use a different name."), - display_name, - G_DIR_SEPARATOR_S); - return NULL; - } - - filename = g_filename_from_utf8 (display_name, -1, NULL, NULL, &tmp_error); - if (!filename) - { - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_BAD_FILENAME, - "%s", - tmp_error->message); - - g_error_free (tmp_error); - - return NULL; - } - - full_filename = g_build_filename (base_filename, filename, NULL); - result = filename_to_path (full_filename); - g_free (filename); - g_free (full_filename); - - return result; -} - -/* If this was a publically exported function, it should return - * a dup'ed result, but we make it modify-in-place for efficiency - * here, and because it works for us. - */ -static void -canonicalize_filename (gchar *filename) -{ - gchar *p, *q; - gboolean last_was_slash = FALSE; - - p = filename; - q = filename; - - while (*p) - { - if (*p == G_DIR_SEPARATOR) - { - if (!last_was_slash) - *q++ = G_DIR_SEPARATOR; - - last_was_slash = TRUE; - } - else - { - if (last_was_slash && *p == '.') - { - if (*(p + 1) == G_DIR_SEPARATOR || - *(p + 1) == '\0') - { - if (*(p + 1) == '\0') - break; - - p += 1; - } - else if (*(p + 1) == '.' && - (*(p + 2) == G_DIR_SEPARATOR || - *(p + 2) == '\0')) - { - if (q > filename + 1) - { - q--; - while (q > filename + 1 && - *(q - 1) != G_DIR_SEPARATOR) - q--; - } - - if (*(p + 2) == '\0') - break; - - p += 2; - } - else - { - *q++ = *p; - last_was_slash = FALSE; - } - } - else - { - *q++ = *p; - last_was_slash = FALSE; - } - } - - p++; - } - - if (q > filename + 1 && *(q - 1) == G_DIR_SEPARATOR) - q--; - - *q = '\0'; -} - -/* Takes a user-typed filename and expands a tilde at the beginning of the string */ -static char * -expand_tilde (const char *filename) -{ - const char *notilde; - const char *slash; - const char *home; - - if (filename[0] != '~') - return g_strdup (filename); - - notilde = filename + 1; - - slash = strchr (notilde, G_DIR_SEPARATOR); - - if (slash == notilde || !*notilde) - { - home = g_get_home_dir (); - - if (!home) - return g_strdup (filename); - } - else - { - char *username; - struct passwd *passwd; - - if (slash) - username = g_strndup (notilde, slash - notilde); - else - username = g_strdup (notilde); - - passwd = getpwnam (username); - g_free (username); - - if (!passwd) - return g_strdup (filename); - - home = passwd->pw_dir; - } - - /* We put G_DIR_SEPARATOR_S so that empty basenames will make the resulting path end in a slash */ - if (slash) - return g_build_filename (home, G_DIR_SEPARATOR_S, slash + 1, NULL); - else - return g_build_filename (home, G_DIR_SEPARATOR_S, NULL); -} - -static gboolean -gtk_file_system_unix_parse (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *str, - GtkFilePath **folder, - gchar **file_part, - GError **error) -{ - const char *base_filename; - gchar *filename; - gchar *last_slash; - gboolean result = FALSE; - - base_filename = gtk_file_path_get_string (base_path); - g_return_val_if_fail (base_filename != NULL, FALSE); - g_return_val_if_fail (g_path_is_absolute (base_filename), FALSE); - - filename = expand_tilde (str); - if (!filename) - { - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_BAD_FILENAME, - "%s", ""); /* nothing for now, as we are string-frozen */ - return FALSE; - } - - last_slash = strrchr (filename, G_DIR_SEPARATOR); - if (!last_slash) - { - *folder = gtk_file_path_copy (base_path); - *file_part = g_strdup (filename); - result = TRUE; - } - else - { - gchar *folder_part; - gchar *folder_path; - GError *tmp_error = NULL; - - if (last_slash == filename) - folder_part = g_strdup ("/"); - else - folder_part = g_filename_from_utf8 (filename, last_slash - filename, - NULL, NULL, &tmp_error); - - if (!folder_part) - { - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_BAD_FILENAME, - "%s", - tmp_error->message); - g_error_free (tmp_error); - } - else - { - if (folder_part[0] == G_DIR_SEPARATOR) - folder_path = folder_part; - else - { - folder_path = g_build_filename (base_filename, folder_part, NULL); - g_free (folder_part); - } - - canonicalize_filename (folder_path); - - *folder = filename_to_path (folder_path); - *file_part = g_strdup (last_slash + 1); - - g_free (folder_path); - - result = TRUE; - } - } - - g_free (filename); - - return result; -} - -static gchar * -gtk_file_system_unix_path_to_uri (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - return g_filename_to_uri (gtk_file_path_get_string (path), NULL, NULL); -} - -static gchar * -gtk_file_system_unix_path_to_filename (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - return g_strdup (gtk_file_path_get_string (path)); -} - -static GtkFilePath * -gtk_file_system_unix_uri_to_path (GtkFileSystem *file_system, - const gchar *uri) -{ - GtkFilePath *path; - gchar *filename = g_filename_from_uri (uri, NULL, NULL); - - if (filename) - { - path = filename_to_path (filename); - g_free (filename); - } - else - path = NULL; - - return path; -} - -static GtkFilePath * -gtk_file_system_unix_filename_to_path (GtkFileSystem *file_system, - const gchar *filename) -{ - return filename_to_path (filename); -} - -/* Returns the name of the icon to be used for a path which is known to be a - * directory. This can vary for Home, Desktop, etc. - */ -static const char * -get_icon_name_for_directory (const char *path) -{ - if (!g_get_home_dir ()) - return "gnome-fs-directory"; - - if (strcmp (g_get_home_dir (), path) == 0) - return "gnome-fs-home"; - else if (strcmp (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP), path) == 0) - return "gnome-fs-desktop"; - else - return "gnome-fs-directory"; - - return NULL; -} - -/* Computes our internal icon type based on a path name; also returns the MIME - * type in case we come up with ICON_REGULAR. - */ -static IconType -get_icon_type_from_path (GtkFileFolderUnix *folder_unix, - struct stat *statbuf, - const char *filename, - const char **mime_type) -{ - IconType icon_type; - - *mime_type = NULL; - - if (folder_unix && folder_unix->have_stat) - { - char *basename; - struct stat_info_entry *entry; - - g_assert (folder_unix->stat_info != NULL); - - basename = g_path_get_basename (filename); - entry = g_hash_table_lookup (folder_unix->stat_info, basename); - g_free (basename); - if (entry) - { - if (entry->icon_type == ICON_UNDECIDED) - { - entry->icon_type = get_icon_type_from_stat (&entry->statbuf); - g_assert (entry->icon_type != ICON_UNDECIDED); - } - icon_type = entry->icon_type; - if (icon_type == ICON_REGULAR) - { - fill_in_mime_type (folder_unix); - *mime_type = entry->mime_type; - } - - return icon_type; - } - } - - if (statbuf) - return get_icon_type_from_stat (statbuf); - - icon_type = get_icon_type (filename, NULL); - if (icon_type == ICON_REGULAR) - *mime_type = xdg_mime_get_mime_type_for_file (filename, NULL); - - return icon_type; -} - -/* Renders an icon for a non-ICON_REGULAR file */ -static const gchar * -get_special_icon_name (IconType icon_type, - const gchar *filename) -{ - const char *name; - - g_assert (icon_type != ICON_REGULAR); - - switch (icon_type) - { - case ICON_BLOCK_DEVICE: - name = "gnome-fs-blockdev"; - break; - case ICON_BROKEN_SYMBOLIC_LINK: - name = "gnome-fs-symlink"; - break; - case ICON_CHARACTER_DEVICE: - name = "gnome-fs-chardev"; - break; - case ICON_DIRECTORY: - /* get_icon_name_for_directory() returns a dupped string */ - return get_icon_name_for_directory (filename); - case ICON_EXECUTABLE: - name ="gnome-fs-executable"; - break; - case ICON_FIFO: - name = "gnome-fs-fifo"; - break; - case ICON_SOCKET: - name = "gnome-fs-socket"; - break; - default: - g_assert_not_reached (); - return NULL; - } - - return name; -} - -static gchar * -get_icon_name_for_mime_type (const char *mime_type) -{ - char *name; - const char *separator; - GString *icon_name; - - if (!mime_type) - return NULL; - - separator = strchr (mime_type, '/'); - if (!separator) - return NULL; /* maybe we should return a GError with "invalid MIME-type" */ - - /* FIXME: we default to the gnome icon naming for now. Some question - * as below, how are we going to handle a second attempt? - */ -#if 0 - icon_name = g_string_new (""); - g_string_append_len (icon_name, mime_type, separator - mime_type); - g_string_append_c (icon_name, '-'); - g_string_append (icon_name, separator + 1); - pixbuf = get_cached_icon (widget, icon_name->str, pixel_size); - g_string_free (icon_name, TRUE); - if (pixbuf) - return pixbuf; - - icon_name = g_string_new (""); - g_string_append_len (icon_name, mime_type, separator - mime_type); - g_string_append (icon_name, "-x-generic"); - pixbuf = get_cached_icon (widget, icon_name->str, pixel_size); - g_string_free (icon_name, TRUE); - if (pixbuf) - return pixbuf; -#endif - - icon_name = g_string_new ("gnome-mime-"); - g_string_append_len (icon_name, mime_type, separator - mime_type); - g_string_append_c (icon_name, '-'); - g_string_append (icon_name, separator + 1); - name = icon_name->str; - g_string_free (icon_name, FALSE); - - return name; - - /* FIXME: how are we going to implement a second attempt? */ -#if 0 - if (pixbuf) - return pixbuf; - - icon_name = g_string_new ("gnome-mime-"); - g_string_append_len (icon_name, mime_type, separator - mime_type); - pixbuf = get_cached_icon (widget, icon_name->str, pixel_size); - g_string_free (icon_name, TRUE); - - return pixbuf; -#endif -} - -static void -bookmark_list_free (GSList *list) -{ - GSList *l; - - for (l = list; l; l = l->next) - g_free (l->data); - - g_slist_free (list); -} - -/* Returns whether a URI is a local file:// */ -static gboolean -is_local_uri (const char *uri) -{ - char *filename; - char *hostname; - gboolean result; - - /* This is rather crude, but hey */ - filename = g_filename_from_uri (uri, &hostname, NULL); - - result = (filename && !hostname); - - g_free (filename); - g_free (hostname); - - return result; -} - -static char * -bookmark_get_filename (void) -{ - char *filename; - - filename = g_build_filename (g_get_home_dir (), - BOOKMARKS_FILENAME, NULL); - g_assert (filename != NULL); - return filename; -} - -static gboolean -bookmark_list_read (GSList **bookmarks, GError **error) -{ - gchar *filename; - gchar *contents; - gboolean result = FALSE; - - filename = bookmark_get_filename (); - *bookmarks = NULL; - - if (g_file_get_contents (filename, &contents, NULL, error)) - { - gchar **lines = g_strsplit (contents, "\n", -1); - int i; - GHashTable *table; - - table = g_hash_table_new (g_str_hash, g_str_equal); - - for (i = 0; lines[i]; i++) - { - if (lines[i][0] && !g_hash_table_lookup (table, lines[i])) - { - *bookmarks = g_slist_prepend (*bookmarks, g_strdup (lines[i])); - g_hash_table_insert (table, lines[i], lines[i]); - } - } - - g_free (contents); - g_hash_table_destroy (table); - g_strfreev (lines); - - *bookmarks = g_slist_reverse (*bookmarks); - result = TRUE; - } - - g_free (filename); - - return result; -} - -static gboolean -bookmark_list_write (GSList *bookmarks, - GError **error) -{ - GSList *l; - GString *string; - char *filename; - GError *tmp_error = NULL; - gboolean result; - - string = g_string_new (""); - - for (l = bookmarks; l; l = l->next) - { - g_string_append (string, l->data); - g_string_append_c (string, '\n'); - } - - filename = bookmark_get_filename (); - - result = g_file_set_contents (filename, string->str, -1, &tmp_error); - - g_free (filename); - g_string_free (string, TRUE); - - if (!result) - { - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_FAILED, - _("Bookmark saving failed: %s"), - tmp_error->message); - - g_error_free (tmp_error); - } - - return result; -} - -static gboolean -gtk_file_system_unix_insert_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - gint position, - GError **error) -{ - GSList *bookmarks; - int num_bookmarks; - GSList *l; - char *uri; - gboolean result; - GError *err; - - err = NULL; - if (!bookmark_list_read (&bookmarks, &err) && err->code != G_FILE_ERROR_NOENT) - { - g_propagate_error (error, err); - return FALSE; - } - - num_bookmarks = g_slist_length (bookmarks); - g_return_val_if_fail (position >= -1 && position <= num_bookmarks, FALSE); - - result = FALSE; - - uri = gtk_file_system_unix_path_to_uri (file_system, path); - - for (l = bookmarks; l; l = l->next) - { - char *bookmark, *space; - - bookmark = l->data; - - space = strchr (bookmark, ' '); - if (space) - *space = '\0'; - if (strcmp (bookmark, uri) != 0) - { - if (space) - *space = ' '; - } - else - { - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_ALREADY_EXISTS, - _("'%s' already exists in the bookmarks list"), - uri); - goto out; - } - } - - bookmarks = g_slist_insert (bookmarks, g_strdup (uri), position); - if (bookmark_list_write (bookmarks, error)) - { - result = TRUE; - g_signal_emit_by_name (file_system, "bookmarks-changed", 0); - } - - out: - - g_free (uri); - bookmark_list_free (bookmarks); - - return result; -} - -static gboolean -gtk_file_system_unix_remove_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - GError **error) -{ - GSList *bookmarks; - char *uri; - GSList *l; - gboolean result; - - if (!bookmark_list_read (&bookmarks, error)) - return FALSE; - - result = FALSE; - - uri = gtk_file_system_path_to_uri (file_system, path); - - for (l = bookmarks; l; l = l->next) - { - char *bookmark, *space; - - bookmark = (char *)l->data; - space = strchr (bookmark, ' '); - if (space) - *space = '\0'; - - if (strcmp (bookmark, uri) != 0) - { - if (space) - *space = ' '; - } - else - { - g_free (l->data); - bookmarks = g_slist_remove_link (bookmarks, l); - g_slist_free_1 (l); - - if (bookmark_list_write (bookmarks, error)) - { - result = TRUE; - - g_signal_emit_by_name (file_system, "bookmarks-changed", 0); - } - - goto out; - } - } - - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_NONEXISTENT, - _("'%s' does not exist in the bookmarks list"), - uri); - - out: - - g_free (uri); - bookmark_list_free (bookmarks); - - return result; -} - -static GSList * -gtk_file_system_unix_list_bookmarks (GtkFileSystem *file_system) -{ - GSList *bookmarks; - GSList *result; - GSList *l; - - if (!bookmark_list_read (&bookmarks, NULL)) - return NULL; - - result = NULL; - - for (l = bookmarks; l; l = l->next) - { - char *bookmark, *space; - - bookmark = (char *)l->data; - space = strchr (bookmark, ' '); - if (space) - *space = '\0'; - - if (is_local_uri (bookmark)) - result = g_slist_prepend (result, gtk_file_system_unix_uri_to_path (file_system, bookmark)); - } - - bookmark_list_free (bookmarks); - - result = g_slist_reverse (result); - return result; -} - -static gchar * -gtk_file_system_unix_get_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - GSList *labels; - gchar *label; - GSList *l; - char *bookmark, *space, *uri; - - labels = NULL; - label = NULL; - - uri = gtk_file_system_path_to_uri (file_system, path); - bookmark_list_read (&labels, NULL); - - for (l = labels; l && !label; l = l->next) - { - bookmark = (char *)l->data; - space = strchr (bookmark, ' '); - if (!space) - continue; - - *space = '\0'; - - if (strcmp (uri, bookmark) == 0) - label = g_strdup (space + 1); - } - - bookmark_list_free (labels); - g_free (uri); - - return label; -} - -static void -gtk_file_system_unix_set_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path, - const gchar *label) -{ - GSList *labels; - GSList *l; - gchar *bookmark, *space, *uri; - gboolean found; - - labels = NULL; - - uri = gtk_file_system_path_to_uri (file_system, path); - bookmark_list_read (&labels, NULL); - - found = FALSE; - for (l = labels; l && !found; l = l->next) - { - bookmark = (gchar *)l->data; - space = strchr (bookmark, ' '); - if (space) - *space = '\0'; - - if (strcmp (bookmark, uri) != 0) - { - if (space) - *space = ' '; - } - else - { - g_free (bookmark); - - if (label && *label) - l->data = g_strdup_printf ("%s %s", uri, label); - else - l->data = g_strdup (uri); - - found = TRUE; - break; - } - } - - if (found) - { - if (bookmark_list_write (labels, NULL)) - g_signal_emit_by_name (file_system, "bookmarks-changed", 0); - } - - bookmark_list_free (labels); - g_free (uri); -} - -static void -_gtk_file_folder_unix_class_init (GtkFileFolderUnixClass *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - - gobject_class->finalize = gtk_file_folder_unix_finalize; -} - -static void -gtk_file_folder_unix_iface_init (GtkFileFolderIface *iface) -{ - iface->get_info = gtk_file_folder_unix_get_info; - iface->list_children = gtk_file_folder_unix_list_children; - iface->is_finished_loading = gtk_file_folder_unix_is_finished_loading; -} - -static void -_gtk_file_folder_unix_init (GtkFileFolderUnix *impl) -{ -} - -static void -gtk_file_folder_unix_finalize (GObject *object) -{ - GtkFileFolderUnix *folder_unix = GTK_FILE_FOLDER_UNIX (object); - - if (folder_unix->load_folder_id) - { - g_source_remove (folder_unix->load_folder_id); - folder_unix->load_folder_id = 0; - } - - g_hash_table_remove (folder_unix->system_unix->folder_hash, folder_unix->filename); - - if (folder_unix->stat_info) - { -#if 0 - g_print ("Releasing information for directory %s\n", folder_unix->filename); -#endif - g_hash_table_destroy (folder_unix->stat_info); - } - - g_free (folder_unix->filename); - - G_OBJECT_CLASS (_gtk_file_folder_unix_parent_class)->finalize (object); -} - -/* Creates a GtkFileInfo for "/" by stat()ing it */ -static GtkFileInfo * -file_info_for_root_with_error (const char *root_name, - GError **error) -{ - struct stat statbuf; - GtkFileInfo *info; - - if (stat (root_name, &statbuf) != 0) - { - int saved_errno; - - saved_errno = errno; - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_FAILED, - _("Error getting information for '%s': %s"), - "/", g_strerror (saved_errno)); - - return NULL; - } - - info = gtk_file_info_new (); - gtk_file_info_set_display_name (info, "/"); - gtk_file_info_set_is_folder (info, TRUE); - gtk_file_info_set_is_hidden (info, FALSE); - gtk_file_info_set_mime_type (info, "x-directory/normal"); - gtk_file_info_set_modification_time (info, statbuf.st_mtime); - gtk_file_info_set_size (info, statbuf.st_size); - - return info; -} - -static gboolean -stat_with_error (const char *filename, - struct stat *statbuf, - GError **error) -{ - if (stat (filename, statbuf) == -1 && - (errno != ENOENT || lstat (filename, statbuf) == -1)) - { - int saved_errno; - int code; - char *display_name; - - saved_errno = errno; - - if (saved_errno == ENOENT) - code = GTK_FILE_SYSTEM_ERROR_NONEXISTENT; - else - code = GTK_FILE_SYSTEM_ERROR_FAILED; - - display_name = g_filename_display_name (filename); - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - code, - _("Error getting information for '%s': %s"), - display_name, - g_strerror (saved_errno)); - - g_free (display_name); - return FALSE; - } - - return TRUE; -} - -/* Creates a new GtkFileInfo from the specified data */ -static GtkFileInfo * -create_file_info (GtkFileFolderUnix *folder_unix, - const char *filename, - const char *basename, - GtkFileInfoType types, - struct stat *statbuf, - const char *mime_type) -{ - GtkFileInfo *info; - - info = gtk_file_info_new (); - - if (types & GTK_FILE_INFO_DISPLAY_NAME) - { - gchar *display_name = g_filename_display_basename (filename); - gtk_file_info_set_display_name (info, display_name); - g_free (display_name); - } - - if (types & GTK_FILE_INFO_IS_HIDDEN) - { - if (folder_unix) - { - if (file_is_hidden (folder_unix, basename)) - gtk_file_info_set_is_hidden (info, TRUE); - } - else - { - if (get_is_hidden_for_file (filename, basename)) - gtk_file_info_set_is_hidden (info, TRUE); - } - } - - if (types & GTK_FILE_INFO_IS_FOLDER) - gtk_file_info_set_is_folder (info, S_ISDIR (statbuf->st_mode)); - - if (types & GTK_FILE_INFO_MIME_TYPE) - gtk_file_info_set_mime_type (info, mime_type); - - if (types & GTK_FILE_INFO_MODIFICATION_TIME) - gtk_file_info_set_modification_time (info, statbuf->st_mtime); - - if (types & GTK_FILE_INFO_SIZE) - gtk_file_info_set_size (info, (gint64) statbuf->st_size); - - if (types & GTK_FILE_INFO_ICON) - { - IconType icon_type; - gboolean free_icon_name = FALSE; - const char *icon_name; - const char *icon_mime_type; - - icon_type = get_icon_type_from_path (folder_unix, statbuf, filename, &icon_mime_type); - - switch (icon_type) - { - case ICON_NONE: - icon_name = get_fallback_icon_name (icon_type); - break; - - case ICON_REGULAR: - free_icon_name = TRUE; - if (icon_mime_type) - icon_name = get_icon_name_for_mime_type (icon_mime_type); - else - icon_name = get_icon_name_for_mime_type (mime_type); - break; - - default: - icon_name = get_special_icon_name (icon_type, filename); - break; - } - - gtk_file_info_set_icon_name (info, icon_name); - - if (free_icon_name) - g_free ((char *) icon_name); - } - - return info; -} - -static struct stat_info_entry * -create_stat_info_entry_and_emit_add (GtkFileFolderUnix *folder_unix, - const char *filename, - const char *basename, - struct stat *statbuf) -{ - GSList *paths; - GtkFilePath *path; - struct stat_info_entry *entry; - - entry = g_new0 (struct stat_info_entry, 1); - - if ((folder_unix->types & STAT_NEEDED_MASK) != 0) - entry->statbuf = *statbuf; - - if ((folder_unix->types & GTK_FILE_INFO_MIME_TYPE) != 0) - entry->mime_type = g_strdup (xdg_mime_get_mime_type_for_file (filename, statbuf)); - - g_hash_table_insert (folder_unix->stat_info, - g_strdup (basename), - entry); - - path = gtk_file_path_new_dup (filename); - paths = g_slist_append (NULL, path); - g_signal_emit_by_name (folder_unix, "files-added", paths); - gtk_file_path_free (path); - g_slist_free (paths); - - return entry; -} - -static GtkFileInfo * -gtk_file_folder_unix_get_info (GtkFileFolder *folder, - const GtkFilePath *path, - GError **error) -{ - GtkFileFolderUnix *folder_unix = GTK_FILE_FOLDER_UNIX (folder); - GtkFileInfo *info; - gchar *dirname, *basename; - const char *filename; - GtkFileInfoType types; - struct stat statbuf; - const char *mime_type; - - /* Get_info for "/" */ - if (!path) - { - g_return_val_if_fail (filename_is_root (folder_unix->filename), NULL); - return file_info_for_root_with_error (folder_unix->filename, error); - } - - /* Get_info for normal files */ - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (filename), NULL); - - dirname = get_parent_dir (filename); - g_return_val_if_fail (strcmp (dirname, folder_unix->filename) == 0, NULL); - g_free (dirname); - - basename = g_path_get_basename (filename); - types = folder_unix->types; - - if (folder_unix->have_stat) - { - struct stat_info_entry *entry; - - g_assert (folder_unix->stat_info != NULL); - entry = g_hash_table_lookup (folder_unix->stat_info, basename); - - if (!entry) - { - if (!stat_with_error (filename, &statbuf, error)) - { - g_free (basename); - return NULL; - } - - entry = create_stat_info_entry_and_emit_add (folder_unix, filename, basename, &statbuf); - } - - info = create_file_info (folder_unix, filename, basename, types, &entry->statbuf, entry->mime_type); - g_free (basename); - return info; - } - else - { - if (!stat_with_error (filename, &statbuf, error)) - { - g_free (basename); - return NULL; - } - - if ((types & GTK_FILE_INFO_MIME_TYPE) != 0) - mime_type = xdg_mime_get_mime_type_for_file (filename, &statbuf); - else - mime_type = NULL; - - info = create_file_info (folder_unix, filename, basename, types, &statbuf, mime_type); - g_free (basename); - return info; - } -} - - -static void -cb_list_children (gpointer key, gpointer value, gpointer user_data) -{ - GSList **children = user_data; - *children = g_slist_prepend (*children, key); -} - -static gboolean -gtk_file_folder_unix_list_children (GtkFileFolder *folder, - GSList **children, - GError **error) -{ - GtkFileFolderUnix *folder_unix = GTK_FILE_FOLDER_UNIX (folder); - GSList *l; - - *children = NULL; - - /* Get the list of basenames. */ - if (folder_unix->stat_info) - g_hash_table_foreach (folder_unix->stat_info, cb_list_children, children); - - /* Turn basenames into GFilePaths. */ - for (l = *children; l; l = l->next) - { - const char *basename = l->data; - char *fullname = g_build_filename (folder_unix->filename, basename, NULL); - l->data = filename_to_path (fullname); - g_free (fullname); - } - - return TRUE; -} - -static gboolean -gtk_file_folder_unix_is_finished_loading (GtkFileFolder *folder) -{ - return GTK_FILE_FOLDER_UNIX (folder)->is_finished_loading; -} - -static void -free_stat_info_entry (struct stat_info_entry *entry) -{ - g_free (entry->mime_type); - g_free (entry); -} - -static gboolean -fill_in_names (GtkFileFolderUnix *folder_unix, GError **error) -{ - GDir *dir; - - if (folder_unix->stat_info) - return TRUE; - - dir = g_dir_open (folder_unix->filename, 0, error); - if (!dir) - return FALSE; - - folder_unix->stat_info = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) free_stat_info_entry); - - while (TRUE) - { - struct stat_info_entry *entry; - const gchar *basename; - - basename = g_dir_read_name (dir); - if (!basename) - break; - - entry = g_new0 (struct stat_info_entry, 1); - if (folder_unix->is_network_dir) - { - entry->statbuf.st_mode = S_IFDIR; - entry->mime_type = g_strdup ("x-directory/normal"); - } - - g_hash_table_insert (folder_unix->stat_info, - g_strdup (basename), - entry); - } - - g_dir_close (dir); - - folder_unix->asof = time (NULL); - return TRUE; -} - -static gboolean -cb_fill_in_stats (gpointer key, gpointer value, gpointer user_data) -{ - const char *basename = key; - struct stat_info_entry *entry = value; - GtkFileFolderUnix *folder_unix = user_data; - char *fullname = g_build_filename (folder_unix->filename, basename, NULL); - gboolean result; - - if (stat (fullname, &entry->statbuf) == -1 && - (errno != ENOENT || lstat (fullname, &entry->statbuf) == -1)) - result = TRUE; /* Couldn't stat -- remove from hash. */ - else - result = FALSE; - - g_free (fullname); - return result; -} - - -static void -fill_in_stats (GtkFileFolderUnix *folder_unix) -{ - if (folder_unix->have_stat) - return; - - if (!fill_in_names (folder_unix, NULL)) - return; - - if (!folder_unix->is_network_dir) - g_hash_table_foreach_remove (folder_unix->stat_info, - cb_fill_in_stats, - folder_unix); - - folder_unix->have_stat = TRUE; -} - - -static gboolean -cb_fill_in_mime_type (gpointer key, gpointer value, gpointer user_data) -{ - const char *basename = key; - struct stat_info_entry *entry = value; - GtkFileFolderUnix *folder_unix = user_data; - char *fullname = g_build_filename (folder_unix->filename, basename, NULL); - struct stat *statbuf = NULL; - const char *mime_type; - - if (folder_unix->have_stat) - statbuf = &entry->statbuf; - - mime_type = xdg_mime_get_mime_type_for_file (fullname, statbuf); - entry->mime_type = g_strdup (mime_type); - - g_free (fullname); - - return FALSE; -} - -static void -fill_in_mime_type (GtkFileFolderUnix *folder_unix) -{ - if (folder_unix->have_mime_type) - return; - - if (!folder_unix->have_stat) - return; - - g_assert (folder_unix->stat_info != NULL); - - if (!folder_unix->is_network_dir) - g_hash_table_foreach_remove (folder_unix->stat_info, - cb_fill_in_mime_type, - folder_unix); - - folder_unix->have_mime_type = TRUE; -} - -static gchar ** -read_hidden_file (const char *dirname) -{ - gchar **lines = NULL; - gchar *contents; - gchar *hidden_file; - - hidden_file = g_build_filename (dirname, HIDDEN_FILENAME, NULL); - - if (g_file_get_contents (hidden_file, &contents, NULL, NULL)) - { - lines = g_strsplit (contents, "\n", -1); - g_free (contents); - } - - g_free (hidden_file); - - return lines; -} - -static void -fill_in_hidden (GtkFileFolderUnix *folder_unix) -{ - gchar **lines; - - if (folder_unix->have_hidden) - return; - - lines = read_hidden_file (folder_unix->filename); - - if (lines) - { - int i; - - for (i = 0; lines[i]; i++) - { - if (lines[i][0]) - { - struct stat_info_entry *entry; - - entry = g_hash_table_lookup (folder_unix->stat_info, lines[i]); - if (entry != NULL) - entry->hidden = TRUE; - } - } - - g_strfreev (lines); - } - - folder_unix->have_hidden = TRUE; -} - -static GtkFilePath * -filename_to_path (const char *filename) -{ - char *tmp; - - tmp = remove_trailing_slash (filename); - return gtk_file_path_new_steal (tmp); -} - -static gboolean -filename_is_root (const char *filename) -{ - const gchar *after_root; - - after_root = g_path_skip_root (filename); - - return (after_root != NULL && *after_root == '\0'); -} - -static gboolean -get_is_hidden_for_file (const char *filename, - const char *basename) -{ - gchar *dirname; - gchar **lines; - gboolean hidden = FALSE; - - dirname = g_path_get_dirname (filename); - lines = read_hidden_file (dirname); - g_free (dirname); - - if (lines) - { - int i; - - for (i = 0; lines[i]; i++) - { - if (lines[i][0] && strcmp (lines[i], basename) == 0) - { - hidden = TRUE; - break; - } - } - - g_strfreev (lines); - } - - return hidden; -} - -static gboolean -file_is_hidden (GtkFileFolderUnix *folder_unix, - const char *basename) -{ - struct stat_info_entry *entry; - - if (basename[0] == '.' || basename[strlen (basename) - 1] == '~') - return TRUE; - - if (folder_unix->have_stat) - { - fill_in_hidden (folder_unix); - - entry = g_hash_table_lookup (folder_unix->stat_info, basename); - - if (entry) - return entry->hidden; - } - - return FALSE; -} - -#define __GTK_FILE_SYSTEM_UNIX_C__ -#include "gtkaliasdef.c" diff --git a/gtk/gtkfilesystemunix.h b/gtk/gtkfilesystemunix.h deleted file mode 100644 index 9c8e9e2b1..000000000 --- a/gtk/gtkfilesystemunix.h +++ /dev/null @@ -1,40 +0,0 @@ -/* GTK - The GIMP Toolkit - * gtkfilesystemunix.h: Default implementation of GtkFileSystem for UNIX-like systems - * Copyright (C) 2003, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GTK_FILE_SYSTEM_UNIX_H__ -#define __GTK_FILE_SYSTEM_UNIX_H__ - -#include -#include "gtkfilesystem.h" - -G_BEGIN_DECLS - -#define GTK_TYPE_FILE_SYSTEM_UNIX (gtk_file_system_unix_get_type ()) -#define GTK_FILE_SYSTEM_UNIX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_SYSTEM_UNIX, GtkFileSystemUnix)) -#define GTK_IS_FILE_SYSTEM_UNIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_SYSTEM_UNIX)) - -typedef struct _GtkFileSystemUnix GtkFileSystemUnix; - -GtkFileSystem *gtk_file_system_unix_new (void); -GType gtk_file_system_unix_get_type (void) G_GNUC_CONST; - -G_END_DECLS - -#endif /* __GTK_FILE_SYSTEM_UNIX_H__ */ diff --git a/gtk/gtkfilesystemwin32.c b/gtk/gtkfilesystemwin32.c deleted file mode 100644 index 3fc8a088e..000000000 --- a/gtk/gtkfilesystemwin32.c +++ /dev/null @@ -1,2771 +0,0 @@ -/* GTK - The GIMP Toolkit - * gtkfilesystemwin32.c: Default implementation of GtkFileSystem for Windows - * Copyright (C) 2003, Red Hat, Inc. - * Copyright (C) 2004, Hans Breuer - * Copyright (C) 2007, Novell, Inc. - * Copyright (C) 2007, Mathias Hasselmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* #define this if you want the program to crash when a file system gets - * finalized while async handles are still outstanding. - */ -#undef HANDLE_ME_HARDER - -#include - -#include "gtkfilesystem.h" -#include "gtkfilesystemwin32.h" -#include "gtkicontheme.h" -#include "gtkintl.h" -#include "gtkstock.h" -#include "gtkiconfactory.h" -#include "gtkalias.h" - -#include - -#include -#include -#include -#include -#include - -#define WIN32_LEAN_AND_MEAN -#define STRICT -#include "gdk/win32/gdkwin32.h" -#undef STRICT -#include -#include -#include - -#define BOOKMARKS_FILENAME ".gtk-bookmarks" - -#define FOLDER_CACHE_LIFETIME 2 /* seconds */ - -typedef struct _GtkFileSystemWin32Class GtkFileSystemWin32Class; - -#define GTK_FILE_SYSTEM_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SYSTEM_WIN32, GtkFileSystemWin32Class)) -#define GTK_IS_FILE_SYSTEM_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SYSTEM_WIN32)) -#define GTK_FILE_SYSTEM_WIN32_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_SYSTEM_WIN32, GtkFileSystemWin32Class)) - -struct _GtkFileSystemWin32Class -{ - GObjectClass parent_class; -}; - -struct _GtkFileSystemWin32 -{ - GObject parent_instance; - - guint32 drives; /* bitmask as returned by GetLogicalDrives() */ - GHashTable *folder_hash; - guint timeout; - - GHashTable *handles; - - guint execute_callbacks_idle_id; - GSList *callbacks; -}; - -/* Icon type, supplemented by MIME type - */ -typedef enum { - ICON_UNDECIDED, /* Only used while we have not yet computed the icon in a struct stat_info_entry */ - ICON_NONE, /* "Could not compute the icon type" */ - ICON_REGULAR, /* Use mime type for icon */ - ICON_DIRECTORY, - ICON_EXECUTABLE, - ICON_VOLUME -} IconType; - - -#define GTK_TYPE_FILE_FOLDER_WIN32 (_gtk_file_folder_win32_get_type ()) -#define GTK_FILE_FOLDER_WIN32(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_FOLDER_WIN32, GtkFileFolderWin32)) -#define GTK_IS_FILE_FOLDER_WIN32(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_FOLDER_WIN32)) -#define GTK_FILE_FOLDER_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_FOLDER_WIN32, GtkFileFolderWin32Class)) -#define GTK_IS_FILE_FOLDER_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_FOLDER_WIN32)) -#define GTK_FILE_FOLDER_WIN32_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_FOLDER_WIN32, GtkFileFolderWin32Class)) - -typedef struct _GtkFileFolderWin32 GtkFileFolderWin32; -typedef struct _GtkFileFolderWin32Class GtkFileFolderWin32Class; - -struct _GtkFileFolderWin32Class -{ - GObjectClass parent_class; -}; - -struct _GtkFileFolderWin32 -{ - GObject parent_instance; - - GtkFileSystemWin32 *system_win32; - GtkFileInfoType types; - gchar *filename; - GHashTable *stat_info; - guint load_folder_id; - guint have_stat : 1; - guint have_mime_type : 1; - guint is_network_dir : 1; - guint is_finished_loading : 1; - time_t asof; -}; - -struct stat_info_entry { - WIN32_FILE_ATTRIBUTE_DATA wfad; - char *mime_type; - IconType icon_type; - gboolean hidden; -}; - -static const GtkFileInfoType STAT_NEEDED_MASK = (GTK_FILE_INFO_IS_FOLDER | - GTK_FILE_INFO_MODIFICATION_TIME | - GTK_FILE_INFO_SIZE | - GTK_FILE_INFO_ICON); - -static void gtk_file_system_win32_iface_init (GtkFileSystemIface *iface); -static void gtk_file_system_win32_dispose (GObject *object); -static void gtk_file_system_win32_finalize (GObject *object); - -static GSList * gtk_file_system_win32_list_volumes (GtkFileSystem *file_system); -static GtkFileSystemVolume *gtk_file_system_win32_get_volume_for_path (GtkFileSystem *file_system, - const GtkFilePath *path); - -static GtkFileSystemHandle *gtk_file_system_win32_get_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetFolderCallback callback, - gpointer data); -static GtkFileSystemHandle *gtk_file_system_win32_get_info (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetInfoCallback callback, - gpointer data); -static GtkFileSystemHandle *gtk_file_system_win32_create_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileSystemCreateFolderCallback callback, - gpointer data); -static void gtk_file_system_win32_cancel_operation (GtkFileSystemHandle *handle); - -static void gtk_file_system_win32_volume_free (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -static GtkFilePath *gtk_file_system_win32_volume_get_base_path (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -static gboolean gtk_file_system_win32_volume_get_is_mounted (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -static GtkFileSystemHandle *gtk_file_system_win32_volume_mount (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GtkFileSystemVolumeMountCallback callback, - gpointer data); -static gchar * gtk_file_system_win32_volume_get_display_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume); -static gchar * gtk_file_system_win32_volume_get_icon_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GError **error); - -static gboolean gtk_file_system_win32_get_parent (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFilePath **parent, - GError **error); -static GtkFilePath * gtk_file_system_win32_make_path (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *display_name, - GError **error); -static gboolean gtk_file_system_win32_parse (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *str, - GtkFilePath **folder, - gchar **file_part, - GError **error); - -static gchar * gtk_file_system_win32_path_to_uri (GtkFileSystem *file_system, - const GtkFilePath *path); -static gchar * gtk_file_system_win32_path_to_filename (GtkFileSystem *file_system, - const GtkFilePath *path); -static GtkFilePath *gtk_file_system_win32_uri_to_path (GtkFileSystem *file_system, - const gchar *uri); -static GtkFilePath *gtk_file_system_win32_filename_to_path (GtkFileSystem *file_system, - const gchar *filename); - - -static gboolean gtk_file_system_win32_insert_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - gint position, - GError **error); -static gboolean gtk_file_system_win32_remove_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - GError **error); -static GSList * gtk_file_system_win32_list_bookmarks (GtkFileSystem *file_system); -static gchar * gtk_file_system_win32_get_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path); -static void gtk_file_system_win32_set_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path, - const gchar *label); - -static void gtk_file_folder_win32_iface_init (GtkFileFolderIface *iface); -static void gtk_file_folder_win32_finalize (GObject *object); - -static GtkFileInfo *gtk_file_folder_win32_get_info (GtkFileFolder *folder, - const GtkFilePath *path, - GError **error); -static gboolean gtk_file_folder_win32_list_children (GtkFileFolder *folder, - GSList **children, - GError **error); - -static gboolean gtk_file_folder_win32_is_finished_loading (GtkFileFolder *folder); - -static GtkFilePath *filename_to_path (const gchar *filename); - -static gboolean filename_is_root (const char *filename); - -static gboolean filename_is_drive_root (const char *filename); -static gboolean filename_is_some_root (const char *filename); - -static gboolean stat_with_error (const char *filename, - WIN32_FILE_ATTRIBUTE_DATA *wfad, - GError **error); -static GtkFileInfo *create_file_info (GtkFileFolderWin32 *folder_win32, - const char *filename, - GtkFileInfoType types, - WIN32_FILE_ATTRIBUTE_DATA *wfad, - const char *mime_type); - -static gboolean execute_callbacks (gpointer data); - -static gboolean fill_in_names (GtkFileFolderWin32 *folder_win32, - GError **error); -static void fill_in_stats (GtkFileFolderWin32 *folder_win32); -static void fill_in_mime_type (GtkFileFolderWin32 *folder_win32); - -static gboolean cb_fill_in_stats (gpointer key, - gpointer value, - gpointer user_data); -static gboolean cb_fill_in_mime_type (gpointer key, - gpointer value, - gpointer user_data); - -/* some info kept together for volumes */ -struct _GtkFileSystemVolume -{ - gchar *drive; - int drive_type; -}; - -/* - * GtkFileSystemWin32 - */ -G_DEFINE_TYPE_WITH_CODE (GtkFileSystemWin32, gtk_file_system_win32, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_SYSTEM, - gtk_file_system_win32_iface_init)) - -/* - * GtkFileFolderWin32 - */ -G_DEFINE_TYPE_WITH_CODE (GtkFileFolderWin32, _gtk_file_folder_win32, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_FOLDER, - gtk_file_folder_win32_iface_init)) - -/** - * gtk_file_system_win32_new: - * - * Creates a new #GtkFileSystemWin32 object. #GtkFileSystemWin32 - * implements the #GtkFileSystem interface with direct access to - * the filesystem using Windows API calls - * - * Return value: the new #GtkFileSystemWin32 object - **/ -GtkFileSystem * -gtk_file_system_win32_new (void) -{ - return g_object_new (GTK_TYPE_FILE_SYSTEM_WIN32, NULL); -} - -static void -gtk_file_system_win32_class_init (GtkFileSystemWin32Class *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - - gobject_class->dispose = gtk_file_system_win32_dispose; - gobject_class->finalize = gtk_file_system_win32_finalize; -} - -static void -gtk_file_system_win32_iface_init (GtkFileSystemIface *iface) -{ - iface->list_volumes = gtk_file_system_win32_list_volumes; - iface->get_volume_for_path = gtk_file_system_win32_get_volume_for_path; - iface->get_folder = gtk_file_system_win32_get_folder; - iface->get_info = gtk_file_system_win32_get_info; - iface->create_folder = gtk_file_system_win32_create_folder; - iface->cancel_operation = gtk_file_system_win32_cancel_operation; - iface->volume_free = gtk_file_system_win32_volume_free; - iface->volume_get_base_path = gtk_file_system_win32_volume_get_base_path; - iface->volume_get_is_mounted = gtk_file_system_win32_volume_get_is_mounted; - iface->volume_mount = gtk_file_system_win32_volume_mount; - iface->volume_get_display_name = gtk_file_system_win32_volume_get_display_name; - iface->volume_get_icon_name = gtk_file_system_win32_volume_get_icon_name; - iface->get_parent = gtk_file_system_win32_get_parent; - iface->make_path = gtk_file_system_win32_make_path; - iface->parse = gtk_file_system_win32_parse; - iface->path_to_uri = gtk_file_system_win32_path_to_uri; - iface->path_to_filename = gtk_file_system_win32_path_to_filename; - iface->uri_to_path = gtk_file_system_win32_uri_to_path; - iface->filename_to_path = gtk_file_system_win32_filename_to_path; - iface->insert_bookmark = gtk_file_system_win32_insert_bookmark; - iface->remove_bookmark = gtk_file_system_win32_remove_bookmark; - iface->list_bookmarks = gtk_file_system_win32_list_bookmarks; - iface->get_bookmark_label = gtk_file_system_win32_get_bookmark_label; - iface->set_bookmark_label = gtk_file_system_win32_set_bookmark_label; -} - -/** - * get_viewable_logical_drives: - * - * Returns the list of logical and viewable drives as defined by - * GetLogicalDrives() and the registry keys - * Software\Microsoft\Windows\CurrentVersion\Policies\Explorer under - * HKLM or HKCU. If neither key exists the result of - * GetLogicalDrives() is returned. - * - * Return value: bitmask with same meaning as returned by GetLogicalDrives() -**/ -static guint32 -get_viewable_logical_drives (void) -{ - guint viewable_drives = GetLogicalDrives (); - HKEY key; - - DWORD var_type = REG_DWORD; //the value's a REG_DWORD type - DWORD no_drives_size = 4; - DWORD no_drives; - gboolean hklm_present = FALSE; - - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, - "Software\\Microsoft\\Windows\\" - "CurrentVersion\\Policies\\Explorer", - 0, KEY_READ, &key) == ERROR_SUCCESS) - { - if (RegQueryValueEx (key, "NoDrives", NULL, &var_type, - (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS) - { - /* We need the bits that are set in viewable_drives, and - * unset in no_drives. - */ - viewable_drives = viewable_drives & ~no_drives; - hklm_present = TRUE; - } - RegCloseKey (key); - } - - /* If the key is present in HKLM then the one in HKCU should be ignored */ - if (!hklm_present) - { - if (RegOpenKeyEx (HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\" - "CurrentVersion\\Policies\\Explorer", - 0, KEY_READ, &key) == ERROR_SUCCESS) - { - if (RegQueryValueEx (key, "NoDrives", NULL, &var_type, - (LPBYTE) &no_drives, &no_drives_size) == ERROR_SUCCESS) - { - viewable_drives = viewable_drives & ~no_drives; - } - RegCloseKey (key); - } - } - - return viewable_drives; -} - -static gboolean -check_volumes (gpointer data) -{ - GtkFileSystemWin32 *system_win32 = GTK_FILE_SYSTEM_WIN32 (data); - - g_return_val_if_fail (system_win32, FALSE); - - if (system_win32->drives != get_viewable_logical_drives ()) - { - g_signal_emit_by_name (system_win32, "volumes-changed", 0); - } - - return TRUE; -} - -static guint -casefolded_hash (gconstpointer v) -{ - const gchar *p = (const gchar *) v; - guint32 h = 0; - - while (*p) - { - h = (h << 5) - h + g_unichar_toupper (g_utf8_get_char (p)); - p = g_utf8_next_char (p); - } - - return h; -} - -static gboolean casefolded_equal (gconstpointer v1, - gconstpointer v2) -{ - return (_gtk_file_system_win32_path_compare ((const gchar *) v1, (const gchar *) v2) == 0); -} - -static void -gtk_file_system_win32_init (GtkFileSystemWin32 *system_win32) -{ - system_win32->folder_hash = g_hash_table_new (casefolded_hash, casefolded_equal); - - /* Set up an idle handler for volume changes. Once a second should - * be enough. - */ - system_win32->timeout = gdk_threads_add_timeout_full (0, 1000, check_volumes, system_win32, NULL); - - system_win32->handles = g_hash_table_new (g_direct_hash, g_direct_equal); - - system_win32->execute_callbacks_idle_id = 0; - system_win32->callbacks = NULL; -} - -static void -check_handle_fn (gpointer key, gpointer value, gpointer data) -{ - GtkFileSystemHandle *handle; - int *num_live_handles; - - handle = key; - num_live_handles = data; - - (*num_live_handles)++; - - g_warning ("file_system_win32=%p still has handle=%p at finalization which is %s!", - handle->file_system, - handle, - handle->cancelled ? "CANCELLED" : "NOT CANCELLED"); -} - -static void -check_handles_at_finalization (GtkFileSystemWin32 *system_win32) -{ - int num_live_handles; - - num_live_handles = 0; - - g_hash_table_foreach (system_win32->handles, check_handle_fn, &num_live_handles); -#ifdef HANDLE_ME_HARDER - g_assert (num_live_handles == 0); -#endif - - g_hash_table_destroy (system_win32->handles); - system_win32->handles = NULL; -} - -#define GTK_TYPE_FILE_SYSTEM_HANDLE_WIN32 (_gtk_file_system_handle_win32_get_type ()) - -typedef struct _GtkFileSystemHandle GtkFileSystemHandleWin32; -typedef struct _GtkFileSystemHandleClass GtkFileSystemHandleWin32Class; - -G_DEFINE_TYPE (GtkFileSystemHandleWin32, _gtk_file_system_handle_win32, GTK_TYPE_FILE_SYSTEM_HANDLE) - -static void -_gtk_file_system_handle_win32_init (GtkFileSystemHandleWin32 *handle) -{ -} - -static void -_gtk_file_system_handle_win32_finalize (GObject *object) -{ - GtkFileSystemHandleWin32 *handle; - GtkFileSystemWin32 *system_win32; - - handle = (GtkFileSystemHandleWin32 *)object; - - system_win32 = GTK_FILE_SYSTEM_WIN32 (GTK_FILE_SYSTEM_HANDLE (handle)->file_system); - - g_assert (g_hash_table_lookup (system_win32->handles, handle) != NULL); - g_hash_table_remove (system_win32->handles, handle); - - if (G_OBJECT_CLASS (_gtk_file_system_handle_win32_parent_class)->finalize) - G_OBJECT_CLASS (_gtk_file_system_handle_win32_parent_class)->finalize (object); -} - -static void -_gtk_file_system_handle_win32_class_init (GtkFileSystemHandleWin32Class *class) -{ - GObjectClass *gobject_class = (GObjectClass *) class; - - gobject_class->finalize = _gtk_file_system_handle_win32_finalize; -} - -static void -gtk_file_system_win32_dispose (GObject *object) -{ - GtkFileSystemWin32 *system_win32; - - system_win32 = GTK_FILE_SYSTEM_WIN32 (object); - - if (system_win32->execute_callbacks_idle_id) - { - g_source_remove (system_win32->execute_callbacks_idle_id); - system_win32->execute_callbacks_idle_id = 0; - - /* call pending callbacks */ - execute_callbacks (system_win32); - } - - G_OBJECT_CLASS (gtk_file_system_win32_parent_class)->dispose (object); -} - -static void -gtk_file_system_win32_finalize (GObject *object) -{ - GtkFileSystemWin32 *system_win32; - - system_win32 = GTK_FILE_SYSTEM_WIN32 (object); - - g_source_remove (system_win32->timeout); - - check_handles_at_finalization (system_win32); - - /* FIXME: assert that the hash is empty? */ - g_hash_table_destroy (system_win32->folder_hash); - - G_OBJECT_CLASS (gtk_file_system_win32_parent_class)->finalize (object); -} - -/* Lifted from GLib */ - -static gchar * -get_special_folder (int csidl) -{ - union { - char c[MAX_PATH+1]; - wchar_t wc[MAX_PATH+1]; - } path; - HRESULT hr; - LPITEMIDLIST pidl = NULL; - BOOL b; - gchar *retval = NULL; - - hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl); - if (hr == S_OK) - { - b = SHGetPathFromIDListW (pidl, path.wc); - if (b) - retval = g_utf16_to_utf8 (path.wc, -1, NULL, NULL, NULL); - CoTaskMemFree (pidl); - } - return retval; -} - -gchar * -_gtk_file_system_win32_get_desktop (void) -{ - return get_special_folder (CSIDL_DESKTOPDIRECTORY); -} - -static GSList * -gtk_file_system_win32_list_volumes (GtkFileSystem *file_system) -{ - DWORD drives; - gchar drive[4] = "A:\\"; - GSList *list = NULL; - GtkFileSystemWin32 *system_win32 = (GtkFileSystemWin32 *)file_system; - - drives = get_viewable_logical_drives (); - - system_win32->drives = drives; - if (!drives) - g_warning ("get_viewable_logical_drives failed."); - - while (drives && drive[0] <= 'Z') - { - if (drives & 1) - { - GtkFileSystemVolume *vol = g_new0 (GtkFileSystemVolume, 1); - vol->drive = g_strdup (drive); - vol->drive_type = GetDriveType (drive); - list = g_slist_append (list, vol); - } - drives >>= 1; - drive[0]++; - } - return list; -} - -static GtkFileSystemVolume * -gtk_file_system_win32_get_volume_for_path (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - GtkFileSystemVolume *vol = g_new0 (GtkFileSystemVolume, 1); - const gchar *p; - - g_return_val_if_fail (path != NULL, NULL); - - p = gtk_file_path_get_string (path); - - if (!g_path_is_absolute (p)) - { - if (g_ascii_isalpha (p[0]) && p[1] == ':') - vol->drive = g_strdup_printf ("%c:\\", p[0]); - else - vol->drive = g_strdup ("\\"); - vol->drive_type = GetDriveType (vol->drive); - } - else - { - const gchar *q = g_path_skip_root (p); - vol->drive = g_strndup (p, q - p); - if (!G_IS_DIR_SEPARATOR (q[-1])) - { - /* Make sure "drive" always ends in a slash */ - gchar *tem = vol->drive; - vol->drive = g_strconcat (vol->drive, "\\", NULL); - g_free (tem); - } - - if (filename_is_drive_root (vol->drive)) - { - vol->drive[0] = g_ascii_toupper (vol->drive[0]); - vol->drive_type = GetDriveType (vol->drive); - } - else - { - wchar_t *wdrive = g_utf8_to_utf16 (vol->drive, -1, NULL, NULL, NULL); - vol->drive_type = GetDriveTypeW (wdrive); - g_free (wdrive); - } - } - return vol; -} - -static char * -remove_trailing_slash (const char *filename) -{ - int root_len, len; - - len = strlen (filename); - - if (g_path_is_absolute (filename)) - root_len = g_path_skip_root (filename) - filename; - else - root_len = 1; - if (len > root_len && G_IS_DIR_SEPARATOR (filename[len - 1])) - return g_strndup (filename, len - 1); - else - return g_memdup (filename, len + 1); -} - -/* Delay callback dispatching - */ - -enum callback_types -{ - CALLBACK_GET_INFO, - CALLBACK_GET_FOLDER, - CALLBACK_CREATE_FOLDER, - CALLBACK_VOLUME_MOUNT -}; - -static void queue_callback (GtkFileSystemWin32 *system_win32, enum callback_types type, gpointer data); - -struct get_info_callback -{ - GtkFileSystemGetInfoCallback callback; - GtkFileSystemHandle *handle; - GtkFileInfo *file_info; - GError *error; - gpointer data; -}; - -static inline void -dispatch_get_info_callback (struct get_info_callback *info) -{ - (* info->callback) (info->handle, info->file_info, info->error, info->data); - - if (info->file_info) - gtk_file_info_free (info->file_info); - - if (info->error) - g_error_free (info->error); - - g_object_unref (info->handle); - - g_free (info); -} - -static inline void -queue_get_info_callback (GtkFileSystemGetInfoCallback callback, - GtkFileSystemHandle *handle, - GtkFileInfo *file_info, - GError *error, - gpointer data) -{ - struct get_info_callback *info; - - info = g_new (struct get_info_callback, 1); - info->callback = callback; - info->handle = handle; - info->file_info = file_info; - info->error = error; - info->data = data; - - queue_callback (GTK_FILE_SYSTEM_WIN32 (handle->file_system), CALLBACK_GET_INFO, info); -} - - -struct get_folder_callback -{ - GtkFileSystemGetFolderCallback callback; - GtkFileSystemHandle *handle; - GtkFileFolder *folder; - GError *error; - gpointer data; -}; - -static inline void -dispatch_get_folder_callback (struct get_folder_callback *info) -{ - (* info->callback) (info->handle, info->folder, info->error, info->data); - - if (info->error) - g_error_free (info->error); - - g_object_unref (info->handle); - - g_free (info); -} - -static inline void -queue_get_folder_callback (GtkFileSystemGetFolderCallback callback, - GtkFileSystemHandle *handle, - GtkFileFolder *folder, - GError *error, - gpointer data) -{ - struct get_folder_callback *info; - - info = g_new (struct get_folder_callback, 1); - info->callback = callback; - info->handle = handle; - info->folder = folder; - info->error = error; - info->data = data; - - queue_callback (GTK_FILE_SYSTEM_WIN32 (handle->file_system), CALLBACK_GET_FOLDER, info); -} - - -struct create_folder_callback -{ - GtkFileSystemCreateFolderCallback callback; - GtkFileSystemHandle *handle; - GtkFilePath *path; - GError *error; - gpointer data; -}; - -static inline void -dispatch_create_folder_callback (struct create_folder_callback *info) -{ - (* info->callback) (info->handle, info->path, info->error, info->data); - - if (info->error) - g_error_free (info->error); - - if (info->path) - gtk_file_path_free (info->path); - - g_object_unref (info->handle); - - g_free (info); -} - -static inline void -queue_create_folder_callback (GtkFileSystemCreateFolderCallback callback, - GtkFileSystemHandle *handle, - const GtkFilePath *path, - GError *error, - gpointer data) -{ - struct create_folder_callback *info; - - info = g_new (struct create_folder_callback, 1); - info->callback = callback; - info->handle = handle; - info->path = gtk_file_path_copy (path); - info->error = error; - info->data = data; - - queue_callback (GTK_FILE_SYSTEM_WIN32 (handle->file_system), CALLBACK_CREATE_FOLDER, info); -} - - -struct volume_mount_callback -{ - GtkFileSystemVolumeMountCallback callback; - GtkFileSystemHandle *handle; - GtkFileSystemVolume *volume; - GError *error; - gpointer data; -}; - -static inline void -dispatch_volume_mount_callback (struct volume_mount_callback *info) -{ - (* info->callback) (info->handle, info->volume, info->error, info->data); - - if (info->error) - g_error_free (info->error); - - g_object_unref (info->handle); - - g_free (info); -} - -static inline void -queue_volume_mount_callback (GtkFileSystemVolumeMountCallback callback, - GtkFileSystemHandle *handle, - GtkFileSystemVolume *volume, - GError *error, - gpointer data) -{ - struct volume_mount_callback *info; - - info = g_new (struct volume_mount_callback, 1); - info->callback = callback; - info->handle = handle; - info->volume = volume; - info->error = error; - info->data = data; - - queue_callback (GTK_FILE_SYSTEM_WIN32 (handle->file_system), CALLBACK_VOLUME_MOUNT, info); -} - - -struct callback_info -{ - enum callback_types type; - - union - { - struct get_info_callback *get_info; - struct get_folder_callback *get_folder; - struct create_folder_callback *create_folder; - struct volume_mount_callback *volume_mount; - } info; -}; - - - -static gboolean -execute_callbacks (gpointer data) -{ - GSList *l; - gboolean unref_file_system = TRUE; - GtkFileSystemWin32 *system_win32 = GTK_FILE_SYSTEM_WIN32 (data); - - if (!system_win32->execute_callbacks_idle_id) - unref_file_system = FALSE; - else - g_object_ref (system_win32); - - for (l = system_win32->callbacks; l; l = l->next) - { - struct callback_info *info = l->data; - - switch (info->type) - { - case CALLBACK_GET_INFO: - dispatch_get_info_callback (info->info.get_info); - break; - - case CALLBACK_GET_FOLDER: - dispatch_get_folder_callback (info->info.get_folder); - break; - - case CALLBACK_CREATE_FOLDER: - dispatch_create_folder_callback (info->info.create_folder); - break; - - case CALLBACK_VOLUME_MOUNT: - dispatch_volume_mount_callback (info->info.volume_mount); - break; - } - - g_free (info); - } - - g_slist_free (system_win32->callbacks); - system_win32->callbacks = NULL; - - if (unref_file_system) - g_object_unref (system_win32); - - system_win32->execute_callbacks_idle_id = 0; - - return FALSE; -} - -static void -queue_callback (GtkFileSystemWin32 *system_win32, - enum callback_types type, - gpointer data) -{ - struct callback_info *info; - - info = g_new (struct callback_info, 1); - info->type = type; - - switch (type) - { - case CALLBACK_GET_INFO: - info->info.get_info = data; - break; - - case CALLBACK_GET_FOLDER: - info->info.get_folder = data; - break; - - case CALLBACK_CREATE_FOLDER: - info->info.create_folder = data; - break; - - case CALLBACK_VOLUME_MOUNT: - info->info.volume_mount = data; - break; - } - - system_win32->callbacks = g_slist_append (system_win32->callbacks, info); - - if (!system_win32->execute_callbacks_idle_id) - system_win32->execute_callbacks_idle_id = gdk_threads_add_idle (execute_callbacks, system_win32); -} - -static GtkFileSystemHandle * -create_handle (GtkFileSystem *file_system) -{ - GtkFileSystemWin32 *system_win32; - GtkFileSystemHandle *handle; - - system_win32 = GTK_FILE_SYSTEM_WIN32 (file_system); - - handle = g_object_new (GTK_TYPE_FILE_SYSTEM_HANDLE_WIN32, NULL); - handle->file_system = file_system; - - g_assert (g_hash_table_lookup (system_win32->handles, handle) == NULL); - g_hash_table_insert (system_win32->handles, handle, handle); - - return handle; -} - -static char * -get_mime_type_for_file (const char *filename, - const WIN32_FILE_ATTRIBUTE_DATA *wfad) -{ - const char *extension; - HKEY key = NULL; - DWORD type, nbytes = 0; - char *value = NULL; - - if (wfad->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - return g_strdup ("x-directory/normal"); - - extension = strrchr (filename, '.'); - - if (extension != NULL && - (stricmp (extension, ".exe") == 0 || - stricmp (extension, ".com") == 0)) - return g_strdup ("application/x-executable"); - - if (extension != NULL && - extension[1] != '\0' && - RegOpenKeyEx (HKEY_CLASSES_ROOT, extension, 0, - KEY_QUERY_VALUE, &key) == ERROR_SUCCESS && - RegQueryValueEx (key, "Content Type", 0, - &type, NULL, &nbytes) == ERROR_SUCCESS && - type == REG_SZ && - (value = g_try_malloc (nbytes + 1)) && - RegQueryValueEx (key, "Content Type", 0, - &type, value, &nbytes) == ERROR_SUCCESS) - { - value[nbytes] = '\0'; - } - else - value = g_strdup ("application/octet-stream"); - if (key != NULL) - RegCloseKey (key); - - return value; -} - -static GtkFileSystemHandle * -gtk_file_system_win32_get_info (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetInfoCallback callback, - gpointer data) -{ - GError *error = NULL; - GtkFileSystemWin32 *system_win32; - GtkFileSystemHandle *handle; - const char *filename; - GtkFileInfo *info; - WIN32_FILE_ATTRIBUTE_DATA wfad; - const char *mime_type; - - system_win32 = GTK_FILE_SYSTEM_WIN32 (file_system); - handle = create_handle (file_system); - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (filename), NULL); - - if (!stat_with_error (filename, &wfad, &error)) - { - g_object_ref (handle); - queue_get_info_callback (callback, handle, NULL, error, data); - return handle; - } - - if ((types & GTK_FILE_INFO_MIME_TYPE) != 0) - mime_type = get_mime_type_for_file (filename, &wfad); - else - mime_type = NULL; - - info = create_file_info (NULL, filename, types, &wfad, mime_type); - g_object_ref (handle); - queue_get_info_callback (callback, handle, info, NULL, data); - - return handle; -} - -static gboolean -load_folder (gpointer data) -{ - GtkFileFolderWin32 *folder_win32 = data; - GSList *children; - - if ((folder_win32->types & STAT_NEEDED_MASK) != 0) - fill_in_stats (folder_win32); - - if ((folder_win32->types & GTK_FILE_INFO_MIME_TYPE) != 0) - fill_in_mime_type (folder_win32); - - if (gtk_file_folder_win32_list_children (GTK_FILE_FOLDER (folder_win32), &children, NULL)) - { - folder_win32->is_finished_loading = TRUE; - g_signal_emit_by_name (folder_win32, "files-added", children); - gtk_file_paths_free (children); - } - - folder_win32->load_folder_id = 0; - - g_signal_emit_by_name (folder_win32, "finished-loading", 0); - - return FALSE; -} - -static GtkFileSystemHandle * -gtk_file_system_win32_get_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileInfoType types, - GtkFileSystemGetFolderCallback callback, - gpointer data) -{ - GError *error = NULL; - GtkFileSystemWin32 *system_win32; - GtkFileFolderWin32 *folder_win32; - GtkFileSystemHandle *handle; - const gchar *filename; - char *filename_copy; - gboolean set_asof = FALSE; - - system_win32 = GTK_FILE_SYSTEM_WIN32 (file_system); - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (filename), NULL); - - handle = create_handle (file_system); - - filename_copy = remove_trailing_slash (filename); - folder_win32 = g_hash_table_lookup (system_win32->folder_hash, filename_copy); - - if (folder_win32) - { - g_free (filename_copy); - if (folder_win32->stat_info && - time (NULL) - folder_win32->asof >= FOLDER_CACHE_LIFETIME) - { -#if 0 - g_print ("Cleaning out cached directory %s\n", filename); -#endif - g_hash_table_destroy (folder_win32->stat_info); - folder_win32->stat_info = NULL; - folder_win32->have_mime_type = FALSE; - folder_win32->have_stat = FALSE; - set_asof = TRUE; - } - - g_object_ref (folder_win32); - folder_win32->types |= types; - types = folder_win32->types; - } - else - { - WIN32_FILE_ATTRIBUTE_DATA wfad; - - if (!stat_with_error (filename, &wfad, &error)) - { - g_object_ref (handle); - queue_get_folder_callback (callback, handle, NULL, error, data); - - g_free (filename_copy); - return handle; - } - - if (!wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - gchar *display_name = g_filename_display_name (filename); - - g_set_error (&error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_NOT_FOLDER, - _("Path is not a folder: '%s'"), - display_name); - - g_object_ref (handle); - queue_get_folder_callback (callback, handle, NULL, error, data); - - g_free (display_name); - g_free (filename_copy); - return handle; - } - - folder_win32 = g_object_new (GTK_TYPE_FILE_FOLDER_WIN32, NULL); - folder_win32->system_win32 = system_win32; - folder_win32->filename = filename_copy; - folder_win32->types = types; - folder_win32->stat_info = NULL; - folder_win32->load_folder_id = 0; - folder_win32->have_mime_type = FALSE; - folder_win32->have_stat = FALSE; - folder_win32->is_finished_loading = FALSE; - set_asof = TRUE; - - /* Browsing for shares not yet implemented */ - folder_win32->is_network_dir = FALSE; - - g_hash_table_insert (system_win32->folder_hash, - folder_win32->filename, - folder_win32); - } - - if (set_asof) - folder_win32->asof = time (NULL); - - g_object_ref (handle); - queue_get_folder_callback (callback, handle, GTK_FILE_FOLDER (folder_win32), NULL, data); - - /* Start loading the folder contents in an idle */ - if (!folder_win32->load_folder_id) - folder_win32->load_folder_id = - gdk_threads_add_idle ((GSourceFunc) load_folder, folder_win32); - - return handle; -} - -static GtkFileSystemHandle * -gtk_file_system_win32_create_folder (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFileSystemCreateFolderCallback callback, - gpointer data) -{ - GError *error = NULL; - GtkFileSystemWin32 *system_win32; - GtkFileSystemHandle *handle; - const char *filename; - gboolean result; - char *parent, *tmp; - int save_errno; - - system_win32 = GTK_FILE_SYSTEM_WIN32 (file_system); - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (filename), NULL); - - handle = create_handle (file_system); - - tmp = remove_trailing_slash (filename); - result = g_mkdir (tmp, 0777) == 0; - save_errno = errno; - g_free (tmp); - - if (!result) - { - gchar *display_filename = g_filename_display_name (filename); - g_set_error (&error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_NONEXISTENT, - _("Error creating folder '%s': %s"), - display_filename, - g_strerror (save_errno)); - - g_object_ref (handle); - queue_create_folder_callback (callback, handle, path, error, data); - - g_free (display_filename); - return handle; - } - - if (!filename_is_some_root (filename)) - { - parent = g_path_get_dirname (filename); - if (parent) - { - GtkFileFolderWin32 *folder_win32; - - folder_win32 = g_hash_table_lookup (system_win32->folder_hash, parent); - if (folder_win32) - { - GSList *paths; - char *basename; - struct stat_info_entry *entry; - - /* Make sure the new folder exists in the parent's folder */ - entry = g_new0 (struct stat_info_entry, 1); - if (folder_win32->is_network_dir) - { - entry->wfad.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; - entry->mime_type = g_strdup ("x-directory/normal"); - } - - basename = g_path_get_basename (filename); - g_hash_table_insert (folder_win32->stat_info, - basename, - entry); - - if (folder_win32->have_stat) - { - /* Cheating */ - if ((folder_win32->types & STAT_NEEDED_MASK) != 0) - cb_fill_in_stats (basename, entry, folder_win32); - - if ((folder_win32->types & GTK_FILE_INFO_MIME_TYPE) != 0) - cb_fill_in_mime_type (basename, entry, folder_win32); - } - - paths = g_slist_append (NULL, (GtkFilePath *) path); - g_signal_emit_by_name (folder_win32, "files-added", paths); - g_slist_free (paths); - } - - g_free(parent); - } - } - - return handle; -} - -static void -gtk_file_system_win32_cancel_operation (GtkFileSystemHandle *handle) -{ - /* We don't set "cancelled" to TRUE here, since the actual operation - * is executed in the function itself and not in a callback. So - * the operations can never be cancelled (since they will be already - * completed at this point. - */ -} - -static void -gtk_file_system_win32_volume_free (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) -{ - GtkFilePath *path; - - g_free (volume->drive); - path = (GtkFilePath *) volume; - gtk_file_path_free (path); -} - -static GtkFilePath * -gtk_file_system_win32_volume_get_base_path (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) -{ - return (GtkFilePath *) g_strdup (volume->drive); -} - -static gboolean -gtk_file_system_win32_volume_get_is_mounted (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) -{ - return TRUE; -} - -static GtkFileSystemHandle * -gtk_file_system_win32_volume_mount (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GtkFileSystemVolumeMountCallback callback, - gpointer data) -{ - GError *error = NULL; - GtkFileSystemHandle *handle = create_handle (file_system); - - g_set_error (&error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_FAILED, - _("This file system does not support mounting")); - - g_object_ref (handle); - queue_volume_mount_callback (callback, handle, volume, error, data); - - return handle; -} - -static gchar * -gtk_file_system_win32_volume_get_display_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume) -{ - gchar *real_display_name; - - g_return_val_if_fail (volume->drive != NULL, NULL); - - if (filename_is_drive_root (volume->drive) && - volume->drive_type == DRIVE_REMOTE) - real_display_name = g_strdup_printf (_("Network Drive (%s)"), volume->drive); - else if ((filename_is_drive_root (volume->drive) && volume->drive[0] >= 'C') || - volume->drive_type != DRIVE_REMOVABLE) - { - gchar *name = NULL; - gunichar2 *wdrive = g_utf8_to_utf16 (volume->drive, -1, NULL, NULL, NULL); - gunichar2 wname[80]; - - if (GetVolumeInformationW (wdrive, - wname, G_N_ELEMENTS(wname), - NULL, /* serial number */ - NULL, /* max. component length */ - NULL, /* fs flags */ - NULL, 0) /* fs type like FAT, NTFS */ && - wname[0]) - { - name = g_utf16_to_utf8 (wname, -1, NULL, NULL, NULL); - } - g_free (wdrive); - - if (name != NULL) - { - real_display_name = g_strdup_printf (_("%s (%s)"), name, volume->drive); - g_free (name); - } - else - { - real_display_name = g_strdup (volume->drive); - } - } - else - real_display_name = g_strdup (volume->drive); - - return real_display_name; -} - -static IconType -get_icon_type_from_stat (WIN32_FILE_ATTRIBUTE_DATA *wfad) -{ - if (wfad->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - return ICON_DIRECTORY; - else - return ICON_REGULAR; -} - -/* Computes our internal icon type based on a path name; also returns the MIME - * type in case we come up with ICON_REGULAR. - */ -static IconType -get_icon_type_from_path (GtkFileFolderWin32 *folder_win32, - WIN32_FILE_ATTRIBUTE_DATA *wfad, - const char *filename) -{ - IconType icon_type; - - if (folder_win32 && folder_win32->have_stat) - { - char *basename; - struct stat_info_entry *entry; - - g_assert (folder_win32->stat_info != NULL); - - basename = g_path_get_basename (filename); - entry = g_hash_table_lookup (folder_win32->stat_info, basename); - g_free (basename); - if (entry) - { - if (entry->icon_type == ICON_UNDECIDED) - { - entry->icon_type = get_icon_type_from_stat (&entry->wfad); - g_assert (entry->icon_type != ICON_UNDECIDED); - } - icon_type = entry->icon_type; - if (icon_type == ICON_REGULAR) - { - fill_in_mime_type (folder_win32); - } - - return icon_type; - } - } - - icon_type = get_icon_type_from_stat (wfad); - - return icon_type; -} - -static const gchar * -get_fallback_icon_name (IconType icon_type) -{ - switch (icon_type) - { - case ICON_VOLUME: - return GTK_STOCK_HARDDISK; - - case ICON_DIRECTORY: - return GTK_STOCK_DIRECTORY; - - case ICON_EXECUTABLE: - return GTK_STOCK_EXECUTE; - - default: - return GTK_STOCK_FILE; - } -} - -static gchar * -get_icon_path (const gchar *filename, - IconType icon_type, - gint *index) -{ - gchar *path = NULL; - SHFILEINFOW shfi; - wchar_t *wfn; - - g_return_val_if_fail (NULL != filename, NULL); - g_return_val_if_fail ('\0' != *filename, NULL); - g_return_val_if_fail (NULL != index, NULL); - - wfn = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL); - - if (SHGetFileInfoW (wfn, 0, &shfi, sizeof (shfi), SHGFI_ICONLOCATION)) - { - path = g_utf16_to_utf8 (shfi.szDisplayName, -1, NULL, NULL, NULL); - *index = shfi.iIcon; - } - - g_free (wfn); - return path; -} - -static gboolean -create_builtin_icon (const gchar *filename, - const gchar *icon_name, - IconType icon_type) -{ - static const DWORD attributes[] = - { - SHGFI_ICON | SHGFI_LARGEICON, - SHGFI_ICON | SHGFI_SMALLICON, - 0 - }; - - GdkPixbuf *pixbuf = NULL; - SHFILEINFOW shfi; - DWORD_PTR rc; - wchar_t *wfn; - int i; - - g_return_val_if_fail (NULL != filename, FALSE); - g_return_val_if_fail ('\0' != *filename, FALSE); - - wfn = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL); - - for(i = 0; attributes[i]; ++i) - { - rc = SHGetFileInfoW (wfn, 0, &shfi, sizeof (shfi), attributes[i]); - - if (rc && shfi.hIcon) - { - pixbuf = gdk_win32_icon_to_pixbuf_libgtk_only (shfi.hIcon); - - if (!DestroyIcon (shfi.hIcon)) - g_warning (G_STRLOC ": DestroyIcon failed: %s\n", - g_win32_error_message (GetLastError ())); - - gtk_icon_theme_add_builtin_icon (icon_name, - gdk_pixbuf_get_height (pixbuf), - pixbuf); - g_object_unref (pixbuf); - } - } - - g_free (wfn); - return (NULL != pixbuf); /* at least one icon was created */ -} - -gchar * -get_icon_name (const gchar *filename, - IconType icon_type) -{ - gchar *icon_name = NULL; - gchar *icon_path = NULL; - gint icon_index = -1; - - icon_path = get_icon_path(filename, icon_type, &icon_index); - - if (icon_path) - icon_name = g_strdup_printf ("gtk-win32-shell-icon;%s;%d", - icon_path, icon_index); - else - icon_name = g_strdup_printf ("gtk-win32-shell-icon;%s", - filename); - - if (!gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), icon_name) && - !create_builtin_icon (filename, icon_name, icon_type)) - { - g_free (icon_name); - icon_name = g_strdup (get_fallback_icon_name (icon_type)); - } - - g_free (icon_path); - return icon_name; -} - -static gchar * -gtk_file_system_win32_volume_get_icon_name (GtkFileSystem *file_system, - GtkFileSystemVolume *volume, - GError **error) -{ - return get_icon_name (volume->drive, ICON_VOLUME); -} - -#if 0 /* Unused, see below */ - -static char * -get_parent_dir (const char *filename) -{ - int len; - - len = strlen (filename); - - /* Ignore trailing slashes */ - if (len > 1 && G_IS_DIR_SEPARATOR (filename[len - 1])) - { - char *tmp, *parent; - - tmp = g_strndup (filename, len - 1); - - parent = g_path_get_dirname (tmp); - g_free (tmp); - - return parent; - } - else - return g_path_get_dirname (filename); -} - -#endif - -static gboolean -gtk_file_system_win32_get_parent (GtkFileSystem *file_system, - const GtkFilePath *path, - GtkFilePath **parent, - GError **error) -{ - const char *filename; - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, FALSE); - g_return_val_if_fail (g_path_is_absolute (filename), FALSE); - - if (filename_is_some_root (filename)) - { - *parent = NULL; - } - else - { - gchar *parent_filename = g_path_get_dirname (filename); - *parent = filename_to_path (parent_filename); - g_free (parent_filename); - } -#if DEBUGGING_OUTPUT - printf ("%s: %s => %s\n", __FUNCTION__, (char*)path, (*parent)?(char*)*parent:"NULL"), fflush(stdout); -#endif - return TRUE; -} - -static GtkFilePath * -gtk_file_system_win32_make_path (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *display_name, - GError **error) -{ - const char *base_filename; - gchar *full_filename; - GtkFilePath *result; - char *p; - - base_filename = gtk_file_path_get_string (base_path); - g_return_val_if_fail (base_filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (base_filename), NULL); - - if ((p = strpbrk (display_name, "<>\"/\\|"))) - { - gchar badchar[2]; - - badchar[0] = *p; /* We know it is a single-byte char */ - badchar[1] = '\0'; - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_BAD_FILENAME, - _("The name \"%s\" is not valid because it contains the character \"%s\". " - "Please use a different name."), - display_name, - badchar); - return NULL; - } - - full_filename = g_build_filename (base_filename, display_name, NULL); - result = filename_to_path (full_filename); - g_free (full_filename); - - return result; -} - -/* If this was a publically exported function, it should return - * a dup'ed result, but we make it modify-in-place for efficiency - * here, and because it works for us. - */ -static void -canonicalize_filename (gchar *filename) -{ - gchar *p, *q; - gchar *past_root; - gboolean last_was_slash = FALSE; - -#if DEBUGGING_OUTPUT - printf("%s: %s ", __FUNCTION__, filename), fflush (stdout); -#endif - - past_root = (gchar *) g_path_skip_root (filename); - - q = p = past_root; - - while (*p) - { - if (G_IS_DIR_SEPARATOR (*p)) - { - if (!last_was_slash) - *q++ = '\\'; - - last_was_slash = TRUE; - } - else - { - if (last_was_slash && *p == '.') - { - if (G_IS_DIR_SEPARATOR (*(p + 1)) || - *(p + 1) == '\0') - { - if (*(p + 1) == '\0') - break; - - p += 1; - } - else if (*(p + 1) == '.' && - (G_IS_DIR_SEPARATOR (*(p + 2)) || - *(p + 2) == '\0')) - { - if (q > past_root) - { - q--; - while (q > past_root && - !G_IS_DIR_SEPARATOR (*(q - 1))) - q--; - } - - if (*(p + 2) == '\0') - break; - - p += 2; - } - else - { - *q++ = *p; - last_was_slash = FALSE; - } - } - else - { - *q++ = *p; - last_was_slash = FALSE; - } - } - - p++; - } - - if (q > past_root && G_IS_DIR_SEPARATOR (*(q - 1))) - q--; - - *q = '\0'; - -#if DEBUGGING_OUTPUT - printf(" => %s\n", filename), fflush (stdout); -#endif -} - -static gboolean -gtk_file_system_win32_parse (GtkFileSystem *file_system, - const GtkFilePath *base_path, - const gchar *str, - GtkFilePath **folder, - gchar **file_part, - GError **error) -{ - const char *base_filename; - gchar *last_backslash, *last_slash; - gboolean result = FALSE; - -#if DEBUGGING_OUTPUT - printf("%s: base_path=%s str=%s\n",__FUNCTION__,(char*)base_path,str),fflush(stdout); -#endif - - base_filename = gtk_file_path_get_string (base_path); - g_return_val_if_fail (base_filename != NULL, FALSE); - g_return_val_if_fail (g_path_is_absolute (base_filename), FALSE); - - last_backslash = strrchr (str, '\\'); - last_slash = strrchr (str, '/'); - if (last_slash == NULL || - (last_backslash != NULL && last_backslash > last_slash)) - last_slash = last_backslash; - - if (!last_slash) - { - *folder = gtk_file_path_copy (base_path); - *file_part = g_strdup (str); - result = TRUE; - } - else - { - gchar *folder_part; - gchar *folder_path; - - if (last_slash == str) - { - if (g_ascii_isalpha (base_filename[0]) && - base_filename[1] == ':') - folder_part = g_strdup_printf ("%c:\\", base_filename[0]); - else - folder_part = g_strdup ("\\"); - } - else if (g_ascii_isalpha (str[0]) && - str[1] == ':' && - last_slash == str + 2) - folder_part = g_strndup (str, last_slash - str + 1); -#if 0 - /* Hmm, what the heck was this case supposed to do? It splits up - * \\server\share\foo\bar into folder_part - * \\server\share\foo\bar and file_path bar. Not good. As far as - * I can see, this isn't needed. - */ - else if (G_IS_DIR_SEPARATOR (str[0]) && - G_IS_DIR_SEPARATOR (str[1]) && - (!str[2] || !G_IS_DIR_SEPARATOR (str[2]))) - folder_part = g_strdup (str); -#endif - else - folder_part = g_strndup (str, last_slash - str); - - g_assert (folder_part); - - if (g_path_is_absolute (folder_part)) - folder_path = folder_part; - else - { - folder_path = g_build_filename (base_filename, folder_part, NULL); - g_free (folder_part); - } - - canonicalize_filename (folder_path); - - *folder = filename_to_path (folder_path); - *file_part = g_strdup (last_slash + 1); - - g_free (folder_path); - - result = TRUE; - } - -#if DEBUGGING_OUTPUT - printf ("%s:returning folder=%s file_part=%s\n", __FUNCTION__, (*folder?(char*)*folder:"NULL"), *file_part), fflush(stdout); -#endif - - return result; -} - -static gchar * -gtk_file_system_win32_path_to_uri (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - return g_filename_to_uri (gtk_file_path_get_string (path), NULL, NULL); -} - -static gchar * -gtk_file_system_win32_path_to_filename (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - return g_strdup (gtk_file_path_get_string (path)); -} - -static GtkFilePath * -gtk_file_system_win32_uri_to_path (GtkFileSystem *file_system, - const gchar *uri) -{ - GtkFilePath *path; - gchar *filename = g_filename_from_uri (uri, NULL, NULL); - -#if DEBUGGING_OUTPUT - printf ("%s: %s -> %s\n", __FUNCTION__, uri, filename?filename:"NULL"), fflush (stdout); -#endif - - if (filename) - { - path = filename_to_path (filename); - g_free (filename); - } - else - path = NULL; - - return path; -} - -static GtkFilePath * -gtk_file_system_win32_filename_to_path (GtkFileSystem *file_system, - const gchar *filename) -{ - return filename_to_path (filename); -} - -static void -bookmark_list_free (GSList *list) -{ - GSList *l; - - for (l = list; l; l = l->next) - g_free (l->data); - - g_slist_free (list); -} - -/* Returns whether a URI is a local file:// */ -static gboolean -is_local_uri (const char *uri) -{ - char *filename; - char *hostname; - gboolean result; - - /* This is rather crude, but hey */ - filename = g_filename_from_uri (uri, &hostname, NULL); - - result = (filename && !hostname); - - g_free (filename); - g_free (hostname); - - return result; -} - -static char * -bookmark_get_filename (void) -{ - char *filename; - - filename = g_build_filename (g_get_home_dir (), - BOOKMARKS_FILENAME, NULL); - g_assert (filename != NULL); - return filename; -} - -static gboolean -bookmark_list_read (GSList **bookmarks, GError **error) -{ - gchar *filename; - gchar *contents; - gboolean result = FALSE; - - filename = bookmark_get_filename (); - *bookmarks = NULL; - - if (g_file_get_contents (filename, &contents, NULL, error)) - { - gchar **lines = g_strsplit (contents, "\n", -1); - int i; - GHashTable *table; - - table = g_hash_table_new (g_str_hash, g_str_equal); - - for (i = 0; lines[i]; i++) - { - if (lines[i][0] && !g_hash_table_lookup (table, lines[i])) - { - *bookmarks = g_slist_prepend (*bookmarks, g_strdup (lines[i])); - g_hash_table_insert (table, lines[i], lines[i]); - } - } - - g_free (contents); - g_hash_table_destroy (table); - g_strfreev (lines); - - *bookmarks = g_slist_reverse (*bookmarks); - result = TRUE; - } - - g_free (filename); - - return result; -} - -static gboolean -bookmark_list_write (GSList *bookmarks, - GError **error) -{ - GSList *l; - GString *string; - char *filename; - GError *tmp_error = NULL; - gboolean result; - - string = g_string_new (""); - - for (l = bookmarks; l; l = l->next) - { - g_string_append (string, l->data); - g_string_append_c (string, '\n'); - } - - filename = bookmark_get_filename (); - - result = g_file_set_contents (filename, string->str, -1, &tmp_error); - - g_free (filename); - g_string_free (string, TRUE); - - if (!result) - { - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_FAILED, - _("Bookmark saving failed: %s"), - tmp_error->message); - - g_error_free (tmp_error); - } - - return result; -} - -static gboolean -gtk_file_system_win32_insert_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - gint position, - GError **error) -{ - GSList *bookmarks; - int num_bookmarks; - GSList *l; - char *uri; - gboolean result; - GError *err; - - err = NULL; - if (!bookmark_list_read (&bookmarks, &err) && err->code != G_FILE_ERROR_NOENT) - { - g_propagate_error (error, err); - return FALSE; - } - - num_bookmarks = g_slist_length (bookmarks); - g_return_val_if_fail (position >= -1 && position <= num_bookmarks, FALSE); - - result = FALSE; - - uri = gtk_file_system_win32_path_to_uri (file_system, path); - - for (l = bookmarks; l; l = l->next) - { - char *bookmark, *space; - - bookmark = l->data; - - space = strchr (bookmark, ' '); - if (space) - *space = '\0'; - if (strcmp (bookmark, uri) != 0) - { - if (space) - *space = ' '; - } - else - { - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_ALREADY_EXISTS, - _("'%s' already exists in the bookmarks list"), - uri); - goto out; - } - } - - bookmarks = g_slist_insert (bookmarks, g_strdup (uri), position); - if (bookmark_list_write (bookmarks, error)) - { - result = TRUE; - g_signal_emit_by_name (file_system, "bookmarks-changed", 0); - } - - out: - - g_free (uri); - bookmark_list_free (bookmarks); - - return result; -} - -static gboolean -gtk_file_system_win32_remove_bookmark (GtkFileSystem *file_system, - const GtkFilePath *path, - GError **error) -{ - GSList *bookmarks; - char *uri; - GSList *l; - gboolean result; - - if (!bookmark_list_read (&bookmarks, error)) - return FALSE; - - result = FALSE; - - uri = gtk_file_system_path_to_uri (file_system, path); - - for (l = bookmarks; l; l = l->next) - { - char *bookmark, *space; - - bookmark = (char *)l->data; - space = strchr (bookmark, ' '); - if (space) - *space = '\0'; - - if (strcmp (bookmark, uri) != 0) - { - if (space) - *space = ' '; - } - else - { - g_free (l->data); - bookmarks = g_slist_remove_link (bookmarks, l); - g_slist_free_1 (l); - - if (bookmark_list_write (bookmarks, error)) - { - result = TRUE; - - g_signal_emit_by_name (file_system, "bookmarks-changed", 0); - } - - goto out; - } - } - - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_NONEXISTENT, - _("'%s' does not exist in the bookmarks list"), - uri); - - out: - - g_free (uri); - bookmark_list_free (bookmarks); - - return result; -} - -static GSList * -gtk_file_system_win32_list_bookmarks (GtkFileSystem *file_system) -{ - GSList *bookmarks; - GSList *result; - GSList *l; - - if (!bookmark_list_read (&bookmarks, NULL)) - return NULL; - - result = NULL; - - for (l = bookmarks; l; l = l->next) - { - char *bookmark, *space; - - bookmark = (char *)l->data; - space = strchr (bookmark, ' '); - if (space) - *space = '\0'; - - if (is_local_uri (bookmark)) - result = g_slist_prepend (result, gtk_file_system_win32_uri_to_path (file_system, bookmark)); - } - - bookmark_list_free (bookmarks); - - result = g_slist_reverse (result); - return result; -} - -static gchar * -gtk_file_system_win32_get_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path) -{ - GSList *labels; - gchar *label; - GSList *l; - char *bookmark, *space, *uri; - - labels = NULL; - label = NULL; - - uri = gtk_file_system_path_to_uri (file_system, path); - bookmark_list_read (&labels, NULL); - - for (l = labels; l && !label; l = l->next) - { - bookmark = (char *)l->data; - space = strchr (bookmark, ' '); - if (!space) - continue; - - *space = '\0'; - - if (strcmp (uri, bookmark) == 0) - label = g_strdup (space + 1); - } - - bookmark_list_free (labels); - g_free (uri); - - return label; -} - -static void -gtk_file_system_win32_set_bookmark_label (GtkFileSystem *file_system, - const GtkFilePath *path, - const gchar *label) -{ - GSList *labels; - GSList *l; - gchar *bookmark, *space, *uri; - gboolean found; - - labels = NULL; - - uri = gtk_file_system_path_to_uri (file_system, path); - bookmark_list_read (&labels, NULL); - - found = FALSE; - for (l = labels; l && !found; l = l->next) - { - bookmark = (gchar *)l->data; - space = strchr (bookmark, ' '); - if (space) - *space = '\0'; - - if (strcmp (bookmark, uri) != 0) - { - if (space) - *space = ' '; - } - else - { - g_free (bookmark); - - if (label && *label) - l->data = g_strdup_printf ("%s %s", uri, label); - else - l->data = g_strdup (uri); - - found = TRUE; - break; - } - } - - if (found) - { - if (bookmark_list_write (labels, NULL)) - g_signal_emit_by_name (file_system, "bookmarks-changed", 0); - } - - bookmark_list_free (labels); - g_free (uri); -} - -static void -_gtk_file_folder_win32_class_init (GtkFileFolderWin32Class *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - - gobject_class->finalize = gtk_file_folder_win32_finalize; -} - -static void -gtk_file_folder_win32_iface_init (GtkFileFolderIface *iface) -{ - iface->get_info = gtk_file_folder_win32_get_info; - iface->list_children = gtk_file_folder_win32_list_children; - iface->is_finished_loading = gtk_file_folder_win32_is_finished_loading; -} - -static void -_gtk_file_folder_win32_init (GtkFileFolderWin32 *impl) -{ -} - -static void -gtk_file_folder_win32_finalize (GObject *object) -{ - GtkFileFolderWin32 *folder_win32 = GTK_FILE_FOLDER_WIN32 (object); - - if (folder_win32->load_folder_id) - { - g_source_remove (folder_win32->load_folder_id); - folder_win32->load_folder_id = 0; - } - - g_hash_table_remove (folder_win32->system_win32->folder_hash, folder_win32->filename); - - if (folder_win32->stat_info) - { -#if 0 - g_print ("Releasing information for directory %s\n", folder_win32->filename); -#endif - g_hash_table_destroy (folder_win32->stat_info); - } - - g_free (folder_win32->filename); - - G_OBJECT_CLASS (_gtk_file_folder_win32_parent_class)->finalize (object); -} - -/* Creates a GtkFileInfo for a volume root by stat()ing it */ -static GtkFileInfo * -file_info_for_root_with_error (const char *root_name, - GError **error) -{ - struct stat statbuf; - GtkFileInfo *info; - - if (g_stat (root_name, &statbuf) != 0) - { - int saved_errno; - char *display_name; - - saved_errno = errno; - display_name = g_filename_display_name (root_name); - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - GTK_FILE_SYSTEM_ERROR_FAILED, - _("Error getting information for '%s': %s"), - display_name, - g_strerror (saved_errno)); - - g_free (display_name); - return NULL; - } - - info = gtk_file_info_new (); - gtk_file_info_set_display_name (info, root_name); - gtk_file_info_set_is_folder (info, TRUE); - gtk_file_info_set_is_hidden (info, FALSE); - gtk_file_info_set_mime_type (info, "x-directory/normal"); - gtk_file_info_set_modification_time (info, statbuf.st_mtime); - gtk_file_info_set_size (info, statbuf.st_size); - - return info; -} - -static gboolean -stat_with_error (const char *filename, - WIN32_FILE_ATTRIBUTE_DATA *wfad, - GError **error) -{ - wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, error); - int rc; - - if (wfilename == NULL) - return FALSE; - - rc = GetFileAttributesExW (wfilename, GetFileExInfoStandard, wfad); - - if (rc == 0) - { - if (error) - { - int error_number = GetLastError (); - char *emsg = g_win32_error_message (error_number); - gchar *display_name = g_filename_display_name (filename); - int code; - - if (error_number == ERROR_FILE_NOT_FOUND || - error_number == ERROR_PATH_NOT_FOUND) - code = GTK_FILE_SYSTEM_ERROR_NONEXISTENT; - else - code = GTK_FILE_SYSTEM_ERROR_FAILED; - - g_set_error (error, - GTK_FILE_SYSTEM_ERROR, - code, - _("Error getting information for '%s': %s"), - display_name, - emsg); - g_free (display_name); - g_free (wfilename); - g_free (emsg); - } - return FALSE; - } - - g_free (wfilename); - return TRUE; -} - -/* Creates a new GtkFileInfo from the specified data */ -static GtkFileInfo * -create_file_info (GtkFileFolderWin32 *folder_win32, - const char *filename, - GtkFileInfoType types, - WIN32_FILE_ATTRIBUTE_DATA *wfad, - const char *mime_type) -{ - GtkFileInfo *info; - - info = gtk_file_info_new (); - - if (types & GTK_FILE_INFO_DISPLAY_NAME) - { - gchar *display_name; - - if (filename_is_root (filename)) - display_name = g_filename_display_name (filename); - else - display_name = g_filename_display_basename (filename); - - gtk_file_info_set_display_name (info, display_name); - g_free (display_name); - } - - if (types & GTK_FILE_INFO_IS_HIDDEN) - { - gboolean is_hidden = !!(wfad->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN); - gtk_file_info_set_is_hidden (info, is_hidden); - } - - if (types & GTK_FILE_INFO_IS_FOLDER) - gtk_file_info_set_is_folder (info, !!(wfad->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); - - if (types & GTK_FILE_INFO_MIME_TYPE) - gtk_file_info_set_mime_type (info, mime_type); - - if (types & GTK_FILE_INFO_MODIFICATION_TIME) - { - GtkFileTime time = (wfad->ftLastWriteTime.dwLowDateTime - | ((guint64)wfad->ftLastWriteTime.dwHighDateTime) << 32); - /* 100-nanosecond intervals since January 1, 1601, urgh! */ - time /= G_GINT64_CONSTANT (10000000); /* now seconds */ - time -= G_GINT64_CONSTANT (134774) * 24 * 3600; /* good old Unix time */ - gtk_file_info_set_modification_time (info, time); - } - - if (types & GTK_FILE_INFO_SIZE) - { - gint64 size = wfad->nFileSizeLow | ((guint64)wfad->nFileSizeHigh) << 32; - gtk_file_info_set_size (info, size); - } - - if (types & GTK_FILE_INFO_ICON) - { - IconType icon_type = get_icon_type_from_path (folder_win32, wfad, filename); - gchar *icon_name = get_icon_name (filename, icon_type); - gtk_file_info_set_icon_name (info, icon_name); - g_free (icon_name); - } - - return info; -} - -static struct stat_info_entry * -create_stat_info_entry_and_emit_add (GtkFileFolderWin32 *folder_win32, - const char *filename, - const char *basename, - WIN32_FILE_ATTRIBUTE_DATA *wfad) -{ - GSList *paths; - GtkFilePath *path; - struct stat_info_entry *entry; - - entry = g_new0 (struct stat_info_entry, 1); - - if ((folder_win32->types & STAT_NEEDED_MASK) != 0) - entry->wfad = *wfad; - - if ((folder_win32->types & GTK_FILE_INFO_MIME_TYPE) != 0) - entry->mime_type = get_mime_type_for_file (filename, wfad); - - g_hash_table_insert (folder_win32->stat_info, - g_strdup (basename), - entry); - - path = gtk_file_path_new_dup (filename); - paths = g_slist_append (NULL, path); - g_signal_emit_by_name (folder_win32, "files-added", paths); - gtk_file_path_free (path); - g_slist_free (paths); - - return entry; -} - -static GtkFileInfo * -gtk_file_folder_win32_get_info (GtkFileFolder *folder, - const GtkFilePath *path, - GError **error) -{ - GtkFileFolderWin32 *folder_win32 = GTK_FILE_FOLDER_WIN32 (folder); - GtkFileInfo *info; - const char *filename; - GtkFileInfoType types; - WIN32_FILE_ATTRIBUTE_DATA wfad; - const char *mime_type; - - /* Get_info for "/" */ - if (!path) - { - g_return_val_if_fail (filename_is_root (folder_win32->filename), NULL); - return file_info_for_root_with_error (folder_win32->filename, error); - } - - /* Get_info for normal files */ - - filename = gtk_file_path_get_string (path); - g_return_val_if_fail (filename != NULL, NULL); - g_return_val_if_fail (g_path_is_absolute (filename), NULL); - -#if 0 - /* Skip this sanity check, as it fails for server share roots, where - * dirname gets set to \\server\share\ and folder_win32->filename is - * \\server\share. Also, should we do a casefolded comparison here, - * too, anyway? - */ - { - gchar *dirname = get_parent_dir (filename); - g_return_val_if_fail (strcmp (dirname, folder_win32->filename) == 0, NULL); - g_free (dirname); - } -#endif - - types = folder_win32->types; - - if (folder_win32->have_stat) - { - struct stat_info_entry *entry; - gchar *basename; - - g_assert (folder_win32->stat_info != NULL); - - basename = g_path_get_basename (filename); - entry = g_hash_table_lookup (folder_win32->stat_info, basename); - - if (!entry) - { - if (!stat_with_error (filename, &wfad, error)) - { - g_free (basename); - return NULL; - } - - entry = create_stat_info_entry_and_emit_add (folder_win32, filename, basename, &wfad); - } - g_free (basename); - - info = create_file_info (folder_win32, filename, types, &entry->wfad, entry->mime_type); - return info; - } - else - { - if (!stat_with_error (filename, &wfad, error)) - return NULL; - - if ((types & GTK_FILE_INFO_MIME_TYPE) != 0) - mime_type = get_mime_type_for_file (filename, &wfad); - else - mime_type = NULL; - - info = create_file_info (folder_win32, filename, types, &wfad, mime_type); - - return info; - } -} - -static void -cb_list_children (gpointer key, gpointer value, gpointer user_data) -{ - GSList **children = user_data; - *children = g_slist_prepend (*children, key); -} - -static gboolean -gtk_file_folder_win32_list_children (GtkFileFolder *folder, - GSList **children, - GError **error) -{ - GtkFileFolderWin32 *folder_win32 = GTK_FILE_FOLDER_WIN32 (folder); - GSList *l; - - *children = NULL; - - /* Get the list of basenames. */ - if (folder_win32->stat_info) - g_hash_table_foreach (folder_win32->stat_info, cb_list_children, children); - - /* Turn basenames into GFilePaths. */ - for (l = *children; l; l = l->next) - { - const char *basename = l->data; - char *fullname = g_build_filename (folder_win32->filename, basename, NULL); - l->data = filename_to_path (fullname); - g_free (fullname); - } - - return TRUE; -} - -static gboolean -gtk_file_folder_win32_is_finished_loading (GtkFileFolder *folder) -{ - return GTK_FILE_FOLDER_WIN32 (folder)->is_finished_loading; -} - -static void -free_stat_info_entry (struct stat_info_entry *entry) -{ - g_free (entry->mime_type); - g_free (entry); -} - -static gboolean -fill_in_names (GtkFileFolderWin32 *folder_win32, GError **error) -{ - GDir *dir; - - if (folder_win32->stat_info) - return TRUE; - - dir = g_dir_open (folder_win32->filename, 0, error); - if (!dir) - return FALSE; - - folder_win32->stat_info = g_hash_table_new_full (casefolded_hash, casefolded_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) free_stat_info_entry); - - while (TRUE) - { - struct stat_info_entry *entry; - const gchar *basename; - - basename = g_dir_read_name (dir); - if (!basename) - break; - - entry = g_new0 (struct stat_info_entry, 1); - if (folder_win32->is_network_dir) - { - g_assert_not_reached (); - entry->wfad.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; - entry->mime_type = g_strdup ("x-directory/normal"); - } - - g_hash_table_insert (folder_win32->stat_info, - g_strdup (basename), - entry); - } - - g_dir_close (dir); - - folder_win32->asof = time (NULL); - return TRUE; -} - -static gboolean -cb_fill_in_stats (gpointer key, gpointer value, gpointer user_data) -{ - const char *basename = key; - struct stat_info_entry *entry = value; - GtkFileFolderWin32 *folder_win32 = user_data; - char *fullname = g_build_filename (folder_win32->filename, basename, NULL); - gboolean result; - - if (!stat_with_error (fullname, &entry->wfad, NULL)) - result = TRUE; /* Couldn't stat -- remove from hash. */ - else - result = FALSE; - - g_free (fullname); - return result; -} - - -static void -fill_in_stats (GtkFileFolderWin32 *folder_win32) -{ - if (folder_win32->have_stat) - return; - - if (!fill_in_names (folder_win32, NULL)) - return; - - if (!folder_win32->is_network_dir) - g_hash_table_foreach_remove (folder_win32->stat_info, - cb_fill_in_stats, - folder_win32); - - folder_win32->have_stat = TRUE; -} - -static gboolean -cb_fill_in_mime_type (gpointer key, gpointer value, gpointer user_data) -{ - const char *basename = key; - struct stat_info_entry *entry = value; - GtkFileFolderWin32 *folder_win32 = user_data; - char *fullname = g_build_filename (folder_win32->filename, basename, NULL); - - entry->mime_type = get_mime_type_for_file (fullname, &entry->wfad); - - g_free (fullname); - - return FALSE; -} - -static void -fill_in_mime_type (GtkFileFolderWin32 *folder_win32) -{ - if (folder_win32->have_mime_type) - return; - - if (!folder_win32->have_stat) - return; - - g_assert (folder_win32->stat_info != NULL); - - if (!folder_win32->is_network_dir) - g_hash_table_foreach_remove (folder_win32->stat_info, - cb_fill_in_mime_type, - folder_win32); - - folder_win32->have_mime_type = TRUE; -} - -static GtkFilePath * -filename_to_path (const char *filename) -{ - char *tmp; - - tmp = remove_trailing_slash (filename); - return gtk_file_path_new_steal (tmp); -} - -static gboolean -filename_is_root (const char *filename) -{ - const gchar *after_root; - - after_root = g_path_skip_root (filename); - - return (after_root != NULL && *after_root == '\0'); -} - -static gboolean -filename_is_drive_root (const char *filename) -{ - guint len = strlen (filename); - - return (len == 3 && - g_ascii_isalpha (filename[0]) && - filename[1] == ':' && - G_IS_DIR_SEPARATOR (filename[2])); -} - -static gboolean -filename_is_some_root (const char *filename) -{ - return (g_path_is_absolute (filename) && - *(g_path_skip_root (filename)) == '\0'); -} - -int -_gtk_file_system_win32_path_compare (const gchar *path1, - const gchar *path2) -{ - while (*path1 && *path2) - { - gunichar c1 = g_utf8_get_char (path1); - gunichar c2 = g_utf8_get_char (path2); - if (c1 == c2 || - (G_IS_DIR_SEPARATOR (c1) && G_IS_DIR_SEPARATOR (c1)) || - g_unichar_toupper (c1) == g_unichar_toupper (c2)) - { - path1 = g_utf8_next_char (path1); - path2 = g_utf8_next_char (path2); - } - else - break; - } - if (!*path1 && !*path2) - return 0; - else if (!*path1) - return -1; - else if (!*path2) - return 1; - else - return g_unichar_toupper (g_utf8_get_char (path1)) - g_unichar_toupper (g_utf8_get_char (path2)); -} - -#define __GTK_FILE_SYSTEM_WIN32_C__ -#include "gtkaliasdef.c" diff --git a/gtk/gtkfilesystemwin32.h b/gtk/gtkfilesystemwin32.h deleted file mode 100644 index e68a89e5d..000000000 --- a/gtk/gtkfilesystemwin32.h +++ /dev/null @@ -1,42 +0,0 @@ -/* GTK - The GIMP Toolkit - * gtkfilesystemunix.h: Default implementation of GtkFileSystem for UNIX-like systems - * Copyright (C) 2003, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GTK_FILE_SYSTEM_WIN32_H__ -#define __GTK_FILE_SYSTEM_WIN32_H__ - -#include -#include "gtkfilesystem.h" - -G_BEGIN_DECLS - -#define GTK_TYPE_FILE_SYSTEM_WIN32 (gtk_file_system_win32_get_type ()) -#define GTK_FILE_SYSTEM_WIN32(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_SYSTEM_WIN32, GtkFileSystemWin32)) -#define GTK_IS_FILE_SYSTEM_WIN32(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_SYSTEM_WIN32)) - -typedef struct _GtkFileSystemWin32 GtkFileSystemWin32; - -GtkFileSystem *gtk_file_system_win32_new (void); -GType gtk_file_system_win32_get_type (void) G_GNUC_CONST; - -gchar *_gtk_file_system_win32_get_desktop (void); - -G_END_DECLS - -#endif /* __GTK_FILE_SYSTEM_WIN32_H__ */ diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c index d396cc895..62e8a857e 100644 --- a/gtk/gtkpathbar.c +++ b/gtk/gtkpathbar.c @@ -63,10 +63,10 @@ struct _ButtonData GtkWidget *button; ButtonType type; char *dir_name; - GtkFilePath *path; + GFile *file; GtkWidget *image; GtkWidget *label; - GtkFileSystemHandle *handle; + GCancellable *cancellable; guint ignore_changes : 1; guint file_is_hidden : 1; }; @@ -171,7 +171,7 @@ gtk_path_bar_init (GtkPathBar *path_bar) GTK_WIDGET_SET_FLAGS (path_bar, GTK_NO_WINDOW); gtk_widget_set_redraw_on_allocate (GTK_WIDGET (path_bar), FALSE); - path_bar->set_path_handle = NULL; + path_bar->get_info_cancellable = NULL; path_bar->spacing = 0; path_bar->up_slider_button = get_slider_button (path_bar, GTK_ARROW_LEFT); @@ -248,12 +248,12 @@ gtk_path_bar_finalize (GObject *object) gtk_path_bar_stop_scrolling (path_bar); g_list_free (path_bar->button_list); - if (path_bar->root_path) - gtk_file_path_free (path_bar->root_path); - if (path_bar->home_path) - gtk_file_path_free (path_bar->home_path); - if (path_bar->desktop_path) - gtk_file_path_free (path_bar->desktop_path); + if (path_bar->root_file) + g_object_unref (path_bar->root_file); + if (path_bar->home_file) + g_object_unref (path_bar->home_file); + if (path_bar->desktop_file) + g_object_unref (path_bar->desktop_file); if (path_bar->root_icon) g_object_unref (path_bar->root_icon); @@ -291,9 +291,9 @@ gtk_path_bar_dispose (GObject *object) remove_settings_signal (path_bar, gtk_widget_get_screen (GTK_WIDGET (object))); - if (path_bar->set_path_handle) - gtk_file_system_cancel_operation (path_bar->set_path_handle); - path_bar->set_path_handle = NULL; + if (path_bar->get_info_cancellable) + g_cancellable_cancel (path_bar->get_info_cancellable); + path_bar->get_info_cancellable = NULL; G_OBJECT_CLASS (gtk_path_bar_parent_class)->dispose (object); } @@ -1137,7 +1137,7 @@ button_clicked_cb (GtkWidget *button, GtkPathBar *path_bar; GList *button_list; gboolean child_is_hidden; - GtkFilePath *child_path; + GFile *child_file; button_data = BUTTON_DATA (data); if (button_data->ignore_changes) @@ -1159,17 +1159,17 @@ button_clicked_cb (GtkWidget *button, ButtonData *child_data; child_data = BUTTON_DATA (button_list->prev->data); - child_path = child_data->path; + child_file = child_data->file; child_is_hidden = child_data->file_is_hidden; } else { - child_path = NULL; + child_file = NULL; child_is_hidden = FALSE; } g_signal_emit (path_bar, path_bar_signals [PATH_CLICKED], 0, - button_data->path, child_path, child_is_hidden); + button_data->file, child_file, child_is_hidden); } struct SetButtonImageData @@ -1179,19 +1179,19 @@ struct SetButtonImageData }; static void -set_button_image_get_info_cb (GtkFileSystemHandle *handle, - const GtkFileInfo *info, - const GError *error, - gpointer user_data) +set_button_image_get_info_cb (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer user_data) { - gboolean cancelled = handle->cancelled; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); GdkPixbuf *pixbuf; struct SetButtonImageData *data = user_data; - if (handle != data->button_data->handle) + if (cancellable != data->button_data->cancellable) goto out; - data->button_data->handle = NULL; + data->button_data->cancellable = NULL; if (!data->button_data->button) { @@ -1203,7 +1203,7 @@ set_button_image_get_info_cb (GtkFileSystemHandle *handle, goto out; pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->path_bar), - data->path_bar->icon_size, NULL); + data->path_bar->icon_size); gtk_image_set_from_pixbuf (GTK_IMAGE (data->button_data->image), pixbuf); switch (data->button_data->type) @@ -1228,7 +1228,7 @@ set_button_image_get_info_cb (GtkFileSystemHandle *handle, out: g_free (data); - g_object_unref (handle); + g_object_unref (cancellable); } static void @@ -1247,17 +1247,16 @@ set_button_image (GtkPathBar *path_bar, gtk_image_set_from_pixbuf (GTK_IMAGE (button_data->image), path_bar->root_icon); break; } - - volume = gtk_file_system_get_volume_for_path (path_bar->file_system, path_bar->root_path); + + volume = gtk_file_system_get_volume_for_file (path_bar->file_system, path_bar->root_file); if (volume == NULL) return; - path_bar->root_icon = gtk_file_system_volume_render_icon (path_bar->file_system, - volume, + path_bar->root_icon = gtk_file_system_volume_render_icon (volume, GTK_WIDGET (path_bar), path_bar->icon_size, NULL); - gtk_file_system_volume_free (path_bar->file_system, volume); + gtk_file_system_volume_free (volume); gtk_image_set_from_pixbuf (GTK_IMAGE (button_data->image), path_bar->root_icon); break; @@ -1273,13 +1272,13 @@ set_button_image (GtkPathBar *path_bar, data->path_bar = path_bar; data->button_data = button_data; - if (button_data->handle) - gtk_file_system_cancel_operation (button_data->handle); + if (button_data->cancellable) + g_cancellable_cancel (button_data->cancellable); - button_data->handle = + button_data->cancellable = gtk_file_system_get_info (path_bar->file_system, - path_bar->home_path, - GTK_FILE_INFO_ICON, + path_bar->home_file, + "standard::icon", set_button_image_get_info_cb, data); break; @@ -1295,13 +1294,13 @@ set_button_image (GtkPathBar *path_bar, data->path_bar = path_bar; data->button_data = button_data; - if (button_data->handle) - gtk_file_system_cancel_operation (button_data->handle); + if (button_data->cancellable) + g_cancellable_cancel (button_data->cancellable); - button_data->handle = + button_data->cancellable = gtk_file_system_get_info (path_bar->file_system, - path_bar->desktop_path, - GTK_FILE_INFO_ICON, + path_bar->desktop_file, + "standard::icon", set_button_image_get_info_cb, data); break; @@ -1313,17 +1312,17 @@ set_button_image (GtkPathBar *path_bar, static void button_data_free (ButtonData *button_data) { - if (button_data->path) - gtk_file_path_free (button_data->path); - button_data->path = NULL; + if (button_data->file) + g_object_unref (button_data->file); + button_data->file = NULL; g_free (button_data->dir_name); button_data->dir_name = NULL; button_data->button = NULL; - if (button_data->handle) - gtk_file_system_cancel_operation (button_data->handle); + if (button_data->cancellable) + g_cancellable_cancel (button_data->cancellable); else g_free (button_data); } @@ -1398,16 +1397,16 @@ gtk_path_bar_update_button_appearance (GtkPathBar *path_bar, static ButtonType find_button_type (GtkPathBar *path_bar, - GtkFilePath *path) + GFile *file) { - if (path_bar->root_path != NULL && - ! gtk_file_path_compare (path, path_bar->root_path)) + if (path_bar->root_file != NULL && + g_file_equal (file, path_bar->root_file)) return ROOT_BUTTON; - if (path_bar->home_path != NULL && - ! gtk_file_path_compare (path, path_bar->home_path)) + if (path_bar->home_file != NULL && + g_file_equal (file, path_bar->home_file)) return HOME_BUTTON; - if (path_bar->desktop_path != NULL && - ! gtk_file_path_compare (path, path_bar->desktop_path)) + if (path_bar->desktop_file != NULL && + g_file_equal (file, path_bar->desktop_file)) return DESKTOP_BUTTON; return NORMAL_BUTTON; @@ -1428,7 +1427,7 @@ button_drag_data_get_cb (GtkWidget *widget, button_data = data; path_bar = GTK_PATH_BAR (widget->parent); /* the button's parent *is* the path bar */ - uris[0] = gtk_file_system_path_to_uri (path_bar->file_system, button_data->path); + uris[0] = g_file_get_uri (button_data->file); uris[1] = NULL; gtk_selection_data_set_uris (selection_data, uris); @@ -1438,7 +1437,7 @@ button_drag_data_get_cb (GtkWidget *widget, static ButtonData * make_directory_button (GtkPathBar *path_bar, const char *dir_name, - GtkFilePath *path, + GFile *file, gboolean current_dir, gboolean file_is_hidden) { @@ -1451,7 +1450,7 @@ make_directory_button (GtkPathBar *path_bar, /* Is it a special button? */ button_data = g_new0 (ButtonData, 1); - button_data->type = find_button_type (path_bar, path); + button_data->type = find_button_type (path_bar, file); button_data->button = gtk_toggle_button_new (); atk_obj = gtk_widget_get_accessible (button_data->button); gtk_button_set_focus_on_click (GTK_BUTTON (button_data->button), FALSE); @@ -1492,9 +1491,9 @@ make_directory_button (GtkPathBar *path_bar, G_CALLBACK (label_size_request_cb), button_data); button_data->dir_name = g_strdup (dir_name); - button_data->path = gtk_file_path_new_dup (gtk_file_path_get_string (path)); + button_data->file = g_object_ref (file); button_data->file_is_hidden = file_is_hidden; - + gtk_container_add (GTK_CONTAINER (button_data->button), child); gtk_widget_show_all (button_data->button); @@ -1519,7 +1518,7 @@ make_directory_button (GtkPathBar *path_bar, static gboolean gtk_path_bar_check_parent_path (GtkPathBar *path_bar, - const GtkFilePath *file_path, + GFile *file, GtkFileSystem *file_system) { GList *list; @@ -1531,7 +1530,7 @@ gtk_path_bar_check_parent_path (GtkPathBar *path_bar, ButtonData *button_data; button_data = list->data; - if (! gtk_file_path_compare (file_path, button_data->path)) + if (g_file_equal (file, button_data->file)) { current_path = list; break; @@ -1577,10 +1576,10 @@ gtk_path_bar_check_parent_path (GtkPathBar *path_bar, } -struct SetPathInfo +struct SetFileInfo { - GtkFilePath *path; - GtkFilePath *parent_path; + GFile *file; + GFile *parent_file; GtkPathBar *path_bar; GList *new_buttons; GList *fake_root; @@ -1588,8 +1587,8 @@ struct SetPathInfo }; static void -gtk_path_bar_set_path_finish (struct SetPathInfo *info, - gboolean result) +gtk_path_bar_set_file_finish (struct SetFileInfo *info, + gboolean result) { if (result) { @@ -1620,95 +1619,86 @@ gtk_path_bar_set_path_finish (struct SetPathInfo *info, g_list_free (info->new_buttons); } - if (info->path) - gtk_file_path_free (info->path); - if (info->parent_path) - gtk_file_path_free (info->parent_path); + if (info->file) + g_object_unref (info->file); + if (info->parent_file) + g_object_unref (info->parent_file); g_free (info); } static void -gtk_path_bar_get_info_callback (GtkFileSystemHandle *handle, - const GtkFileInfo *file_info, - const GError *error, - gpointer data) +gtk_path_bar_get_info_callback (GCancellable *cancellable, + GFileInfo *info, + const GError *error, + gpointer data) { - gboolean cancelled = handle->cancelled; - struct SetPathInfo *path_info = data; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); + struct SetFileInfo *file_info = data; ButtonData *button_data; const gchar *display_name; gboolean is_hidden; - gboolean valid; - if (handle != path_info->path_bar->set_path_handle) + if (cancellable != file_info->path_bar->get_info_cancellable) { - gtk_path_bar_set_path_finish (path_info, FALSE); - g_object_unref (handle); + gtk_path_bar_set_file_finish (file_info, FALSE); + g_object_unref (cancellable); return; } - g_object_unref (handle); - path_info->path_bar->set_path_handle = NULL; + g_object_unref (cancellable); + file_info->path_bar->get_info_cancellable = NULL; - if (cancelled || !file_info) + if (cancelled || !info) { - gtk_path_bar_set_path_finish (path_info, FALSE); + gtk_path_bar_set_file_finish (file_info, FALSE); return; } - display_name = gtk_file_info_get_display_name (file_info); - is_hidden = gtk_file_info_get_is_hidden (file_info); + display_name = g_file_info_get_display_name (info); + is_hidden = g_file_info_get_is_hidden (info); gtk_widget_push_composite_child (); - button_data = make_directory_button (path_info->path_bar, display_name, - path_info->path, - path_info->first_directory, is_hidden); + button_data = make_directory_button (file_info->path_bar, display_name, + file_info->file, + file_info->first_directory, is_hidden); gtk_widget_pop_composite_child (); - gtk_file_path_free (path_info->path); + g_object_unref (file_info->file); - path_info->new_buttons = g_list_prepend (path_info->new_buttons, button_data); + file_info->new_buttons = g_list_prepend (file_info->new_buttons, button_data); if (BUTTON_IS_FAKE_ROOT (button_data)) - path_info->fake_root = path_info->new_buttons; + file_info->fake_root = file_info->new_buttons; - path_info->path = path_info->parent_path; - path_info->first_directory = FALSE; + file_info->file = file_info->parent_file; + file_info->first_directory = FALSE; - if (!path_info->path) + if (!file_info->file) { - gtk_path_bar_set_path_finish (path_info, TRUE); + gtk_path_bar_set_file_finish (file_info, TRUE); return; } - valid = gtk_file_system_get_parent (path_info->path_bar->file_system, - path_info->path, - &path_info->parent_path, - NULL); - if (!valid) - { - gtk_path_bar_set_path_finish (path_info, FALSE); - return; - } + file_info->parent_file = g_file_get_parent (file_info->file); - path_info->path_bar->set_path_handle = - gtk_file_system_get_info (handle->file_system, - path_info->path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_HIDDEN, + file_info->path_bar->get_info_cancellable = + gtk_file_system_get_info (file_info->path_bar->file_system, + file_info->file, + "standard::display-name,standard::is-hidden", gtk_path_bar_get_info_callback, - path_info); + file_info); } gboolean -_gtk_path_bar_set_path (GtkPathBar *path_bar, - const GtkFilePath *file_path, - const gboolean keep_trail, +_gtk_path_bar_set_file (GtkPathBar *path_bar, + GFile *file, + const gboolean keep_trail, GError **error) { - struct SetPathInfo *info; + struct SetFileInfo *info; gboolean result; g_return_val_if_fail (GTK_IS_PATH_BAR (path_bar), FALSE); - g_return_val_if_fail (file_path != NULL, FALSE); + g_return_val_if_fail (G_IS_FILE (file), FALSE); result = TRUE; @@ -1716,30 +1706,22 @@ _gtk_path_bar_set_path (GtkPathBar *path_bar, * This could be a parent directory or a previous selected subdirectory. */ if (keep_trail && - gtk_path_bar_check_parent_path (path_bar, file_path, path_bar->file_system)) + gtk_path_bar_check_parent_path (path_bar, file, path_bar->file_system)) return TRUE; - info = g_new0 (struct SetPathInfo, 1); - info->path = gtk_file_path_copy (file_path); + info = g_new0 (struct SetFileInfo, 1); + info->file = g_object_ref (file); info->path_bar = path_bar; info->first_directory = TRUE; + info->parent_file = g_file_get_parent (info->file); - result = gtk_file_system_get_parent (path_bar->file_system, - info->path, &info->parent_path, error); - if (!result) - { - gtk_file_path_free (info->path); - g_free (info); - return result; - } - - if (path_bar->set_path_handle) - gtk_file_system_cancel_operation (path_bar->set_path_handle); + if (path_bar->get_info_cancellable) + g_cancellable_cancel (path_bar->get_info_cancellable); - path_bar->set_path_handle = + path_bar->get_info_cancellable = gtk_file_system_get_info (path_bar->file_system, - info->path, - GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_HIDDEN, + info->file, + "standard::display-name,standard::is-hidden", gtk_path_bar_get_info_callback, info); @@ -1764,22 +1746,22 @@ _gtk_path_bar_set_file_system (GtkPathBar *path_bar, { const gchar *desktop; - path_bar->home_path = gtk_file_system_filename_to_path (path_bar->file_system, home); + path_bar->home_file = g_file_new_for_path (home); /* FIXME: Need file system backend specific way of getting the * Desktop path. */ desktop = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP); if (desktop != NULL) - path_bar->desktop_path = gtk_file_system_filename_to_path (path_bar->file_system, desktop); + path_bar->desktop_file = g_file_new_for_path (desktop); else - path_bar->desktop_path = NULL; + path_bar->desktop_file = NULL; } else { - path_bar->home_path = NULL; - path_bar->desktop_path = NULL; + path_bar->home_file = NULL; + path_bar->desktop_file = NULL; } - path_bar->root_path = gtk_file_system_filename_to_path (path_bar->file_system, "/"); + path_bar->root_file = g_file_new_for_path ("/"); } /** diff --git a/gtk/gtkpathbar.h b/gtk/gtkpathbar.h index aa56ff81c..2006411a0 100644 --- a/gtk/gtkpathbar.h +++ b/gtk/gtkpathbar.h @@ -41,11 +41,11 @@ struct _GtkPathBar GtkContainer parent; GtkFileSystem *file_system; - GtkFilePath *root_path; - GtkFilePath *home_path; - GtkFilePath *desktop_path; + GFile *root_file; + GFile *home_file; + GFile *desktop_file; - GtkFileSystemHandle *set_path_handle; + GCancellable *get_info_cancellable; GdkPixbuf *root_icon; GdkPixbuf *home_icon; @@ -76,16 +76,16 @@ struct _GtkPathBarClass GtkContainerClass parent_class; void (* path_clicked) (GtkPathBar *path_bar, - GtkFilePath *file_path, - GtkFilePath *child_path, + GFile *file, + GFile *child_file, gboolean child_is_hidden); }; GType gtk_path_bar_get_type (void) G_GNUC_CONST; void _gtk_path_bar_set_file_system (GtkPathBar *path_bar, GtkFileSystem *file_system); -gboolean _gtk_path_bar_set_path (GtkPathBar *path_bar, - const GtkFilePath *file_path, +gboolean _gtk_path_bar_set_file (GtkPathBar *path_bar, + GFile *file, gboolean keep_trail, GError **error); void _gtk_path_bar_up (GtkPathBar *path_bar);