1/* GTK - The GIMP Toolkit
2 * gtkfilechooser.c: Abstract interface for file selector GUIs
3 * Copyright (C) 2003, Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20#include "gtkfilechooser.h"
21#include "gtkfilechooserprivate.h"
22#include "gtkintl.h"
23#include "gtktypebuiltins.h"
24#include "gtkprivate.h"
25#include "gtkmarshalers.h"
26
27
28/**
29 * GtkFileChooser:
30 *
31 * `GtkFileChooser` is an interface that can be implemented by file
32 * selection widgets.
33 *
34 * In GTK, the main objects that implement this interface are
35 * [class@Gtk.FileChooserWidget] and [class@Gtk.FileChooserDialog].
36 *
37 * You do not need to write an object that implements the `GtkFileChooser`
38 * interface unless you are trying to adapt an existing file selector to
39 * expose a standard programming interface.
40 *
41 * `GtkFileChooser` allows for shortcuts to various places in the filesystem.
42 * In the default implementation these are displayed in the left pane. It
43 * may be a bit confusing at first that these shortcuts come from various
44 * sources and in various flavours, so lets explain the terminology here:
45 *
46 * - Bookmarks: are created by the user, by dragging folders from the
47 * right pane to the left pane, or by using the “Add”. Bookmarks
48 * can be renamed and deleted by the user.
49 *
50 * - Shortcuts: can be provided by the application. For example, a Paint
51 * program may want to add a shortcut for a Clipart folder. Shortcuts
52 * cannot be modified by the user.
53 *
54 * - Volumes: are provided by the underlying filesystem abstraction. They are
55 * the “roots” of the filesystem.
56 *
57 * # File Names and Encodings
58 *
59 * When the user is finished selecting files in a `GtkFileChooser`, your
60 * program can get the selected filenames as `GFile`s.
61 *
62 * # Adding options
63 *
64 * You can add extra widgets to a file chooser to provide options
65 * that are not present in the default design, by using
66 * [method@Gtk.FileChooser.add_choice]. Each choice has an identifier and
67 * a user visible label; additionally, each choice can have multiple
68 * options. If a choice has no option, it will be rendered as a
69 * check button with the given label; if a choice has options, it will
70 * be rendered as a combo box.
71 */
72
73
74typedef GtkFileChooserIface GtkFileChooserInterface;
75G_DEFINE_INTERFACE (GtkFileChooser, gtk_file_chooser, G_TYPE_OBJECT);
76
77static void
78gtk_file_chooser_default_init (GtkFileChooserInterface *iface)
79{
80 /**
81 * GtkFileChooser:action: (attributes org.gtk.Property.get=gtk_file_chooser_get_action org.gtk.Property.set=gtk_file_chooser_set_action)
82 *
83 * The type of operation that the file chooser is performing.
84 */
85 g_object_interface_install_property (g_iface: iface,
86 pspec: g_param_spec_enum (name: "action",
87 P_("Action"),
88 P_("The type of operation that the file selector is performing"),
89 enum_type: GTK_TYPE_FILE_CHOOSER_ACTION,
90 default_value: GTK_FILE_CHOOSER_ACTION_OPEN,
91 GTK_PARAM_READWRITE));
92
93
94 /**
95 * GtkFileChooser:filter: (attributes org.gtk.Property.get=gtk_file_chooser_get_filter org.gtk.Property.set=gtk_file_chooser_set_filter)
96 *
97 * The current filter for selecting files that are displayed.
98 */
99 g_object_interface_install_property (g_iface: iface,
100 pspec: g_param_spec_object (name: "filter",
101 P_("Filter"),
102 P_("The current filter for selecting which files are displayed"),
103 GTK_TYPE_FILE_FILTER,
104 GTK_PARAM_READWRITE));
105
106 /**
107 * GtkFileChooser:select-multiple: (attributes org.gtk.Property.get=gtk_file_chooser_get_select_multiple org.gtk.Property.set=gtk_file_chooser_set_select_multiple)
108 *
109 * Whether to allow multiple files to be selected.
110 */
111 g_object_interface_install_property (g_iface: iface,
112 pspec: g_param_spec_boolean (name: "select-multiple",
113 P_("Select Multiple"),
114 P_("Whether to allow multiple files to be selected"),
115 FALSE,
116 GTK_PARAM_READWRITE));
117
118 /**
119 * GtkFileChooser:filters: (attributes org.gtk.Property.get=gtk_file_chooser_get_filters)
120 *
121 * A `GListModel` containing the filters that have been
122 * added with gtk_file_chooser_add_filter().
123 *
124 * The returned object should not be modified. It may
125 * or may not be updated for later changes.
126 */
127 g_object_interface_install_property (g_iface: iface,
128 pspec: g_param_spec_object (name: "filters",
129 P_("Filters"),
130 P_("List model of filters"),
131 G_TYPE_LIST_MODEL,
132 GTK_PARAM_READABLE));
133
134 /**
135 * GtkFileChooser:shortcut-folders: (attributes org.gtk.Property.get=gtk_file_chooser_get_shortcut_folders)
136 *
137 * A `GListModel` containing the shortcut folders that have been
138 * added with gtk_file_chooser_add_shortcut_folder().
139 *
140 * The returned object should not be modified. It may
141 * or may not be updated for later changes.
142 */
143 g_object_interface_install_property (g_iface: iface,
144 pspec: g_param_spec_object (name: "shortcut-folders",
145 P_("Shortcut Folders"),
146 P_("List model of shortcut folders"),
147 G_TYPE_LIST_MODEL,
148 GTK_PARAM_READABLE));
149
150 /**
151 * GtkFileChooser:create-folders: (attributes org.gtk.Property.get=gtk_file_chooser_get_create_folders org.gtk.Property.set=gtk_file_chooser_set_create_folders)
152 *
153 * Whether a file chooser not in %GTK_FILE_CHOOSER_ACTION_OPEN mode
154 * will offer the user to create new folders.
155 */
156 g_object_interface_install_property (g_iface: iface,
157 pspec: g_param_spec_boolean (name: "create-folders",
158 P_("Allow folder creation"),
159 P_("Whether a file chooser not in open mode "
160 "will offer the user to create new folders."),
161 TRUE,
162 GTK_PARAM_READWRITE));
163}
164
165/**
166 * gtk_file_chooser_error_quark:
167 *
168 * Registers an error quark for `GtkFileChooser` errors.
169 *
170 * Returns: The error quark used for `GtkFileChooser` errors.
171 **/
172GQuark
173gtk_file_chooser_error_quark (void)
174{
175 return g_quark_from_static_string (string: "gtk-file-chooser-error-quark");
176}
177
178/**
179 * gtk_file_chooser_set_action: (attributes org.gtk.Method.set_property=action)
180 * @chooser: a `GtkFileChooser`
181 * @action: the action that the file selector is performing
182 *
183 * Sets the type of operation that the chooser is performing.
184 *
185 * The user interface is adapted to suit the selected action.
186 *
187 * For example, an option to create a new folder might be shown
188 * if the action is %GTK_FILE_CHOOSER_ACTION_SAVE but not if the
189 * action is %GTK_FILE_CHOOSER_ACTION_OPEN.
190 **/
191void
192gtk_file_chooser_set_action (GtkFileChooser *chooser,
193 GtkFileChooserAction action)
194{
195 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
196
197 g_object_set (object: chooser, first_property_name: "action", action, NULL);
198}
199
200/**
201 * gtk_file_chooser_get_action: (attributes org.gtk.Method.get_property=action)
202 * @chooser: a `GtkFileChooser`
203 *
204 * Gets the type of operation that the file chooser is performing.
205 *
206 * Returns: the action that the file selector is performing
207 */
208GtkFileChooserAction
209gtk_file_chooser_get_action (GtkFileChooser *chooser)
210{
211 GtkFileChooserAction action;
212
213 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
214
215 g_object_get (object: chooser, first_property_name: "action", &action, NULL);
216
217 return action;
218}
219
220/**
221 * gtk_file_chooser_set_select_multiple: (attributes org.gtk.Method.set_property=select-multiple)
222 * @chooser: a `GtkFileChooser`
223 * @select_multiple: %TRUE if multiple files can be selected.
224 *
225 * Sets whether multiple files can be selected in the file chooser.
226 *
227 * This is only relevant if the action is set to be
228 * %GTK_FILE_CHOOSER_ACTION_OPEN or
229 * %GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER.
230 */
231void
232gtk_file_chooser_set_select_multiple (GtkFileChooser *chooser,
233 gboolean select_multiple)
234{
235 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
236
237 g_object_set (object: chooser, first_property_name: "select-multiple", select_multiple, NULL);
238}
239
240/**
241 * gtk_file_chooser_get_select_multiple: (attributes org.gtk.Method.get_property=select-multiple)
242 * @chooser: a `GtkFileChooser`
243 *
244 * Gets whether multiple files can be selected in the file
245 * chooser.
246 *
247 * Returns: %TRUE if multiple files can be selected.
248 */
249gboolean
250gtk_file_chooser_get_select_multiple (GtkFileChooser *chooser)
251{
252 gboolean select_multiple;
253
254 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
255
256 g_object_get (object: chooser, first_property_name: "select-multiple", &select_multiple, NULL);
257
258 return select_multiple;
259}
260
261/**
262 * gtk_file_chooser_set_create_folders: (attributes org.gtk.Method.set_property=create-folders)
263 * @chooser: a `GtkFileChooser`
264 * @create_folders: %TRUE if the Create Folder button should be displayed
265 *
266 * Sets whether file chooser will offer to create new folders.
267 *
268 * This is only relevant if the action is not set to be
269 * %GTK_FILE_CHOOSER_ACTION_OPEN.
270 */
271void
272gtk_file_chooser_set_create_folders (GtkFileChooser *chooser,
273 gboolean create_folders)
274{
275 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
276
277 g_object_set (object: chooser, first_property_name: "create-folders", create_folders, NULL);
278}
279
280/**
281 * gtk_file_chooser_get_create_folders: (attributes org.gtk.Method.get_property=create-folders)
282 * @chooser: a `GtkFileChooser`
283 *
284 * Gets whether file chooser will offer to create new folders.
285 *
286 * Returns: %TRUE if the Create Folder button should be displayed.
287 */
288gboolean
289gtk_file_chooser_get_create_folders (GtkFileChooser *chooser)
290{
291 gboolean create_folders;
292
293 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
294
295 g_object_get (object: chooser, first_property_name: "create-folders", &create_folders, NULL);
296
297 return create_folders;
298}
299
300/**
301 * gtk_file_chooser_set_current_name:
302 * @chooser: a `GtkFileChooser`
303 * @name: (type utf8): the filename to use, as a UTF-8 string
304 *
305 * Sets the current name in the file selector, as if entered
306 * by the user.
307 *
308 * Note that the name passed in here is a UTF-8 string rather
309 * than a filename. This function is meant for such uses as a
310 * suggested name in a “Save As...” dialog. You can pass
311 * “Untitled.doc” or a similarly suitable suggestion for the @name.
312 *
313 * If you want to preselect a particular existing file, you should
314 * use [method@Gtk.FileChooser.set_file] instead.
315 *
316 * Please see the documentation for those functions for an example
317 * of using [method@Gtk.FileChooser.set_current_name] as well.
318 **/
319void
320gtk_file_chooser_set_current_name (GtkFileChooser *chooser,
321 const char *name)
322{
323 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
324 g_return_if_fail (name != NULL);
325
326 GTK_FILE_CHOOSER_GET_IFACE (chooser)->set_current_name (chooser, name);
327}
328
329/**
330 * gtk_file_chooser_get_current_name:
331 * @chooser: a `GtkFileChooser`
332 *
333 * Gets the current name in the file selector, as entered by the user.
334 *
335 * This is meant to be used in save dialogs, to get the currently typed
336 * filename when the file itself does not exist yet.
337 *
338 * Returns: (nullable): The raw text from the file chooser’s “Name” entry. Free with
339 * g_free(). Note that this string is not a full pathname or URI; it is
340 * whatever the contents of the entry are. Note also that this string is
341 * in UTF-8 encoding, which is not necessarily the system’s encoding for
342 * filenames.
343 */
344char *
345gtk_file_chooser_get_current_name (GtkFileChooser *chooser)
346{
347 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
348
349 return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_current_name (chooser);
350}
351
352void
353gtk_file_chooser_select_all (GtkFileChooser *chooser)
354{
355 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
356
357 GTK_FILE_CHOOSER_GET_IFACE (chooser)->select_all (chooser);
358}
359
360void
361gtk_file_chooser_unselect_all (GtkFileChooser *chooser)
362{
363
364 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
365
366 GTK_FILE_CHOOSER_GET_IFACE (chooser)->unselect_all (chooser);
367}
368
369/**
370 * gtk_file_chooser_set_current_folder:
371 * @chooser: a `GtkFileChooser`
372 * @file: (nullable): the `GFile` for the new folder
373 * @error: location to store error
374 *
375 * Sets the current folder for @chooser from a `GFile`.
376 *
377 * Returns: %TRUE if the folder could be changed successfully, %FALSE
378 * otherwise.
379 */
380gboolean
381gtk_file_chooser_set_current_folder (GtkFileChooser *chooser,
382 GFile *file,
383 GError **error)
384{
385 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
386 g_return_val_if_fail (G_IS_FILE (file), FALSE);
387 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
388
389 return GTK_FILE_CHOOSER_GET_IFACE (chooser)->set_current_folder (chooser, file, error);
390}
391
392/**
393 * gtk_file_chooser_get_current_folder:
394 * @chooser: a `GtkFileChooser`
395 *
396 * Gets the current folder of @chooser as `GFile`.
397 *
398 * Returns: (transfer full) (nullable): the `GFile` for the current folder.
399 */
400GFile *
401gtk_file_chooser_get_current_folder (GtkFileChooser *chooser)
402{
403 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
404
405 return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_current_folder (chooser);
406}
407
408gboolean
409gtk_file_chooser_select_file (GtkFileChooser *chooser,
410 GFile *file,
411 GError **error)
412{
413 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
414 g_return_val_if_fail (G_IS_FILE (file), FALSE);
415 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
416
417 return GTK_FILE_CHOOSER_GET_IFACE (chooser)->select_file (chooser, file, error);
418}
419
420void
421gtk_file_chooser_unselect_file (GtkFileChooser *chooser,
422 GFile *file)
423{
424 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
425 g_return_if_fail (G_IS_FILE (file));
426
427 GTK_FILE_CHOOSER_GET_IFACE (chooser)->unselect_file (chooser, file);
428}
429
430/**
431 * gtk_file_chooser_get_files:
432 * @chooser: a `GtkFileChooser`
433 *
434 * Lists all the selected files and subfolders in the current folder
435 * of @chooser as `GFile`.
436 *
437 * Returns: (transfer full): a list model containing a `GFile` for each
438 * selected file and subfolder in the current folder. Free the returned
439 * list with g_object_unref().
440 */
441GListModel *
442gtk_file_chooser_get_files (GtkFileChooser *chooser)
443{
444 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
445
446 return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_files (chooser);
447}
448
449/**
450 * gtk_file_chooser_set_file:
451 * @chooser: a `GtkFileChooser`
452 * @file: the `GFile` to set as current
453 * @error: (nullable): location to store the error
454 *
455 * Sets @file as the current filename for the file chooser.
456 *
457 * This includes changing to the file’s parent folder and actually selecting
458 * the file in list. If the @chooser is in %GTK_FILE_CHOOSER_ACTION_SAVE mode,
459 * the file’s base name will also appear in the dialog’s file name entry.
460 *
461 * If the file name isn’t in the current folder of @chooser, then the current
462 * folder of @chooser will be changed to the folder containing @file.
463 *
464 * Note that the file must exist, or nothing will be done except
465 * for the directory change.
466 *
467 * If you are implementing a save dialog, you should use this function if
468 * you already have a file name to which the user may save; for example,
469 * when the user opens an existing file and then does “Save As…”. If you
470 * don’t have a file name already — for example, if the user just created
471 * a new file and is saving it for the first time, do not call this function.
472 *
473 * Instead, use something similar to this:
474 *
475 * ```c
476 * static void
477 * prepare_file_chooser (GtkFileChooser *chooser,
478 * GFile *existing_file)
479 * {
480 * gboolean document_is_new = (existing_file == NULL);
481 *
482 * if (document_is_new)
483 * {
484 * GFile *default_file_for_saving = g_file_new_for_path ("./out.txt");
485 * // the user just created a new document
486 * gtk_file_chooser_set_current_folder (chooser, default_file_for_saving, NULL);
487 * gtk_file_chooser_set_current_name (chooser, "Untitled document");
488 * g_object_unref (default_file_for_saving);
489 * }
490 * else
491 * {
492 * // the user edited an existing document
493 * gtk_file_chooser_set_file (chooser, existing_file, NULL);
494 * }
495 * }
496 * ```
497 *
498 * Returns: Not useful
499 */
500gboolean
501gtk_file_chooser_set_file (GtkFileChooser *chooser,
502 GFile *file,
503 GError **error)
504{
505 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
506 g_return_val_if_fail (G_IS_FILE (file), FALSE);
507 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
508
509 gtk_file_chooser_unselect_all (chooser);
510 return gtk_file_chooser_select_file (chooser, file, error);
511}
512
513/**
514 * gtk_file_chooser_get_file:
515 * @chooser: a `GtkFileChooser`
516 *
517 * Gets the `GFile` for the currently selected file in
518 * the file selector.
519 *
520 * If multiple files are selected, one of the files will be
521 * returned at random.
522 *
523 * If the file chooser is in folder mode, this function returns
524 * the selected folder.
525 *
526 * Returns: (transfer full) (nullable): a selected `GFile`. You own the
527 * returned file; use g_object_unref() to release it.
528 */
529GFile *
530gtk_file_chooser_get_file (GtkFileChooser *chooser)
531{
532 GListModel *list;
533 GFile *result = NULL;
534
535 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
536
537 list = gtk_file_chooser_get_files (chooser);
538 if (g_list_model_get_n_items (list) > 0)
539 result = g_list_model_get_item (list, position: 0);
540 g_object_unref (object: list);
541
542 return result;
543}
544
545/**
546 * gtk_file_chooser_add_shortcut_folder:
547 * @chooser: a `GtkFileChooser`
548 * @folder: a `GFile` for the folder to add
549 * @error: location to store error
550 *
551 * Adds a folder to be displayed with the shortcut folders
552 * in a file chooser.
553 *
554 * Returns: %TRUE if the folder could be added successfully,
555 * %FALSE otherwise.
556 */
557gboolean
558gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser,
559 GFile *folder,
560 GError **error)
561{
562 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
563 g_return_val_if_fail (G_IS_FILE (folder), FALSE);
564
565 return GTK_FILE_CHOOSER_GET_IFACE (chooser)->add_shortcut_folder (chooser, folder, error);
566}
567
568/**
569 * gtk_file_chooser_remove_shortcut_folder:
570 * @chooser: a `GtkFileChooser`
571 * @folder: a `GFile` for the folder to remove
572 * @error: location to store error
573 *
574 * Removes a folder from the shortcut folders in a file chooser.
575 *
576 * Returns: %TRUE if the folder could be removed successfully,
577 * %FALSE otherwise.
578 */
579gboolean
580gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser,
581 GFile *folder,
582 GError **error)
583{
584 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
585 g_return_val_if_fail (G_IS_FILE (folder), FALSE);
586
587 return GTK_FILE_CHOOSER_GET_IFACE (chooser)->remove_shortcut_folder (chooser, folder, error);
588}
589
590/**
591 * gtk_file_chooser_add_filter:
592 * @chooser: a `GtkFileChooser`
593 * @filter: (transfer none): a `GtkFileFilter`
594 *
595 * Adds @filter to the list of filters that the user can select between.
596 *
597 * When a filter is selected, only files that are passed by that
598 * filter are displayed.
599 *
600 * Note that the @chooser takes ownership of the filter if it is floating,
601 * so you have to ref and sink it if you want to keep a reference.
602 */
603void
604gtk_file_chooser_add_filter (GtkFileChooser *chooser,
605 GtkFileFilter *filter)
606{
607 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
608
609 GTK_FILE_CHOOSER_GET_IFACE (chooser)->add_filter (chooser, filter);
610}
611
612/**
613 * gtk_file_chooser_remove_filter:
614 * @chooser: a `GtkFileChooser`
615 * @filter: a `GtkFileFilter`
616 *
617 * Removes @filter from the list of filters that the user can select between.
618 */
619void
620gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
621 GtkFileFilter *filter)
622{
623 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
624
625 GTK_FILE_CHOOSER_GET_IFACE (chooser)->remove_filter (chooser, filter);
626}
627
628/**
629 * gtk_file_chooser_get_filters: (attributes org.gtk.Method.get_property=filters)
630 * @chooser: a `GtkFileChooser`
631 *
632 * Gets the current set of user-selectable filters, as a list model.
633 *
634 * See [method@Gtk.FileChooser.add_filter] and
635 * [method@Gtk.FileChooser.remove_filter] for changing individual filters.
636 *
637 * You should not modify the returned list model. Future changes to
638 * @chooser may or may not affect the returned model.
639 *
640 * Returns: (transfer full): a `GListModel` containing the current set
641 * of user-selectable filters.
642 */
643GListModel *
644gtk_file_chooser_get_filters (GtkFileChooser *chooser)
645{
646 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
647
648 return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_filters (chooser);
649}
650
651/**
652 * gtk_file_chooser_set_filter: (attributes org.gtk.Method.set_property=filter)
653 * @chooser: a `GtkFileChooser`
654 * @filter: a `GtkFileFilter`
655 *
656 * Sets the current filter.
657 *
658 * Only the files that pass the filter will be displayed.
659 * If the user-selectable list of filters is non-empty, then
660 * the filter should be one of the filters in that list.
661 *
662 * Setting the current filter when the list of filters is
663 * empty is useful if you want to restrict the displayed
664 * set of files without letting the user change it.
665 */
666void
667gtk_file_chooser_set_filter (GtkFileChooser *chooser,
668 GtkFileFilter *filter)
669{
670 g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
671 g_return_if_fail (GTK_IS_FILE_FILTER (filter));
672
673 g_object_set (object: chooser, first_property_name: "filter", filter, NULL);
674}
675
676/**
677 * gtk_file_chooser_get_filter: (attributes org.gtk.Method.get_property=filter)
678 * @chooser: a `GtkFileChooser`
679 *
680 * Gets the current filter.
681 *
682 * Returns: (nullable) (transfer none): the current filter
683 */
684GtkFileFilter *
685gtk_file_chooser_get_filter (GtkFileChooser *chooser)
686{
687 GtkFileFilter *filter;
688
689 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
690
691 g_object_get (object: chooser, first_property_name: "filter", &filter, NULL);
692 /* Horrid hack; g_object_get() refs returned objects but
693 * that contradicts the memory management conventions
694 * for accessors.
695 */
696 if (filter)
697 g_object_unref (object: filter);
698
699 return filter;
700}
701
702/**
703 * gtk_file_chooser_get_shortcut_folders: (attributes org.gtk.Method.get_property=shortcut-folders)
704 * @chooser: a `GtkFileChooser`
705 *
706 * Queries the list of shortcut folders in the file chooser.
707 *
708 * You should not modify the returned list model. Future changes to
709 * @chooser may or may not affect the returned model.
710 *
711 * Returns: (transfer full): A list model of `GFile`s
712 */
713GListModel *
714gtk_file_chooser_get_shortcut_folders (GtkFileChooser *chooser)
715{
716 g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
717
718 return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_shortcut_folders (chooser);
719}
720
721/**
722 * gtk_file_chooser_add_choice:
723 * @chooser: a `GtkFileChooser`
724 * @id: id for the added choice
725 * @label: user-visible label for the added choice
726 * @options: (nullable) (array zero-terminated=1): ids for the options of the choice, or %NULL for a boolean choice
727 * @option_labels: (nullable) (array zero-terminated=1): user-visible labels for the options, must be the same length as @options
728 *
729 * Adds a 'choice' to the file chooser.
730 *
731 * This is typically implemented as a combobox or, for boolean choices,
732 * as a checkbutton. You can select a value using
733 * [method@Gtk.FileChooser.set_choice] before the dialog is shown,
734 * and you can obtain the user-selected value in the
735 * [signal@Gtk.Dialog::response] signal handler using
736 * [method@Gtk.FileChooser.get_choice].
737 */
738void
739gtk_file_chooser_add_choice (GtkFileChooser *chooser,
740 const char *id,
741 const char *label,
742 const char **options,
743 const char **option_labels)
744{
745 GtkFileChooserIface *iface = GTK_FILE_CHOOSER_GET_IFACE (chooser);
746
747 if (iface->add_choice)
748 iface->add_choice (chooser, id, label, options, option_labels);
749}
750
751/**
752 * gtk_file_chooser_remove_choice:
753 * @chooser: a `GtkFileChooser`
754 * @id: the ID of the choice to remove
755 *
756 * Removes a 'choice' that has been added with gtk_file_chooser_add_choice().
757 */
758void
759gtk_file_chooser_remove_choice (GtkFileChooser *chooser,
760 const char *id)
761{
762 GtkFileChooserIface *iface = GTK_FILE_CHOOSER_GET_IFACE (chooser);
763
764 if (iface->remove_choice)
765 iface->remove_choice (chooser, id);
766}
767
768/**
769 * gtk_file_chooser_set_choice:
770 * @chooser: a `GtkFileChooser`
771 * @id: the ID of the choice to set
772 * @option: the ID of the option to select
773 *
774 * Selects an option in a 'choice' that has been added with
775 * gtk_file_chooser_add_choice().
776 *
777 * For a boolean choice, the possible options are "true" and "false".
778 */
779void
780gtk_file_chooser_set_choice (GtkFileChooser *chooser,
781 const char *id,
782 const char *option)
783{
784 GtkFileChooserIface *iface = GTK_FILE_CHOOSER_GET_IFACE (chooser);
785
786 if (iface->set_choice)
787 iface->set_choice (chooser, id, option);
788}
789
790/**
791 * gtk_file_chooser_get_choice:
792 * @chooser: a `GtkFileChooser`
793 * @id: the ID of the choice to get
794 *
795 * Gets the currently selected option in the 'choice' with the given ID.
796 *
797 * Returns: (nullable): the ID of the currently selected option
798 */
799const char *
800gtk_file_chooser_get_choice (GtkFileChooser *chooser,
801 const char *id)
802{
803 GtkFileChooserIface *iface = GTK_FILE_CHOOSER_GET_IFACE (chooser);
804
805 if (iface->get_choice)
806 return iface->get_choice (chooser, id);
807
808 return NULL;
809}
810

source code of gtk/gtk/gtkfilechooser.c