Reputation: 630
I am making a GTK+3 App with GJS where users select a folder from a GtkFileChooserButton (action
property set to select-folder
). I want to find all image files in the given folder the user have selected, so I can display one of the images.
I tried this._fileChooserButton.get_files()
and this._folderChooseButton.get_uris()
but they only return one file, which is the path to the selected folder. Like this:
_init(application) {
this._folderChooseButton.connect('file-set', () => {
this._onFolderChosen();
});
}
_onFolderChosen() {
let folder = this._folderChooseButton.get_file();
// somehow get files from the folder here
this._image.set_from_file(files[1]);
}
From the API it is not really clear to me, how do I find out which image files are inside the user's selected directory (and subdirectories)?
Upvotes: 0
Views: 1174
Reputation: 630
OK, after help from patrick, georges and matthias at guadec, here is what I got.
The get_file()
function I tried returns a GFile, which in this case is a folder (in UNIX, folders are also files). In order to get the files within the directory path, we need to call enumerate_children_async()
on our GFile, returned by the get_file()
function.
The enumate_children_async()
function takes five parameters:
A comma-separated attribute list. In our case, since we want the identifiers of the children in the directory, we want to use the attribute called standard::name
.
FileQueryInfoFlag
: This allows to either follow or not follow symbolic links. In this case, we will use FileQueryInfoFlag.NONE
which will not follow symbolic links.
io_priority
: How high priority the IO operation should have (we will use GLib.PRIORITY_DEFAULT
)
cancellable
: A cancellable, which is a way to cancel this operation, in this case we will leave it as null.
callback
: This is the function/code you want to run in response to the files having been retreived.
More info on this function is at GJS-Docs at GNOME.org
The enumerate_children_async()
function returns a GFileEnumerator
, which we can use to retreive a number of the files, by calling next_files_async()
, which takes these arguments:
num_files
: How many files you want to retreive. In your case, we use 1.
io_priority
and cancellable
(same as above).
callback
: Where we can run a function or code to actually retreive the file.
Below, is the final code for doing this.
const { Gio, GLib, GObject, Gtk } = imports.gi; // import Gio and GLib API at top of your document.
_onFolderChosen() {
let folder = this._folderChooseButton.get_file();
let files = folder.enumerate_children_async(
'standard::name',
Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_DEFAULT,
null,
(source, result, data) => {
this._fileEnumerator = null;
try {
this._fileEnumerator = folder.enumerate_children_finish(result);
} catch (e) {
log('(Error) Could not retreive list of files! Error:' + e);
return;
}
this._readNextFile();
});
}
_readNextFile() {
if (!this._fileEnumerator)
return;
let fileInfo = null;
this._fileEnumerator.next_files_async(
1,
GLib.PRIORITY_DEFAULT,
null,
(source, result, data) => {
try {
fileInfo = this._fileEnumerator.next_files_finish(result);
} catch (e) {
log('Could not retreive the next file! Error:' + e);
return;
}
let file = fileInfo[0].get_name();
let filePath = GLib.build_filenamev([this._folderChooseButton.get_filename(), file]);
this._carousselImage.set_from_file(filePath);
});
}
Upvotes: 3