#include "xapp-favorites.h" #include "favorite-vfs-file-enumerator.h" #include "favorite-vfs-file.h" typedef struct { GFile *file; GList *uris; gchar *attributes; GFileQueryInfoFlags flags; GList *current_pos; } FavoriteVfsFileEnumeratorPrivate; struct _FavoriteVfsFileEnumerator { GObject parent_instance; FavoriteVfsFileEnumeratorPrivate *priv; }; G_DEFINE_TYPE_WITH_PRIVATE(FavoriteVfsFileEnumerator, favorite_vfs_file_enumerator, G_TYPE_FILE_ENUMERATOR) static GFileInfo * next_file (GFileEnumerator *enumerator, GCancellable *cancellable, GError **error) { FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (enumerator); FavoriteVfsFileEnumeratorPrivate *priv = favorite_vfs_file_enumerator_get_instance_private (self); GFileInfo *info; if (cancellable) { if (g_cancellable_is_cancelled (cancellable)) { *error = g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Enumerate canceled"); return NULL; } } info = NULL; while (priv->current_pos != NULL && info == NULL) { GFile *file; gchar *uri; uri = path_to_fav_uri ((const gchar *) priv->current_pos->data); if (!xapp_favorites_find_by_display_name (xapp_favorites_get_default (), (gchar *) priv->current_pos->data)) { *error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "File not found"); g_warn_if_reached (); } else { file = g_file_new_for_uri (uri); info = g_file_query_info (file, priv->attributes, priv->flags, cancellable, error); } g_free (uri); g_object_unref (file); } if (priv->current_pos) { priv->current_pos = priv->current_pos->next; } return info; } static void next_async_op_free (GList *files) { g_list_free_full (files, g_object_unref); } static void next_files_async_thread (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (source_object); GList *ret; GError *error = NULL; gint i, n_requested; n_requested = GPOINTER_TO_INT (g_task_get_task_data (task)); ret = NULL; for (i = 0; i < n_requested; i++) { GFileInfo *info = NULL; // g_clear_error (&error); if (g_cancellable_set_error_if_cancelled (cancellable, &error)) { g_task_return_error (task, error); return; } else { info = next_file (G_FILE_ENUMERATOR (self), cancellable, &error); } if (info != NULL) { ret = g_list_prepend (ret, info); } else { if (error) { g_critical ("ERROR: %s\n", error->message); } break; } } if (error) { g_task_return_error (task, error); } else { ret = g_list_reverse (ret); g_task_return_pointer (task, ret, (GDestroyNotify) next_async_op_free); } } static void next_files_async (GFileEnumerator *enumerator, gint num_files, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { // FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (enumerator); GTask *task; task = g_task_new (enumerator, cancellable, callback, user_data); g_task_set_priority (task, io_priority); g_task_set_task_data (task, GINT_TO_POINTER (num_files), NULL); g_task_run_in_thread (task, next_files_async_thread); g_object_unref (task); } static GList * next_files_finished (GFileEnumerator *enumerator, GAsyncResult *result, GError **error) { g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL); g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL); return (GList *) g_task_propagate_pointer (G_TASK (result), error); } static gboolean close_fn (GFileEnumerator *enumerator, GCancellable *cancellable, GError **error) { // FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (enumerator); return TRUE; } static void favorite_vfs_file_enumerator_init (FavoriteVfsFileEnumerator *self) { } static void favorite_vfs_file_enumerator_dispose (GObject *object) { G_OBJECT_CLASS (favorite_vfs_file_enumerator_parent_class)->dispose (object); } static void favorite_vfs_file_enumerator_finalize (GObject *object) { FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR(object); FavoriteVfsFileEnumeratorPrivate *priv = favorite_vfs_file_enumerator_get_instance_private(self); g_list_free_full (priv->uris, (GDestroyNotify) g_free); g_free (priv->attributes); g_object_unref (priv->file); G_OBJECT_CLASS (favorite_vfs_file_enumerator_parent_class)->finalize (object); } static void favorite_vfs_file_enumerator_class_init (FavoriteVfsFileEnumeratorClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass); gobject_class->dispose = favorite_vfs_file_enumerator_dispose; gobject_class->finalize = favorite_vfs_file_enumerator_finalize; enumerator_class->next_file = next_file; enumerator_class->next_files_async = next_files_async; enumerator_class->next_files_finish = next_files_finished; enumerator_class->close_fn = close_fn; } GFileEnumerator * favorite_vfs_file_enumerator_new (GFile *file, const gchar *attributes, GFileQueryInfoFlags flags, GList *uris) { FavoriteVfsFileEnumerator *enumerator = g_object_new (FAVORITE_TYPE_VFS_FILE_ENUMERATOR, NULL); FavoriteVfsFileEnumeratorPrivate *priv = favorite_vfs_file_enumerator_get_instance_private(enumerator); priv->uris = g_list_copy_deep (uris, (GCopyFunc) g_strdup, NULL); priv->current_pos = priv->uris; priv->file = g_object_ref (file); priv->attributes = g_strdup (attributes); priv->flags = flags; return G_FILE_ENUMERATOR (enumerator); }