1 #include "xapp-favorites.h"
2 #include "favorite-vfs-file-enumerator.h"
3 #include "favorite-vfs-file.h"
4
5 #define DEBUG_FLAG XAPP_DEBUG_FAVORITE_VFS
6 #include "xapp-debug.h"
7
8 typedef struct
9 {
10 GFile *file;
11
12 GList *uris;
13 gchar *attributes;
14 GFileQueryInfoFlags flags;
15
16 GList *current_pos;
17 } FavoriteVfsFileEnumeratorPrivate;
18
19 struct _FavoriteVfsFileEnumerator
20 {
21 GObject parent_instance;
22 FavoriteVfsFileEnumeratorPrivate *priv;
23 };
24
G_DEFINE_TYPE_WITH_PRIVATE(FavoriteVfsFileEnumerator,favorite_vfs_file_enumerator,G_TYPE_FILE_ENUMERATOR)25 G_DEFINE_TYPE_WITH_PRIVATE(FavoriteVfsFileEnumerator,
26 favorite_vfs_file_enumerator,
27 G_TYPE_FILE_ENUMERATOR)
28
29 static GFileInfo *
30 next_file (GFileEnumerator *enumerator,
31 GCancellable *cancellable,
32 GError **error)
33 {
34 FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (enumerator);
35 FavoriteVfsFileEnumeratorPrivate *priv = favorite_vfs_file_enumerator_get_instance_private (self);
36 GFileInfo *info;
37
38 if (g_cancellable_set_error_if_cancelled (cancellable, error))
39 {
40 return NULL;
41 }
42
43 info = NULL;
44
45 while (priv->current_pos != NULL && info == NULL)
46 {
47 gchar *uri;
48
49 uri = path_to_fav_uri ((const gchar *) priv->current_pos->data);
50 if (!xapp_favorites_find_by_display_name (xapp_favorites_get_default (), (gchar *) priv->current_pos->data))
51 {
52 if (error)
53 {
54 *error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "File not found");
55 }
56
57 g_warn_if_reached ();
58 }
59 else
60 {
61 GFile *file;
62
63 file = g_file_new_for_uri (uri);
64 info = g_file_query_info (file,
65 priv->attributes,
66 priv->flags,
67 cancellable,
68 error);
69
70 g_object_unref (file);
71 }
72
73 g_free (uri);
74 }
75
76 if (priv->current_pos)
77 {
78 priv->current_pos = priv->current_pos->next;
79 }
80
81 return info;
82 }
83
84 static void
next_async_op_free(GList * files)85 next_async_op_free (GList *files)
86 {
87 g_list_free_full (files, g_object_unref);
88 }
89
90 static void
next_files_async_thread(GTask * task,gpointer source_object,gpointer task_data,GCancellable * cancellable)91 next_files_async_thread (GTask *task,
92 gpointer source_object,
93 gpointer task_data,
94 GCancellable *cancellable)
95 {
96 FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (source_object);
97 GList *ret;
98 GError *error = NULL;
99 gint i, n_requested;
100
101 n_requested = GPOINTER_TO_INT (g_task_get_task_data (task));
102
103 ret = NULL;
104
105 for (i = 0; i < n_requested; i++)
106 {
107 GFileInfo *info = NULL;
108 // g_clear_error (&error);
109
110 if (g_cancellable_set_error_if_cancelled (cancellable, &error))
111 {
112 g_task_return_error (task, error);
113 return;
114 }
115 else
116 {
117 info = next_file (G_FILE_ENUMERATOR (self), cancellable, &error);
118 }
119
120 if (info != NULL)
121 {
122 ret = g_list_prepend (ret, info);
123 }
124 else
125 {
126 if (error)
127 {
128 g_critical ("ERROR: %s\n", error->message);
129 }
130 break;
131 }
132 }
133
134 if (error)
135 {
136 g_task_return_error (task, error);
137 }
138 else
139 {
140 ret = g_list_reverse (ret);
141 g_task_return_pointer (task, ret, (GDestroyNotify) next_async_op_free);
142 }
143 }
144
145 static void
next_files_async(GFileEnumerator * enumerator,gint num_files,gint io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)146 next_files_async (GFileEnumerator *enumerator,
147 gint num_files,
148 gint io_priority,
149 GCancellable *cancellable,
150 GAsyncReadyCallback callback,
151 gpointer user_data)
152 {
153 // FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (enumerator);
154
155 GTask *task;
156 task = g_task_new (enumerator, cancellable, callback, user_data);
157 g_task_set_priority (task, io_priority);
158 g_task_set_task_data (task, GINT_TO_POINTER (num_files), NULL);
159
160 g_task_run_in_thread (task, next_files_async_thread);
161 g_object_unref (task);
162 }
163
164 static GList *
next_files_finished(GFileEnumerator * enumerator,GAsyncResult * result,GError ** error)165 next_files_finished (GFileEnumerator *enumerator,
166 GAsyncResult *result,
167 GError **error)
168 {
169 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
170 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
171
172 return (GList *) g_task_propagate_pointer (G_TASK (result), error);
173 }
174
175 static gboolean
close_fn(GFileEnumerator * enumerator,GCancellable * cancellable,GError ** error)176 close_fn (GFileEnumerator *enumerator,
177 GCancellable *cancellable,
178 GError **error)
179 {
180 // FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (enumerator);
181
182 return TRUE;
183 }
184
185 static void
favorite_vfs_file_enumerator_init(FavoriteVfsFileEnumerator * self)186 favorite_vfs_file_enumerator_init (FavoriteVfsFileEnumerator *self)
187 {
188 }
189
190 static void
favorite_vfs_file_enumerator_dispose(GObject * object)191 favorite_vfs_file_enumerator_dispose (GObject *object)
192 {
193 G_OBJECT_CLASS (favorite_vfs_file_enumerator_parent_class)->dispose (object);
194 }
195
196 static void
favorite_vfs_file_enumerator_finalize(GObject * object)197 favorite_vfs_file_enumerator_finalize (GObject *object)
198 {
199 FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR(object);
200 FavoriteVfsFileEnumeratorPrivate *priv = favorite_vfs_file_enumerator_get_instance_private(self);
201
202 g_list_free_full (priv->uris, (GDestroyNotify) g_free);
203 g_free (priv->attributes);
204 g_object_unref (priv->file);
205
206 G_OBJECT_CLASS (favorite_vfs_file_enumerator_parent_class)->finalize (object);
207 }
208
209 static void
favorite_vfs_file_enumerator_class_init(FavoriteVfsFileEnumeratorClass * klass)210 favorite_vfs_file_enumerator_class_init (FavoriteVfsFileEnumeratorClass *klass)
211 {
212 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
213 GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass);
214
215 gobject_class->dispose = favorite_vfs_file_enumerator_dispose;
216 gobject_class->finalize = favorite_vfs_file_enumerator_finalize;
217
218 enumerator_class->next_file = next_file;
219 enumerator_class->next_files_async = next_files_async;
220 enumerator_class->next_files_finish = next_files_finished;
221 enumerator_class->close_fn = close_fn;
222 }
223
224 GFileEnumerator *
favorite_vfs_file_enumerator_new(GFile * file,const gchar * attributes,GFileQueryInfoFlags flags,GList * uris)225 favorite_vfs_file_enumerator_new (GFile *file,
226 const gchar *attributes,
227 GFileQueryInfoFlags flags,
228 GList *uris)
229 {
230 FavoriteVfsFileEnumerator *enumerator = g_object_new (FAVORITE_TYPE_VFS_FILE_ENUMERATOR, NULL);
231 FavoriteVfsFileEnumeratorPrivate *priv = favorite_vfs_file_enumerator_get_instance_private(enumerator);
232
233 priv->uris = g_list_copy_deep (uris, (GCopyFunc) g_strdup, NULL);
234 priv->current_pos = priv->uris;
235
236 priv->file = g_object_ref (file);
237 priv->attributes = g_strdup (attributes);
238 priv->flags = flags;
239
240 return G_FILE_ENUMERATOR (enumerator);
241 }
242
243