mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-09 10:20:07 +00:00
filedialog: add gtk_file_dialog_add_choice() and related
This brings back the add_choice() API that was deprecated as part of the move to GtkFileDialog move without a replacement API. This is needed for applications like Text Editor and Builder to migrate to using GtkFileDialog.
This commit is contained in:
parent
b1995d0d77
commit
dd3447a41e
@ -57,8 +57,18 @@ struct _GtkFileDialog
|
|||||||
GFile *initial_folder;
|
GFile *initial_folder;
|
||||||
char *initial_name;
|
char *initial_name;
|
||||||
GFile *initial_file;
|
GFile *initial_file;
|
||||||
|
GPtrArray *choices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *id;
|
||||||
|
char *label;
|
||||||
|
char **options;
|
||||||
|
char **option_labels;
|
||||||
|
char *choice;
|
||||||
|
} Choice;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
@ -78,10 +88,24 @@ static GParamSpec *properties[NUM_PROPERTIES];
|
|||||||
|
|
||||||
G_DEFINE_TYPE (GtkFileDialog, gtk_file_dialog, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (GtkFileDialog, gtk_file_dialog, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
choice_free (gpointer data)
|
||||||
|
{
|
||||||
|
Choice *choice = data;
|
||||||
|
|
||||||
|
g_clear_pointer (&choice->id, g_free);
|
||||||
|
g_clear_pointer (&choice->label, g_free);
|
||||||
|
g_clear_pointer (&choice->options, g_strfreev);
|
||||||
|
g_clear_pointer (&choice->option_labels, g_strfreev);
|
||||||
|
g_clear_pointer (&choice->choice, g_free);
|
||||||
|
g_free (choice);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_file_dialog_init (GtkFileDialog *self)
|
gtk_file_dialog_init (GtkFileDialog *self)
|
||||||
{
|
{
|
||||||
self->modal = TRUE;
|
self->modal = TRUE;
|
||||||
|
self->choices = g_ptr_array_new_with_free_func (choice_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -95,6 +119,7 @@ gtk_file_dialog_finalize (GObject *object)
|
|||||||
g_clear_object (&self->default_filter);
|
g_clear_object (&self->default_filter);
|
||||||
g_clear_object (&self->initial_folder);
|
g_clear_object (&self->initial_folder);
|
||||||
g_free (self->initial_name);
|
g_free (self->initial_name);
|
||||||
|
g_clear_pointer (&self->choices, g_ptr_array_unref);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gtk_file_dialog_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gtk_file_dialog_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
@ -738,6 +763,184 @@ invalid_file:
|
|||||||
g_object_thaw_notify (G_OBJECT (self));
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Choice *
|
||||||
|
find_choice (GtkFileDialog *self,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
for (guint i = 0; i < self->choices->len; i++)
|
||||||
|
{
|
||||||
|
Choice *choice = g_ptr_array_index (self->choices, i);
|
||||||
|
|
||||||
|
if (strcmp (id, choice->id) == 0)
|
||||||
|
return choice;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_file_dialog_add_choice:
|
||||||
|
* @self: a `GtkFileDialog`
|
||||||
|
* @id: id for the added choice
|
||||||
|
* @label: user-visible label for the added choice
|
||||||
|
* @options: (nullable) (array zero-terminated=1): ids for the options of the choice, or %NULL for a boolean choice
|
||||||
|
* @option_labels: (nullable) (array zero-terminated=1): user-visible labels for the options, must be the same length as @options
|
||||||
|
*
|
||||||
|
* Adds a 'choice' to the file dialog.
|
||||||
|
*
|
||||||
|
* This is typically implemented as a combobox or, for boolean choices,
|
||||||
|
* as a checkbutton. You can select a value using
|
||||||
|
* [method@Gtk.FileDialog.set_choice] before the dialog is shown,
|
||||||
|
* and you can obtain the user-selected value using
|
||||||
|
* [method@Gtk.FileDialog.get_choice] from the appropriate async
|
||||||
|
* finish function.
|
||||||
|
*
|
||||||
|
* This function should be called before opening the dialog.
|
||||||
|
*
|
||||||
|
* Since: 4.16
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_file_dialog_add_choice (GtkFileDialog *self,
|
||||||
|
const char *id,
|
||||||
|
const char *label,
|
||||||
|
const char * const *options,
|
||||||
|
const char * const *option_labels)
|
||||||
|
{
|
||||||
|
Choice *choice;
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||||
|
g_return_if_fail (id != NULL);
|
||||||
|
g_return_if_fail (label != NULL);
|
||||||
|
g_return_if_fail ((options == NULL && option_labels == NULL) ||
|
||||||
|
(options != NULL && option_labels != NULL));
|
||||||
|
g_return_if_fail ((options == NULL && option_labels == NULL) ||
|
||||||
|
(g_strv_length ((char **)options) == g_strv_length ((char **)option_labels)));
|
||||||
|
|
||||||
|
choice = find_choice (self, id);
|
||||||
|
|
||||||
|
if (choice != NULL)
|
||||||
|
{
|
||||||
|
g_warning ("Choice with id %s already added to %s %p", id, G_OBJECT_TYPE_NAME (self), self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
choice = g_new0 (Choice, 1);
|
||||||
|
choice->id = g_strdup (id);
|
||||||
|
choice->label = g_strdup (label);
|
||||||
|
choice->options = g_strdupv ((char **)options);
|
||||||
|
choice->option_labels = g_strdupv ((char **)option_labels);
|
||||||
|
choice->choice = NULL;
|
||||||
|
|
||||||
|
g_ptr_array_add (self->choices, choice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_file_dialog_remove_choice:
|
||||||
|
* @self: a `GtkFileChooser`
|
||||||
|
* @id: the ID of the choice to remove
|
||||||
|
*
|
||||||
|
* Removes a 'choice' that has been added with gtk_file_dialog_add_choice().
|
||||||
|
*
|
||||||
|
* Since: 4.16
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_file_dialog_remove_choice (GtkFileDialog *self,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||||
|
g_return_if_fail (id != NULL);
|
||||||
|
|
||||||
|
for (guint i = 0; i < self->choices->len; i++)
|
||||||
|
{
|
||||||
|
Choice *choice = g_ptr_array_index (self->choices, i);
|
||||||
|
|
||||||
|
if (strcmp (id, choice->id) == 0)
|
||||||
|
{
|
||||||
|
g_ptr_array_remove_index (self->choices, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_warning ("No choice with id %s found in %s %p", id, G_OBJECT_TYPE_NAME (self), self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_file_dialog_get_choice:
|
||||||
|
* @self: a `GtkFileDialog`
|
||||||
|
* @id: the ID of the choice to get
|
||||||
|
*
|
||||||
|
* Gets the currently selected option in the 'choice' with the given ID.
|
||||||
|
*
|
||||||
|
* This function should be used within the `finish` function to obtain
|
||||||
|
* the options that the user selected in the dialog.
|
||||||
|
*
|
||||||
|
* Returns: (nullable): the ID of the currently selected option
|
||||||
|
*
|
||||||
|
* Since: 4.16
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
gtk_file_dialog_get_choice (GtkFileDialog *self,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
Choice *choice;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GTK_IS_FILE_DIALOG (self), NULL);
|
||||||
|
|
||||||
|
choice = find_choice (self, id);
|
||||||
|
|
||||||
|
if (choice == NULL)
|
||||||
|
{
|
||||||
|
g_warning ("No choice with id %s found in %s %p", id, G_OBJECT_TYPE_NAME (self), self);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return choice->choice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtk_file_dialog_set_choice:
|
||||||
|
* @self: a `GtkFileDialog`
|
||||||
|
* @id: the ID of the choice to set
|
||||||
|
* @option: the ID of the option to select
|
||||||
|
*
|
||||||
|
* Selects an option in a 'choice' that has been added with
|
||||||
|
* gtk_file_dialog_add_choice().
|
||||||
|
*
|
||||||
|
* For a boolean choice, the possible options are "true" and "false".
|
||||||
|
*
|
||||||
|
* Since: 4.16
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_file_dialog_set_choice (GtkFileDialog *self,
|
||||||
|
const char *id,
|
||||||
|
const char *option)
|
||||||
|
{
|
||||||
|
Choice *choice;
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||||
|
g_return_if_fail (id != NULL);
|
||||||
|
|
||||||
|
choice = find_choice (self, id);
|
||||||
|
|
||||||
|
if (choice == NULL)
|
||||||
|
{
|
||||||
|
g_warning ("No choice with id %s found in %s %p", id, G_OBJECT_TYPE_NAME (self), self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option != NULL)
|
||||||
|
{
|
||||||
|
if (choice->options == NULL ||
|
||||||
|
!g_strv_contains ((const char * const *)choice->options, option))
|
||||||
|
{
|
||||||
|
g_warning ("No choice %s registered for id %s found in %s %p", option, id, G_OBJECT_TYPE_NAME (self), self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_set_str (&choice->choice, option);
|
||||||
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
/* {{{ Async implementation */
|
/* {{{ Async implementation */
|
||||||
|
|
||||||
@ -756,7 +959,9 @@ response_cb (GTask *task,
|
|||||||
int response)
|
int response)
|
||||||
{
|
{
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
|
GtkFileDialog *dialog;
|
||||||
|
|
||||||
|
dialog = g_task_get_source_object (task);
|
||||||
cancellable = g_task_get_cancellable (task);
|
cancellable = g_task_get_cancellable (task);
|
||||||
|
|
||||||
if (cancellable)
|
if (cancellable)
|
||||||
@ -770,6 +975,15 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
|||||||
|
|
||||||
chooser = GTK_FILE_CHOOSER (g_task_get_task_data (task));
|
chooser = GTK_FILE_CHOOSER (g_task_get_task_data (task));
|
||||||
files = gtk_file_chooser_get_files (chooser);
|
files = gtk_file_chooser_get_files (chooser);
|
||||||
|
|
||||||
|
for (guint i = 0; i < dialog->choices->len; i++)
|
||||||
|
{
|
||||||
|
Choice *choice = g_ptr_array_index (dialog->choices, i);
|
||||||
|
const char *value = gtk_file_chooser_get_choice (chooser, choice->id);
|
||||||
|
|
||||||
|
g_set_str (&choice->choice, value);
|
||||||
|
}
|
||||||
|
|
||||||
g_task_return_pointer (task, files, g_object_unref);
|
g_task_return_pointer (task, files, g_object_unref);
|
||||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||||
}
|
}
|
||||||
@ -870,6 +1084,17 @@ create_file_chooser (GtkFileDialog *self,
|
|||||||
if (self->initial_name && action == GTK_FILE_CHOOSER_ACTION_SAVE)
|
if (self->initial_name && action == GTK_FILE_CHOOSER_ACTION_SAVE)
|
||||||
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (chooser), self->initial_name);
|
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (chooser), self->initial_name);
|
||||||
|
|
||||||
|
for (guint i = 0; i < self->choices->len; i++)
|
||||||
|
{
|
||||||
|
const Choice *choice = g_ptr_array_index (self->choices, i);
|
||||||
|
|
||||||
|
gtk_file_chooser_add_choice (GTK_FILE_CHOOSER (chooser),
|
||||||
|
choice->id,
|
||||||
|
choice->label,
|
||||||
|
(const char **)choice->options,
|
||||||
|
(const char **)choice->option_labels);
|
||||||
|
}
|
||||||
|
|
||||||
return chooser;
|
return chooser;
|
||||||
}
|
}
|
||||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||||
|
@ -155,6 +155,21 @@ GListModel * gtk_file_dialog_select_multiple_folders_finish
|
|||||||
(GtkFileDialog *self,
|
(GtkFileDialog *self,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
GDK_AVAILABLE_IN_4_16
|
||||||
|
void gtk_file_dialog_add_choice (GtkFileDialog *self,
|
||||||
|
const char *id,
|
||||||
|
const char *label,
|
||||||
|
const char * const *options,
|
||||||
|
const char * const *option_labels);
|
||||||
|
GDK_AVAILABLE_IN_4_16
|
||||||
|
void gtk_file_dialog_remove_choice (GtkFileDialog *self,
|
||||||
|
const char *id);
|
||||||
|
GDK_AVAILABLE_IN_4_16
|
||||||
|
const char *gtk_file_dialog_get_choice (GtkFileDialog *self,
|
||||||
|
const char *id);
|
||||||
|
GDK_AVAILABLE_IN_4_16
|
||||||
|
void gtk_file_dialog_set_choice (GtkFileDialog *self,
|
||||||
|
const char *id,
|
||||||
|
const char *option);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
Loading…
Reference in New Issue
Block a user