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