gio/auto/
file_enumerator.rs

1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// DO NOT EDIT
4
5use crate::{ffi, AsyncResult, Cancellable, File, FileInfo};
6use glib::{prelude::*, translate::*};
7use std::{boxed::Box as Box_, pin::Pin};
8
9glib::wrapper! {
10    /// `GFileEnumerator` allows you to operate on a set of [`File`][crate::File] objects,
11    /// returning a [`FileInfo`][crate::FileInfo] structure for each file enumerated (e.g.
12    /// [`FileExt::enumerate_children()`][crate::prelude::FileExt::enumerate_children()] will return a `GFileEnumerator` for each
13    /// of the children within a directory).
14    ///
15    /// To get the next file's information from a `GFileEnumerator`, use
16    /// [`FileEnumeratorExt::next_file()`][crate::prelude::FileEnumeratorExt::next_file()] or its asynchronous version,
17    /// [`FileEnumeratorExt::next_files_async()`][crate::prelude::FileEnumeratorExt::next_files_async()]. Note that the asynchronous
18    /// version will return a list of [`FileInfo`][crate::FileInfo] objects, whereas the
19    /// synchronous will only return the next file in the enumerator.
20    ///
21    /// The ordering of returned files is unspecified for non-Unix
22    /// platforms; for more information, see `GLib::Dir::read_name()`.  On Unix,
23    /// when operating on local files, returned files will be sorted by
24    /// inode number.  Effectively you can assume that the ordering of
25    /// returned files will be stable between successive calls (and
26    /// applications) assuming the directory is unchanged.
27    ///
28    /// If your application needs a specific ordering, such as by name or
29    /// modification time, you will have to implement that in your
30    /// application code.
31    ///
32    /// To close a `GFileEnumerator`, use [`FileEnumeratorExtManual::close()`][crate::prelude::FileEnumeratorExtManual::close()], or
33    /// its asynchronous version, [`FileEnumeratorExt::close_async()`][crate::prelude::FileEnumeratorExt::close_async()]. Once
34    /// a `GFileEnumerator` is closed, no further actions may be performed
35    /// on it, and it should be freed with `GObject::Object::unref()`.
36    ///
37    /// ## Properties
38    ///
39    ///
40    /// #### `container`
41    ///  The container that is being enumerated.
42    ///
43    /// Writeable | Construct Only
44    ///
45    /// # Implements
46    ///
47    /// [`FileEnumeratorExt`][trait@crate::prelude::FileEnumeratorExt], [`trait@glib::ObjectExt`], [`FileEnumeratorExtManual`][trait@crate::prelude::FileEnumeratorExtManual]
48    #[doc(alias = "GFileEnumerator")]
49    pub struct FileEnumerator(Object<ffi::GFileEnumerator, ffi::GFileEnumeratorClass>);
50
51    match fn {
52        type_ => || ffi::g_file_enumerator_get_type(),
53    }
54}
55
56impl FileEnumerator {
57    pub const NONE: Option<&'static FileEnumerator> = None;
58}
59
60/// Trait containing all [`struct@FileEnumerator`] methods.
61///
62/// # Implementors
63///
64/// [`FileEnumerator`][struct@crate::FileEnumerator]
65pub trait FileEnumeratorExt: IsA<FileEnumerator> + 'static {
66    /// Asynchronously closes the file enumerator.
67    ///
68    /// If @cancellable is not [`None`], then the operation can be cancelled by
69    /// triggering the cancellable object from another thread. If the operation
70    /// was cancelled, the error [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled] will be returned in
71    /// g_file_enumerator_close_finish().
72    /// ## `io_priority`
73    /// the [I/O priority](iface.AsyncResult.html#io-priority) of the request
74    /// ## `cancellable`
75    /// optional #GCancellable object, [`None`] to ignore.
76    /// ## `callback`
77    /// a #GAsyncReadyCallback
78    ///   to call when the request is satisfied
79    #[doc(alias = "g_file_enumerator_close_async")]
80    fn close_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
81        &self,
82        io_priority: glib::Priority,
83        cancellable: Option<&impl IsA<Cancellable>>,
84        callback: P,
85    ) {
86        let main_context = glib::MainContext::ref_thread_default();
87        let is_main_context_owner = main_context.is_owner();
88        let has_acquired_main_context = (!is_main_context_owner)
89            .then(|| main_context.acquire().ok())
90            .flatten();
91        assert!(
92            is_main_context_owner || has_acquired_main_context.is_some(),
93            "Async operations only allowed if the thread is owning the MainContext"
94        );
95
96        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
97            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
98        unsafe extern "C" fn close_async_trampoline<
99            P: FnOnce(Result<(), glib::Error>) + 'static,
100        >(
101            _source_object: *mut glib::gobject_ffi::GObject,
102            res: *mut crate::ffi::GAsyncResult,
103            user_data: glib::ffi::gpointer,
104        ) {
105            let mut error = std::ptr::null_mut();
106            ffi::g_file_enumerator_close_finish(_source_object as *mut _, res, &mut error);
107            let result = if error.is_null() {
108                Ok(())
109            } else {
110                Err(from_glib_full(error))
111            };
112            let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
113                Box_::from_raw(user_data as *mut _);
114            let callback: P = callback.into_inner();
115            callback(result);
116        }
117        let callback = close_async_trampoline::<P>;
118        unsafe {
119            ffi::g_file_enumerator_close_async(
120                self.as_ref().to_glib_none().0,
121                io_priority.into_glib(),
122                cancellable.map(|p| p.as_ref()).to_glib_none().0,
123                Some(callback),
124                Box_::into_raw(user_data) as *mut _,
125            );
126        }
127    }
128
129    fn close_future(
130        &self,
131        io_priority: glib::Priority,
132    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
133        Box_::pin(crate::GioFuture::new(
134            self,
135            move |obj, cancellable, send| {
136                obj.close_async(io_priority, Some(cancellable), move |res| {
137                    send.resolve(res);
138                });
139            },
140        ))
141    }
142
143    /// Return a new #GFile which refers to the file named by @info in the source
144    /// directory of @self.  This function is primarily intended to be used
145    /// inside loops with g_file_enumerator_next_file().
146    ///
147    /// To use this, [`FILE_ATTRIBUTE_STANDARD_NAME`][crate::FILE_ATTRIBUTE_STANDARD_NAME] must have been listed in the
148    /// attributes list used when creating the #GFileEnumerator.
149    ///
150    /// This is a convenience method that's equivalent to:
151    ///
152    ///
153    /// **⚠️ The following code is in C ⚠️**
154    ///
155    /// ```C
156    ///   gchar *name = g_file_info_get_name (info);
157    ///   GFile *child = g_file_get_child (g_file_enumerator_get_container (enumr),
158    ///                                    name);
159    /// ```
160    /// ## `info`
161    /// a #GFileInfo gotten from g_file_enumerator_next_file()
162    ///   or the async equivalents.
163    ///
164    /// # Returns
165    ///
166    /// a #GFile for the #GFileInfo passed it.
167    #[doc(alias = "g_file_enumerator_get_child")]
168    #[doc(alias = "get_child")]
169    fn child(&self, info: &FileInfo) -> File {
170        unsafe {
171            from_glib_full(ffi::g_file_enumerator_get_child(
172                self.as_ref().to_glib_none().0,
173                info.to_glib_none().0,
174            ))
175        }
176    }
177
178    /// Get the #GFile container which is being enumerated.
179    ///
180    /// # Returns
181    ///
182    /// the #GFile which is being enumerated.
183    #[doc(alias = "g_file_enumerator_get_container")]
184    #[doc(alias = "get_container")]
185    fn container(&self) -> File {
186        unsafe {
187            from_glib_none(ffi::g_file_enumerator_get_container(
188                self.as_ref().to_glib_none().0,
189            ))
190        }
191    }
192
193    /// Checks if the file enumerator has pending operations.
194    ///
195    /// # Returns
196    ///
197    /// [`true`] if the @self has pending operations.
198    #[doc(alias = "g_file_enumerator_has_pending")]
199    fn has_pending(&self) -> bool {
200        unsafe {
201            from_glib(ffi::g_file_enumerator_has_pending(
202                self.as_ref().to_glib_none().0,
203            ))
204        }
205    }
206
207    /// Checks if the file enumerator has been closed.
208    ///
209    /// # Returns
210    ///
211    /// [`true`] if the @self is closed.
212    #[doc(alias = "g_file_enumerator_is_closed")]
213    fn is_closed(&self) -> bool {
214        unsafe {
215            from_glib(ffi::g_file_enumerator_is_closed(
216                self.as_ref().to_glib_none().0,
217            ))
218        }
219    }
220
221    /// Returns information for the next file in the enumerated object.
222    /// Will block until the information is available. The #GFileInfo
223    /// returned from this function will contain attributes that match the
224    /// attribute string that was passed when the #GFileEnumerator was created.
225    ///
226    /// See the documentation of #GFileEnumerator for information about the
227    /// order of returned files.
228    ///
229    /// On error, returns [`None`] and sets @error to the error. If the
230    /// enumerator is at the end, [`None`] will be returned and @error will
231    /// be unset.
232    /// ## `cancellable`
233    /// optional #GCancellable object, [`None`] to ignore.
234    ///
235    /// # Returns
236    ///
237    /// A #GFileInfo or [`None`] on error
238    ///    or end of enumerator.  Free the returned object with
239    ///    g_object_unref() when no longer needed.
240    #[doc(alias = "g_file_enumerator_next_file")]
241    fn next_file(
242        &self,
243        cancellable: Option<&impl IsA<Cancellable>>,
244    ) -> Result<Option<FileInfo>, glib::Error> {
245        unsafe {
246            let mut error = std::ptr::null_mut();
247            let ret = ffi::g_file_enumerator_next_file(
248                self.as_ref().to_glib_none().0,
249                cancellable.map(|p| p.as_ref()).to_glib_none().0,
250                &mut error,
251            );
252            if error.is_null() {
253                Ok(from_glib_full(ret))
254            } else {
255                Err(from_glib_full(error))
256            }
257        }
258    }
259
260    /// Request information for a number of files from the enumerator asynchronously.
261    /// When all I/O for the operation is finished the @callback will be called with
262    /// the requested information.
263    ///
264    /// See the documentation of #GFileEnumerator for information about the
265    /// order of returned files.
266    ///
267    /// Once the end of the enumerator is reached, or if an error occurs, the
268    /// @callback will be called with an empty list. In this case, the previous call
269    /// to g_file_enumerator_next_files_async() will typically have returned fewer
270    /// than @num_files items.
271    ///
272    /// If a request is cancelled the callback will be called with
273    /// [`IOErrorEnum::Cancelled`][crate::IOErrorEnum::Cancelled].
274    ///
275    /// This leads to the following pseudo-code usage:
276    ///
277    /// ```text
278    /// g_autoptr(GFile) dir = get_directory ();
279    /// g_autoptr(GFileEnumerator) enumerator = NULL;
280    /// g_autolist(GFileInfo) files = NULL;
281    /// g_autoptr(GError) local_error = NULL;
282    ///
283    /// enumerator = yield g_file_enumerate_children_async (dir,
284    ///                                                     G_FILE_ATTRIBUTE_STANDARD_NAME ","
285    ///                                                     G_FILE_ATTRIBUTE_STANDARD_TYPE,
286    ///                                                     G_FILE_QUERY_INFO_NONE,
287    ///                                                     G_PRIORITY_DEFAULT,
288    ///                                                     cancellable,
289    ///                                                     …,
290    ///                                                     &local_error);
291    /// if (enumerator == NULL)
292    ///   g_error ("Error enumerating: %s", local_error->message);
293    ///
294    /// // Loop until no files are returned, either because the end of the enumerator
295    /// // has been reached, or an error was returned.
296    /// do
297    ///   {
298    ///     files = yield g_file_enumerator_next_files_async (enumerator,
299    ///                                                       5,  // number of files to request
300    ///                                                       G_PRIORITY_DEFAULT,
301    ///                                                       cancellable,
302    ///                                                       …,
303    ///                                                       &local_error);
304    ///
305    ///     // Process the returned files, but don’t assume that exactly 5 were returned.
306    ///     for (GList *l = files; l != NULL; l = l->next)
307    ///       {
308    ///         GFileInfo *info = l->data;
309    ///         handle_file_info (info);
310    ///       }
311    ///   }
312    /// while (files != NULL);
313    ///
314    /// if (local_error != NULL &&
315    ///     !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
316    ///   g_error ("Error while enumerating: %s", local_error->message);
317    /// ```
318    ///
319    /// During an async request no other sync and async calls are allowed, and will
320    /// result in [`IOErrorEnum::Pending`][crate::IOErrorEnum::Pending] errors.
321    ///
322    /// Any outstanding I/O request with higher priority (lower numerical value) will
323    /// be executed before an outstanding request with lower priority. Default
324    /// priority is `G_PRIORITY_DEFAULT`.
325    /// ## `num_files`
326    /// the number of file info objects to request
327    /// ## `io_priority`
328    /// the [I/O priority](iface.AsyncResult.html#io-priority) of the request
329    /// ## `cancellable`
330    /// optional #GCancellable object, [`None`] to ignore.
331    /// ## `callback`
332    /// a #GAsyncReadyCallback
333    ///   to call when the request is satisfied
334    #[doc(alias = "g_file_enumerator_next_files_async")]
335    fn next_files_async<P: FnOnce(Result<Vec<FileInfo>, glib::Error>) + 'static>(
336        &self,
337        num_files: i32,
338        io_priority: glib::Priority,
339        cancellable: Option<&impl IsA<Cancellable>>,
340        callback: P,
341    ) {
342        let main_context = glib::MainContext::ref_thread_default();
343        let is_main_context_owner = main_context.is_owner();
344        let has_acquired_main_context = (!is_main_context_owner)
345            .then(|| main_context.acquire().ok())
346            .flatten();
347        assert!(
348            is_main_context_owner || has_acquired_main_context.is_some(),
349            "Async operations only allowed if the thread is owning the MainContext"
350        );
351
352        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
353            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
354        unsafe extern "C" fn next_files_async_trampoline<
355            P: FnOnce(Result<Vec<FileInfo>, glib::Error>) + 'static,
356        >(
357            _source_object: *mut glib::gobject_ffi::GObject,
358            res: *mut crate::ffi::GAsyncResult,
359            user_data: glib::ffi::gpointer,
360        ) {
361            let mut error = std::ptr::null_mut();
362            let ret =
363                ffi::g_file_enumerator_next_files_finish(_source_object as *mut _, res, &mut error);
364            let result = if error.is_null() {
365                Ok(FromGlibPtrContainer::from_glib_full(ret))
366            } else {
367                Err(from_glib_full(error))
368            };
369            let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
370                Box_::from_raw(user_data as *mut _);
371            let callback: P = callback.into_inner();
372            callback(result);
373        }
374        let callback = next_files_async_trampoline::<P>;
375        unsafe {
376            ffi::g_file_enumerator_next_files_async(
377                self.as_ref().to_glib_none().0,
378                num_files,
379                io_priority.into_glib(),
380                cancellable.map(|p| p.as_ref()).to_glib_none().0,
381                Some(callback),
382                Box_::into_raw(user_data) as *mut _,
383            );
384        }
385    }
386
387    fn next_files_future(
388        &self,
389        num_files: i32,
390        io_priority: glib::Priority,
391    ) -> Pin<Box_<dyn std::future::Future<Output = Result<Vec<FileInfo>, glib::Error>> + 'static>>
392    {
393        Box_::pin(crate::GioFuture::new(
394            self,
395            move |obj, cancellable, send| {
396                obj.next_files_async(num_files, io_priority, Some(cancellable), move |res| {
397                    send.resolve(res);
398                });
399            },
400        ))
401    }
402
403    /// Sets the file enumerator as having pending operations.
404    /// ## `pending`
405    /// a boolean value.
406    #[doc(alias = "g_file_enumerator_set_pending")]
407    fn set_pending(&self, pending: bool) {
408        unsafe {
409            ffi::g_file_enumerator_set_pending(self.as_ref().to_glib_none().0, pending.into_glib());
410        }
411    }
412}
413
414impl<O: IsA<FileEnumerator>> FileEnumeratorExt for O {}