[Xfce4-commits] <thunar:master> Directly collect the full info namespace for ls dir.
Nick Schermer
noreply at xfce.org
Sat Nov 10 17:04:05 CET 2012
Updating branch refs/heads/master
to 4d0efd73cd1f3d241fa2b9eb6c9fd2be2acaf8b4 (commit)
from 4569ffdb7e8bb441c9485db58aece581444487be (commit)
commit 4d0efd73cd1f3d241fa2b9eb6c9fd2be2acaf8b4
Author: Nick Schermer <nick at xfce.org>
Date: Sat Nov 10 15:42:53 2012 +0100
Directly collect the full info namespace for ls dir.
Adapt thunar_io_scan_directory to optionally return
ThunarFile's instea of GFile and create ThunarFiles
later for some io jobs.
This trick is that we can directly use the enumerator
to scan all the directory info and use that for the
new ThunarFiles, this saves querying a file twice
resulting in much faster directory loading.
thunar/thunar-file.c | 131 ++++++++++++++++++++++++++++---------
thunar/thunar-file.h | 11 ++-
thunar/thunar-io-jobs.c | 28 ++------
thunar/thunar-io-scan-directory.c | 77 ++++++++++++++++------
thunar/thunar-io-scan-directory.h | 1 +
thunar/thunar-misc-jobs.c | 21 +-----
thunar/thunar-transfer-job.c | 2 +-
7 files changed, 176 insertions(+), 95 deletions(-)
diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c
index 4a4f853..a99e7bb 100644
--- a/thunar/thunar-file.c
+++ b/thunar/thunar-file.c
@@ -1005,6 +1005,7 @@ thunar_file_load (ThunarFile *file,
_thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
_thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
_thunar_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ _thunar_return_val_if_fail (G_IS_FILE (file->gfile), FALSE);
/* reset the file */
thunar_file_info_clear (file);
@@ -1100,51 +1101,77 @@ thunar_file_get (GFile *gfile,
}
-
/**
- * thunar_file_get_async:
+ * thunar_file_get_with_info:
+ * @uri : an URI or an absolute filename.
+ * @info : #GFileInfo to use when loading the info.
+ * @not_mounted : if the file is mounted.
+ *
+ * Looks up the #ThunarFile referred to by @file. This function may return a
+ * ThunarFile even though the file doesn't actually exist. This is the case
+ * with remote URIs (like SFTP) for instance, if they are not mounted.
+ *
+ * This function does not use g_file_query_info() to get the info,
+ * but takes a reference on the @info,
+ *
+ * The caller is responsible to call g_object_unref()
+ * when done with the returned object.
+ *
+ * Return value: the #ThunarFile for @file or %NULL on errors.
**/
-void
-thunar_file_get_async (GFile *location,
- GCancellable *cancellable,
- ThunarFileGetFunc func,
- gpointer user_data)
+ThunarFile *
+thunar_file_get_with_info (GFile *gfile,
+ GFileInfo *info,
+ gboolean not_mounted)
{
- ThunarFile *file;
- ThunarFileGetData *data;
+ ThunarFile *file;
+
+ _thunar_return_val_if_fail (G_IS_FILE (gfile), NULL);
+ _thunar_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
- _thunar_return_if_fail (G_IS_FILE (location));
- _thunar_return_if_fail (func != NULL);
-
/* check if we already have a cached version of that file */
- file = thunar_file_cache_lookup (location);
+ file = thunar_file_cache_lookup (gfile);
if (G_UNLIKELY (file != NULL))
{
- /* call the return function with the file from the cache */
- (func) (location, file, NULL, user_data);
+ /* take a reference for the caller */
+ g_object_ref (file);
}
else
{
- /* allocate get data */
- data = g_slice_new0 (ThunarFileGetData);
- data->user_data = user_data;
- data->func = func;
- if (cancellable != NULL)
- data->cancellable = g_object_ref (cancellable);
+ /* allocate a new object */
+ file = g_object_new (THUNAR_TYPE_FILE, NULL);
+ file->gfile = g_object_ref (gfile);
- /* load the file information asynchronously */
- g_file_query_info_async (location,
- THUNARX_FILE_INFO_NAMESPACE,
- G_FILE_QUERY_INFO_NONE,
- G_PRIORITY_DEFAULT,
- cancellable,
- thunar_file_get_async_finish,
- data);
+ /* reset the file */
+ thunar_file_info_clear (file);
+
+ /* set the passed info */
+ file->info = g_object_ref (info);
+
+ /* update the file from the information */
+ thunar_file_info_reload (file, NULL);
+
+ /* update the mounted info */
+ if (not_mounted)
+ FLAG_UNSET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
+
+ /* setup lock until the file is inserted */
+ G_LOCK (file_cache_mutex);
+
+ /* insert the file into the cache */
+ g_hash_table_insert (file_cache, g_object_ref (file->gfile), file);
+
+ /* done inserting in the cache */
+ G_UNLOCK (file_cache_mutex);
}
+
+ return file;
}
+
+
/**
* thunar_file_get_for_uri:
* @uri : an URI or an absolute filename.
@@ -1179,6 +1206,50 @@ thunar_file_get_for_uri (const gchar *uri,
/**
+ * thunar_file_get_async:
+ **/
+void
+thunar_file_get_async (GFile *location,
+ GCancellable *cancellable,
+ ThunarFileGetFunc func,
+ gpointer user_data)
+{
+ ThunarFile *file;
+ ThunarFileGetData *data;
+
+ _thunar_return_if_fail (G_IS_FILE (location));
+ _thunar_return_if_fail (func != NULL);
+
+ /* check if we already have a cached version of that file */
+ file = thunar_file_cache_lookup (location);
+ if (G_UNLIKELY (file != NULL))
+ {
+ /* call the return function with the file from the cache */
+ (func) (location, file, NULL, user_data);
+ }
+ else
+ {
+ /* allocate get data */
+ data = g_slice_new0 (ThunarFileGetData);
+ data->user_data = user_data;
+ data->func = func;
+ if (cancellable != NULL)
+ data->cancellable = g_object_ref (cancellable);
+
+ /* load the file information asynchronously */
+ g_file_query_info_async (location,
+ THUNARX_FILE_INFO_NAMESPACE,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ thunar_file_get_async_finish,
+ data);
+ }
+}
+
+
+
+/**
* thunar_file_get_file:
* @file : a #ThunarFile instance.
*
@@ -3330,7 +3401,7 @@ thunar_file_get_icon_name (const ThunarFile *file,
* 'Thunar', 'xfmedia', etc.).
*/
if (G_UNLIKELY (thunar_file_is_executable (file)))
- {
+ {g_message("exect crap");
icon_name = g_file_get_basename (file->gfile);
if (G_LIKELY (!gtk_icon_theme_has_icon (icon_theme, icon_name)))
{
diff --git a/thunar/thunar-file.h b/thunar/thunar-file.h
index 7d04b60..48b3770 100644
--- a/thunar/thunar-file.h
+++ b/thunar/thunar-file.h
@@ -118,12 +118,15 @@ GType thunar_file_get_type (void) G_GNUC_CONST;
ThunarFile *thunar_file_get (GFile *file,
GError **error);
+ThunarFile *thunar_file_get_with_info (GFile *file,
+ GFileInfo *info,
+ gboolean not_mounted);
ThunarFile *thunar_file_get_for_uri (const gchar *uri,
GError **error);
-void thunar_file_get_async (GFile *location,
- GCancellable *cancellable,
- ThunarFileGetFunc func,
- gpointer user_data);
+void thunar_file_get_async (GFile *location,
+ GCancellable *cancellable,
+ ThunarFileGetFunc func,
+ gpointer user_data);
GFile *thunar_file_get_file (const ThunarFile *file) G_GNUC_PURE;
diff --git a/thunar/thunar-io-jobs.c b/thunar/thunar-io-jobs.c
index a4b106c..9d904f9 100644
--- a/thunar/thunar-io-jobs.c
+++ b/thunar/thunar-io-jobs.c
@@ -57,7 +57,7 @@ _tij_collect_nofollow (ThunarJob *job,
/* try to scan the directory */
child_file_list = thunar_io_scan_directory (job, lp->data,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- TRUE, unlinking, &err);
+ TRUE, unlinking, FALSE, &err);
/* prepend the new files to the existing list */
file_list = thunar_g_file_list_prepend (file_list, lp->data);
@@ -1170,12 +1170,9 @@ _thunar_io_jobs_ls (ThunarJob *job,
GArray *param_values,
GError **error)
{
- ThunarFile *file;
- GError *err = NULL;
- GFile *directory;
- GList *file_list = NULL;
- GList *lp;
- GList *path_list;
+ GError *err = NULL;
+ GFile *directory;
+ GList *file_list = NULL;
_thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
_thunar_return_val_if_fail (param_values != NULL, FALSE);
@@ -1192,22 +1189,9 @@ _thunar_io_jobs_ls (ThunarJob *job,
_thunar_assert (G_IS_FILE (directory));
/* collect directory contents (non-recursively) */
- path_list = thunar_io_scan_directory (job, directory,
+ file_list = thunar_io_scan_directory (job, directory,
G_FILE_QUERY_INFO_NONE,
- FALSE, FALSE, &err);
-
- /* turn the GFile list into a ThunarFile list */
- for (lp = g_list_last (path_list);
- err == NULL && !exo_job_is_cancelled (EXO_JOB (job)) && lp != NULL;
- lp = lp->prev)
- {
- file = thunar_file_get (lp->data, &err);
- if (G_LIKELY (file != NULL))
- file_list = g_list_prepend (file_list, file);
- }
-
- /* free the GFile list */
- thunar_g_file_list_free (path_list);
+ FALSE, FALSE, TRUE, &err);
/* abort on errors or cancellation */
if (err != NULL)
diff --git a/thunar/thunar-io-scan-directory.c b/thunar/thunar-io-scan-directory.c
index 6c38733..66ddbdf 100644
--- a/thunar/thunar-io-scan-directory.c
+++ b/thunar/thunar-io-scan-directory.c
@@ -39,6 +39,7 @@ thunar_io_scan_directory (ThunarJob *job,
GFileQueryInfoFlags flags,
gboolean recursively,
gboolean unlinking,
+ gboolean return_thunar_files,
GError **error)
{
GFileEnumerator *enumerator;
@@ -48,6 +49,9 @@ thunar_io_scan_directory (ThunarJob *job,
GFile *child_file;
GList *child_files = NULL;
GList *files = NULL;
+ const gchar *namespace;
+ ThunarFile *thunar_file;
+ gboolean is_mounted;
_thunar_return_val_if_fail (THUNAR_IS_JOB (job), NULL);
_thunar_return_val_if_fail (G_IS_FILE (file), NULL);
@@ -80,10 +84,15 @@ thunar_io_scan_directory (ThunarJob *job,
if (type != G_FILE_TYPE_DIRECTORY)
return NULL;
+ /* determine the namespace */
+ if (return_thunar_files)
+ namespace = THUNARX_FILE_INFO_NAMESPACE;
+ else
+ namespace = G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_NAME;
+
/* try to read from the direectory */
- enumerator = g_file_enumerate_children (file,
- G_FILE_ATTRIBUTE_STANDARD_TYPE ","
- G_FILE_ATTRIBUTE_STANDARD_NAME,
+ enumerator = g_file_enumerate_children (file, namespace,
flags, exo_job_get_cancellable (EXO_JOB (job)),
&err);
@@ -93,36 +102,64 @@ thunar_io_scan_directory (ThunarJob *job,
g_propagate_error (error, err);
return NULL;
}
-
- /* query info of the first child */
- info = g_file_enumerator_next_file (enumerator,
- exo_job_get_cancellable (EXO_JOB (job)),
- &err);
-
- /* iterate over children one by one as long as there's no error */
- while (info != NULL && err == NULL && !exo_job_is_cancelled (EXO_JOB (job)))
+
+ /* iterate over children one by one */
+ while (!exo_job_is_cancelled (EXO_JOB (job)))
{
- /* create GFile for the child and prepend it to the file list */
+ /* query info of the child */
+ info = g_file_enumerator_next_file (enumerator,
+ exo_job_get_cancellable (EXO_JOB (job)),
+ &err);
+
+ if (G_UNLIKELY (info == NULL))
+ break;
+
+ is_mounted = TRUE;
+ if (err != NULL)
+ {
+ if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED))
+ {
+ is_mounted = FALSE;
+ g_clear_error (&err);
+ }
+ else
+ {
+ /* break on errors */
+ break;
+ }
+ }
+
+ /* create GFile for the child */
child_file = g_file_get_child (file, g_file_info_get_name (info));
- files = thunar_g_file_list_prepend (files, child_file);
+
+ if (return_thunar_files)
+ {
+ /* Prepend the ThunarFile */
+ thunar_file = thunar_file_get_with_info (child_file, info, !is_mounted);
+ files = thunar_g_file_list_prepend (files, thunar_file);
+ g_object_unref (G_OBJECT (thunar_file));
+ }
+ else
+ {
+ /* Prepend the GFile */
+ files = thunar_g_file_list_prepend (files, child_file);
+ }
/* if the child is a directory and we need to recurse ... just do so */
- if (recursively && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+ if (recursively
+ && is_mounted
+ && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
{
child_files = thunar_io_scan_directory (job, child_file, flags, recursively,
- unlinking, &err);
+ unlinking, return_thunar_files, &err);
/* prepend children to the file list to make sure they're
* processed first (required for unlinking) */
files = g_list_concat (child_files, files);
}
-
+
g_object_unref (child_file);
g_object_unref (info);
-
- info = g_file_enumerator_next_file (enumerator,
- exo_job_get_cancellable (EXO_JOB (job)),
- &err);
}
/* release the enumerator */
diff --git a/thunar/thunar-io-scan-directory.h b/thunar/thunar-io-scan-directory.h
index 1ace975..8137d6a 100644
--- a/thunar/thunar-io-scan-directory.h
+++ b/thunar/thunar-io-scan-directory.h
@@ -33,6 +33,7 @@ GList *thunar_io_scan_directory (ThunarJob *job,
GFileQueryInfoFlags flags,
gboolean recursively,
gboolean unlinking,
+ gboolean return_thunar_files,
GError **error);
G_END_DECLS
diff --git a/thunar/thunar-misc-jobs.c b/thunar/thunar-misc-jobs.c
index eddc2e1..373e2f5 100644
--- a/thunar/thunar-misc-jobs.c
+++ b/thunar/thunar-misc-jobs.c
@@ -37,13 +37,10 @@ _thunar_misc_jobs_load_templates (ThunarJob *job,
GArray *param_values,
GError **error)
{
- ThunarFile *file;
GtkWidget *menu;
GFile *home_dir;
GFile *templates_dir;
GList *files = NULL;
- GList *lp;
- GList *paths = NULL;
const gchar *path;
_thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
@@ -62,22 +59,10 @@ _thunar_misc_jobs_load_templates (ThunarJob *job,
if (G_LIKELY (!g_file_equal (templates_dir, home_dir)))
{
- paths = thunar_io_scan_directory (job, templates_dir,
+ /* load the ThunarFiles */
+ files = thunar_io_scan_directory (job, templates_dir,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- TRUE, FALSE, NULL);
-
- /* turn the GFile list into a ThunarFile list */
- for (lp = g_list_last (paths);
- lp != NULL && !exo_job_is_cancelled (EXO_JOB (job));
- lp = lp->prev)
- {
- file = thunar_file_get (lp->data, NULL);
- if (G_LIKELY (file != NULL))
- files = g_list_prepend (files, file);
- }
-
- /* free the GFile list */
- thunar_g_file_list_free (paths);
+ TRUE, FALSE, TRUE, NULL);
}
g_object_unref (templates_dir);
diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c
index 178a5bc..b33557c 100644
--- a/thunar/thunar-transfer-job.c
+++ b/thunar/thunar-transfer-job.c
@@ -222,7 +222,7 @@ thunar_transfer_job_collect_node (ThunarTransferJob *job,
/* scan the directory for immediate children */
file_list = thunar_io_scan_directory (THUNAR_JOB (job), node->source_file,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- FALSE, FALSE, &err);
+ FALSE, FALSE, FALSE, &err);
/* add children to the transfer node */
for (lp = file_list; err == NULL && lp != NULL; lp = lp->next)
More information about the Xfce4-commits
mailing list