X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkappchooserbutton.c;h=235464c58e80cd1d1cffb2033bf44c4f02c91f56;hb=79695ee64d41c9aadfe2c6f18dc7dd1e3fd44852;hp=fcaf8750bcb55dcc8b3ef6864d5850bf06ad7cab;hpb=06f501fa07a0d450d53aa17b2af12b9b72378587;p=~andy%2Fgtk diff --git a/gtk/gtkappchooserbutton.c b/gtk/gtkappchooserbutton.c index fcaf8750b..235464c58 100644 --- a/gtk/gtkappchooserbutton.c +++ b/gtk/gtkappchooserbutton.c @@ -14,13 +14,39 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . * * Authors: Cosimo Cecchi */ +/** + * SECTION:gtkappchooserbutton + * @Title: GtkAppChooserButton + * @Short_description: A button to launch an application chooser dialog + * + * The #GtkAppChooserButton is a widget that lets the user select + * an application. It implements the #GtkAppChooser interface. + * + * Initially, a #GtkAppChooserButton selects the first application + * in its list, which will either be the most-recently used application + * or, if #GtkAppChooserButton:show-default-item is %TRUE, the + * default application. + * + * The list of applications shown in a #GtkAppChooserButton includes + * the recommended applications for the given content type. When + * #GtkAppChooserButton:show-default-item is set, the default application + * is also included. To let the user chooser other applications, + * you can set the #GtkAppChooserButton:show-dialog-item property, + * which allows to open a full #GtkAppChooserDialog. + * + * It is possible to add custom items to the list, using + * gtk_app_chooser_button_append_custom_item(). These items cause + * the #GtkAppChooserButton::custom-item-activated signal to be + * emitted when they are selected. + * + * To track changes in the selected application, use the + * #GtkComboBox::changed signal. + */ #include "config.h" #include "gtkappchooserbutton.h" @@ -34,65 +60,46 @@ #include "gtkcombobox.h" #include "gtkdialog.h" #include "gtkintl.h" +#include "gtkmarshalers.h" enum { PROP_CONTENT_TYPE = 1, PROP_SHOW_DIALOG_ITEM, + PROP_SHOW_DEFAULT_ITEM, + PROP_HEADING +}; + +enum { + SIGNAL_CUSTOM_ITEM_ACTIVATED, + NUM_SIGNALS }; enum { COLUMN_APP_INFO, COLUMN_NAME, + COLUMN_LABEL, COLUMN_ICON, COLUMN_CUSTOM, COLUMN_SEPARATOR, - COLUMN_CALLBACK, NUM_COLUMNS, }; -typedef struct { - GtkAppChooserButtonItemFunc func; - gpointer user_data; -} CustomAppComboData; - -static gpointer -custom_app_data_copy (gpointer boxed) -{ - CustomAppComboData *retval, *original; - - original = boxed; - - retval = g_slice_new0 (CustomAppComboData); - retval->func = original->func; - retval->user_data = original->user_data; - - return retval; -} - -static void -custom_app_data_free (gpointer boxed) -{ - g_slice_free (CustomAppComboData, boxed); -} - -#define CUSTOM_COMBO_DATA_TYPE custom_app_combo_data_get_type() -G_DEFINE_BOXED_TYPE (CustomAppComboData, custom_app_combo_data, - custom_app_data_copy, - custom_app_data_free); +#define CUSTOM_ITEM_OTHER_APP "gtk-internal-item-other-app" static void app_chooser_iface_init (GtkAppChooserIface *iface); static void real_insert_custom_item (GtkAppChooserButton *self, - const gchar *label, - GIcon *icon, - GtkAppChooserButtonItemFunc func, - gpointer user_data, - gboolean custom, - GtkTreeIter *iter); + const gchar *name, + const gchar *label, + GIcon *icon, + gboolean custom, + GtkTreeIter *iter); static void real_insert_separator (GtkAppChooserButton *self, - gboolean custom, - GtkTreeIter *iter); + gboolean custom, + GtkTreeIter *iter); + +static guint signals[NUM_SIGNALS] = { 0, }; G_DEFINE_TYPE_WITH_CODE (GtkAppChooserButton, gtk_app_chooser_button, GTK_TYPE_COMBO_BOX, G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER, @@ -102,7 +109,12 @@ struct _GtkAppChooserButtonPrivate { GtkListStore *store; gchar *content_type; + gchar *heading; + gint last_active; gboolean show_dialog_item; + gboolean show_default_item; + + GHashTable *custom_item_names; }; static gboolean @@ -154,32 +166,36 @@ select_app_data_free (SelectAppData *data) static gboolean select_application_func_cb (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data) + GtkTreePath *path, + GtkTreeIter *iter, + gpointer user_data) { SelectAppData *data = user_data; GAppInfo *app_to_match = data->info, *app = NULL; gboolean custom; + gboolean result; gtk_tree_model_get (model, iter, - COLUMN_APP_INFO, &app, - COLUMN_CUSTOM, &custom, - -1); + COLUMN_APP_INFO, &app, + COLUMN_CUSTOM, &custom, + -1); - /* cutsom items are always after GAppInfos, so iterating further here + /* custom items are always after GAppInfos, so iterating further here * is just useless. */ if (custom) - return TRUE; - - if (g_app_info_equal (app, app_to_match)) + result = TRUE; + else if (g_app_info_equal (app, app_to_match)) { gtk_combo_box_set_active_iter (GTK_COMBO_BOX (data->self), iter); - return TRUE; + result = TRUE; } + else + result = FALSE; - return FALSE; + g_object_unref (app); + + return result; } static void @@ -193,15 +209,15 @@ gtk_app_chooser_button_select_application (GtkAppChooserButton *self, data->info = g_object_ref (info); gtk_tree_model_foreach (GTK_TREE_MODEL (self->priv->store), - select_application_func_cb, data); + select_application_func_cb, data); select_app_data_free (data); } static void other_application_dialog_response_cb (GtkDialog *dialog, - gint response_id, - gpointer user_data) + gint response_id, + gpointer user_data) { GtkAppChooserButton *self = user_data; GAppInfo *info; @@ -209,15 +225,17 @@ other_application_dialog_response_cb (GtkDialog *dialog, if (response_id != GTK_RESPONSE_OK) { /* reset the active item, otherwise we are stuck on - * 'Other application...' + * 'Other application…' */ - gtk_combo_box_set_active (GTK_COMBO_BOX (self), 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (self), self->priv->last_active); gtk_widget_destroy (GTK_WIDGET (dialog)); return; } info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (dialog)); + gtk_widget_destroy (GTK_WIDGET (dialog)); + /* refresh the combobox to get the new application */ gtk_app_chooser_refresh (GTK_APP_CHOOSER (self)); gtk_app_chooser_button_select_application (self, info); @@ -226,47 +244,73 @@ other_application_dialog_response_cb (GtkDialog *dialog, } static void -other_application_item_activated_cb (GtkAppChooserButton *self, - gpointer _user_data) +other_application_item_activated_cb (GtkAppChooserButton *self) { GtkWidget *dialog, *widget; GtkWindow *toplevel; toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))); dialog = gtk_app_chooser_dialog_new_for_content_type (toplevel, GTK_DIALOG_DESTROY_WITH_PARENT, - self->priv->content_type); + self->priv->content_type); + + gtk_window_set_modal (GTK_WINDOW (dialog), gtk_window_get_modal (toplevel)); + gtk_app_chooser_dialog_set_heading (GTK_APP_CHOOSER_DIALOG (dialog), + self->priv->heading); + widget = gtk_app_chooser_dialog_get_widget (GTK_APP_CHOOSER_DIALOG (dialog)); g_object_set (widget, - "show-fallback", TRUE, - "show-other", TRUE, - NULL); + "show-fallback", TRUE, + "show-other", TRUE, + NULL); gtk_widget_show (dialog); g_signal_connect (dialog, "response", - G_CALLBACK (other_application_dialog_response_cb), self); + G_CALLBACK (other_application_dialog_response_cb), self); } static void gtk_app_chooser_button_ensure_dialog_item (GtkAppChooserButton *self, GtkTreeIter *prev_iter) { - GIcon *icon; - GtkTreeIter iter; + GtkTreeIter iter, iter2; - if (!self->priv->show_dialog_item) + if (!self->priv->show_dialog_item || !self->priv->content_type) return; - icon = g_themed_icon_new ("application-x-executable"); + if (prev_iter == NULL) + gtk_list_store_append (self->priv->store, &iter); + else + gtk_list_store_insert_after (self->priv->store, &iter, prev_iter); - gtk_list_store_insert_after (self->priv->store, &iter, prev_iter); real_insert_separator (self, FALSE, &iter); - *prev_iter = iter; + iter2 = iter; - gtk_list_store_insert_after (self->priv->store, &iter, prev_iter); - real_insert_custom_item (self, - _("Other application..."), icon, - other_application_item_activated_cb, - NULL, FALSE, &iter); + gtk_list_store_insert_after (self->priv->store, &iter, &iter2); + real_insert_custom_item (self, CUSTOM_ITEM_OTHER_APP, + _("Other application…"), NULL, + FALSE, &iter); +} + +static void +insert_one_application (GtkAppChooserButton *self, + GAppInfo *app, + GtkTreeIter *iter) +{ + GIcon *icon; + + icon = g_app_info_get_icon (app); + + if (icon == NULL) + icon = g_themed_icon_new ("application-x-executable"); + else + g_object_ref (icon); + + gtk_list_store_set (self->priv->store, iter, + COLUMN_APP_INFO, app, + COLUMN_LABEL, g_app_info_get_name (app), + COLUMN_ICON, icon, + COLUMN_CUSTOM, FALSE, + -1); g_object_unref (icon); } @@ -275,47 +319,60 @@ static void gtk_app_chooser_button_populate (GtkAppChooserButton *self) { GList *recommended_apps = NULL, *l; - GAppInfo *app; + GAppInfo *app, *default_app = NULL; GtkTreeIter iter, iter2; - GIcon *icon; - gboolean first; + gboolean cycled_recommended; + +#ifndef G_OS_WIN32 + if (self->priv->content_type) + recommended_apps = g_app_info_get_recommended_for_type (self->priv->content_type); +#endif + cycled_recommended = FALSE; - recommended_apps = g_app_info_get_recommended_for_type (self->priv->content_type); - first = TRUE; + if (self->priv->show_default_item) + { + default_app = g_app_info_get_default_for_type (self->priv->content_type, FALSE); + + if (default_app != NULL) + { + get_first_iter (self->priv->store, &iter); + cycled_recommended = TRUE; + + insert_one_application (self, default_app, &iter); + + g_object_unref (default_app); + } + } for (l = recommended_apps; l != NULL; l = l->next) { app = l->data; - icon = g_app_info_get_icon (app); - - if (icon == NULL) - icon = g_themed_icon_new ("application-x-executable"); - else - g_object_ref (icon); + if (default_app != NULL && g_app_info_equal (app, default_app)) + continue; - if (first) + if (cycled_recommended) { - get_first_iter (self->priv->store, &iter); - first = FALSE; + gtk_list_store_insert_after (self->priv->store, &iter2, &iter); + iter = iter2; } else { - gtk_list_store_insert_after (self->priv->store, &iter2, &iter); - iter = iter2; + get_first_iter (self->priv->store, &iter); + cycled_recommended = TRUE; } - gtk_list_store_set (self->priv->store, &iter, - COLUMN_APP_INFO, app, - COLUMN_NAME, g_app_info_get_display_name (app), - COLUMN_ICON, icon, - COLUMN_CUSTOM, FALSE, - -1); - - g_object_unref (icon); + insert_one_application (self, app, &iter); } - gtk_app_chooser_button_ensure_dialog_item (self, &iter); + if (recommended_apps != NULL) + g_list_free_full (recommended_apps, g_object_unref); + + if (!cycled_recommended) + gtk_app_chooser_button_ensure_dialog_item (self, NULL); + else + gtk_app_chooser_button_ensure_dialog_item (self, &iter); + gtk_combo_box_set_active (GTK_COMBO_BOX (self), 0); } @@ -323,32 +380,33 @@ static void gtk_app_chooser_button_build_ui (GtkAppChooserButton *self) { GtkCellRenderer *cell; - - self->priv->store = gtk_list_store_new (NUM_COLUMNS, - G_TYPE_APP_INFO, - G_TYPE_STRING, - G_TYPE_ICON, - G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, - CUSTOM_COMBO_DATA_TYPE); + GtkCellArea *area; gtk_combo_box_set_model (GTK_COMBO_BOX (self), GTK_TREE_MODEL (self->priv->store)); + area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (self)); + gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (self), row_separator_func, NULL, NULL); cell = gtk_cell_renderer_pixbuf_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, FALSE); + gtk_cell_area_add_with_properties (area, cell, + "align", FALSE, + "expand", FALSE, + "fixed-size", FALSE, + NULL); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), cell, "gicon", COLUMN_ICON, NULL); cell = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, TRUE); + gtk_cell_area_add_with_properties (area, cell, + "align", FALSE, + "expand", TRUE, + NULL); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), cell, - "text", COLUMN_NAME, - "xpad", 6, + "text", COLUMN_LABEL, NULL); gtk_app_chooser_button_populate (self); @@ -382,17 +440,36 @@ gtk_app_chooser_button_changed (GtkComboBox *object) { GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (object); GtkTreeIter iter; - CustomAppComboData *custom_data = NULL; + gchar *name = NULL; + gboolean custom; + GQuark name_quark; if (!gtk_combo_box_get_active_iter (object, &iter)) return; gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter, - COLUMN_CALLBACK, &custom_data, + COLUMN_NAME, &name, + COLUMN_CUSTOM, &custom, -1); - if (custom_data != NULL && custom_data->func != NULL) - custom_data->func (self, custom_data->user_data); + if (name != NULL) + { + if (custom) + { + name_quark = g_quark_from_string (name); + g_signal_emit (self, signals[SIGNAL_CUSTOM_ITEM_ACTIVATED], name_quark, name); + self->priv->last_active = gtk_combo_box_get_active (object); + } + else + { + /* trigger the dialog internally */ + other_application_item_activated_cb (self); + } + + g_free (name); + } + else + self->priv->last_active = gtk_combo_box_get_active (object); } static void @@ -429,8 +506,6 @@ gtk_app_chooser_button_constructed (GObject *obj) if (G_OBJECT_CLASS (gtk_app_chooser_button_parent_class)->constructed != NULL) G_OBJECT_CLASS (gtk_app_chooser_button_parent_class)->constructed (obj); - g_assert (self->priv->content_type != NULL); - gtk_app_chooser_button_build_ui (self); } @@ -450,6 +525,12 @@ gtk_app_chooser_button_set_property (GObject *obj, case PROP_SHOW_DIALOG_ITEM: gtk_app_chooser_button_set_show_dialog_item (self, g_value_get_boolean (value)); break; + case PROP_SHOW_DEFAULT_ITEM: + gtk_app_chooser_button_set_show_default_item (self, g_value_get_boolean (value)); + break; + case PROP_HEADING: + gtk_app_chooser_button_set_heading (self, g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); break; @@ -472,6 +553,12 @@ gtk_app_chooser_button_get_property (GObject *obj, case PROP_SHOW_DIALOG_ITEM: g_value_set_boolean (value, self->priv->show_dialog_item); break; + case PROP_SHOW_DEFAULT_ITEM: + g_value_set_boolean (value, self->priv->show_default_item); + break; + case PROP_HEADING: + g_value_set_string (value, self->priv->heading); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); break; @@ -483,7 +570,11 @@ gtk_app_chooser_button_finalize (GObject *obj) { GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (obj); + g_hash_table_destroy (self->priv->custom_item_names); g_free (self->priv->content_type); + g_free (self->priv->heading); + + g_object_unref (self->priv->store); G_OBJECT_CLASS (gtk_app_chooser_button_parent_class)->finalize (obj); } @@ -511,13 +602,72 @@ gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass) g_object_class_override_property (oclass, PROP_CONTENT_TYPE, "content-type"); - pspec = g_param_spec_boolean ("show-dialog-item", - P_("Include an 'Other...' item"), - P_("Whether the combobox should include an item that triggers a GtkAppChooserDialog"), - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + /** + * GtkAppChooserButton:show-dialog-item: + * + * The #GtkAppChooserButton:show-dialog-item property determines + * whether the dropdown menu should show an item that triggers + * a #GtkAppChooserDialog when clicked. + */ + pspec = + g_param_spec_boolean ("show-dialog-item", + P_("Include an 'Other…' item"), + P_("Whether the combobox should include an item that triggers a GtkAppChooserDialog"), + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_SHOW_DIALOG_ITEM, pspec); + /** + * GtkAppChooserButton:show-default-item: + * + * The #GtkAppChooserButton:show-default-item property determines + * whether the dropdown menu should show the default application + * on top for the provided content type. + * + * Since: 3.2 + */ + pspec = + g_param_spec_boolean ("show-default-item", + P_("Show default item"), + P_("Whether the combobox should show the default application on top"), + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_SHOW_DEFAULT_ITEM, pspec); + + + /** + * GtkAppChooserButton:heading: + * + * The text to show at the top of the dialog that can be + * opened from the button. The string may contain Pango markup. + */ + pspec = g_param_spec_string ("heading", + P_("Heading"), + P_("The text to show at the top of the dialog"), + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_HEADING, pspec); + + + /** + * GtkAppChooserButton::custom-item-activated: + * @self: the object which received the signal + * @item_name: the name of the activated item + * + * Emitted when a custom item, previously added with + * gtk_app_chooser_button_append_custom_item(), is activated from the + * dropdown menu. + */ + signals[SIGNAL_CUSTOM_ITEM_ACTIVATED] = + g_signal_new ("custom-item-activated", + GTK_TYPE_APP_CHOOSER_BUTTON, + G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (GtkAppChooserButtonClass, custom_item_activated), + NULL, NULL, + _gtk_marshal_VOID__STRING, + G_TYPE_NONE, + 1, G_TYPE_STRING); + g_type_class_add_private (klass, sizeof (GtkAppChooserButtonPrivate)); } @@ -526,30 +676,79 @@ gtk_app_chooser_button_init (GtkAppChooserButton *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_APP_CHOOSER_BUTTON, GtkAppChooserButtonPrivate); + self->priv->custom_item_names = + g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + + self->priv->store = gtk_list_store_new (NUM_COLUMNS, + G_TYPE_APP_INFO, + G_TYPE_STRING, /* name */ + G_TYPE_STRING, /* label */ + G_TYPE_ICON, + G_TYPE_BOOLEAN, /* separator */ + G_TYPE_BOOLEAN); /* custom */ +} + +static gboolean +app_chooser_button_iter_from_custom_name (GtkAppChooserButton *self, + const gchar *name, + GtkTreeIter *set_me) +{ + GtkTreeIter iter; + gchar *custom_name = NULL; + + if (!gtk_tree_model_get_iter_first + (GTK_TREE_MODEL (self->priv->store), &iter)) + return FALSE; + + do { + gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter, + COLUMN_NAME, &custom_name, + -1); + + if (g_strcmp0 (custom_name, name) == 0) + { + g_free (custom_name); + *set_me = iter; + + return TRUE; + } + + g_free (custom_name); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->store), &iter)); + + return FALSE; } static void real_insert_custom_item (GtkAppChooserButton *self, + const gchar *name, const gchar *label, GIcon *icon, - GtkAppChooserButtonItemFunc func, - gpointer user_data, gboolean custom, GtkTreeIter *iter) { - CustomAppComboData *data; + if (custom) + { + if (g_hash_table_lookup (self->priv->custom_item_names, + name) != NULL) + { + g_warning ("Attempting to add custom item %s to GtkAppChooserButton, " + "when there's already an item with the same name", name); + return; + } - data = g_slice_new0 (CustomAppComboData); - data->func = func; - data->user_data = user_data; + g_hash_table_insert (self->priv->custom_item_names, + g_strdup (name), GINT_TO_POINTER (1)); + } gtk_list_store_set (self->priv->store, iter, - COLUMN_NAME, label, - COLUMN_ICON, icon, - COLUMN_CALLBACK, data, - COLUMN_CUSTOM, custom, - COLUMN_SEPARATOR, FALSE, - -1); + COLUMN_NAME, name, + COLUMN_LABEL, label, + COLUMN_ICON, icon, + COLUMN_CUSTOM, custom, + COLUMN_SEPARATOR, FALSE, + -1); } static void @@ -607,32 +806,78 @@ gtk_app_chooser_button_append_separator (GtkAppChooserButton *self) /** * gtk_app_chooser_button_append_custom_item: * @self: a #GtkAppChooserButton + * @name: the name of the custom item * @label: the label for the custom item * @icon: the icon for the custom item - * @func: callback to call if the item is activated - * @user_data: user data for @func * * Appends a custom item to the list of applications that is shown - * in the popup. See also gtk_app_chooser_button_append_separator(). + * in the popup; the item name must be unique per-widget. + * Clients can use the provided name as a detail for the + * #GtkAppChooserButton::custom-item-activated signal, to add a + * callback for the activation of a particular custom item in the list. + * See also gtk_app_chooser_button_append_separator(). * * Since: 3.0 */ void -gtk_app_chooser_button_append_custom_item (GtkAppChooserButton *self, - const gchar *label, - GIcon *icon, - GtkAppChooserButtonItemFunc func, - gpointer user_data) +gtk_app_chooser_button_append_custom_item (GtkAppChooserButton *self, + const gchar *name, + const gchar *label, + GIcon *icon) { GtkTreeIter iter; g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self)); + g_return_if_fail (name != NULL); gtk_list_store_append (self->priv->store, &iter); - real_insert_custom_item (self, label, icon, - func, user_data, TRUE, &iter); + real_insert_custom_item (self, name, label, icon, TRUE, &iter); +} + +/** + * gtk_app_chooser_button_set_active_custom_item: + * @self: a #GtkAppChooserButton + * @name: the name of the custom item + * + * Selects a custom item previously added with + * gtk_app_chooser_button_append_custom_item(). + * + * Use gtk_app_chooser_refresh() to bring the selection + * to its initial state. + * + * Since: 3.0 + */ +void +gtk_app_chooser_button_set_active_custom_item (GtkAppChooserButton *self, + const gchar *name) +{ + GtkTreeIter iter; + + g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self)); + g_return_if_fail (name != NULL); + + if (g_hash_table_lookup (self->priv->custom_item_names, name) == NULL || + !app_chooser_button_iter_from_custom_name (self, name, &iter)) + { + g_warning ("Can't find the item named %s in the app chooser.", + name); + return; + } + + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter); } +/** + * gtk_app_chooser_button_get_show_dialog_item: + * @self: a #GtkAppChooserButton + * + * Returns the current value of the #GtkAppChooserButton:show-dialog-item + * property. + * + * Returns: the value of #GtkAppChooserButton:show-dialog-item + * + * Since: 3.0 + */ gboolean gtk_app_chooser_button_get_show_dialog_item (GtkAppChooserButton *self) { @@ -641,9 +886,19 @@ gtk_app_chooser_button_get_show_dialog_item (GtkAppChooserButton *self) return self->priv->show_dialog_item; } +/** + * gtk_app_chooser_button_set_show_dialog_item: + * @self: a #GtkAppChooserButton + * @setting: the new value for #GtkAppChooserButton:show-dialog-item + * + * Sets whether the dropdown menu of this button should show an + * entry to trigger a #GtkAppChooserDialog. + * + * Since: 3.0 + */ void gtk_app_chooser_button_set_show_dialog_item (GtkAppChooserButton *self, - gboolean setting) + gboolean setting) { if (self->priv->show_dialog_item != setting) { @@ -654,3 +909,83 @@ gtk_app_chooser_button_set_show_dialog_item (GtkAppChooserButton *self, gtk_app_chooser_refresh (GTK_APP_CHOOSER (self)); } } + +/** + * gtk_app_chooser_button_get_show_default_item: + * @self: a #GtkAppChooserButton + * + * Returns the current value of the #GtkAppChooserButton:show-default-item + * property. + * + * Returns: the value of #GtkAppChooserButton:show-default-item + * + * Since: 3.2 + */ +gboolean +gtk_app_chooser_button_get_show_default_item (GtkAppChooserButton *self) +{ + g_return_val_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self), FALSE); + + return self->priv->show_default_item; +} + +/** + * gtk_app_chooser_button_set_show_default_item: + * @self: a #GtkAppChooserButton + * @setting: the new value for #GtkAppChooserButton:show-default-item + * + * Sets whether the dropdown menu of this button should show the + * default application for the given content type at top. + * + * Since: 3.2 + */ +void +gtk_app_chooser_button_set_show_default_item (GtkAppChooserButton *self, + gboolean setting) +{ + if (self->priv->show_default_item != setting) + { + self->priv->show_default_item = setting; + + g_object_notify (G_OBJECT (self), "show-default-item"); + + gtk_app_chooser_refresh (GTK_APP_CHOOSER (self)); + } +} + +/** + * gtk_app_chooser_button_set_heading: + * @self: a #GtkAppChooserButton + * @heading: a string containing Pango markup + * + * Sets the text to display at the top of the dialog. + * If the heading is not set, the dialog displays a default text. + */ +void +gtk_app_chooser_button_set_heading (GtkAppChooserButton *self, + const gchar *heading) +{ + g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self)); + + g_free (self->priv->heading); + self->priv->heading = g_strdup (heading); + + g_object_notify (G_OBJECT (self), "heading"); +} + +/** + * gtk_app_chooser_button_get_heading: + * @self: a #GtkAppChooserButton + * + * Returns the text to display at the top of the dialog. + * + * Returns: the text to display at the top of the dialog, + * or %NULL, in which case a default text is displayed + */ +const gchar * +gtk_app_chooser_button_get_heading (GtkAppChooserButton *self) +{ + g_return_val_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self), NULL); + + return self->priv->heading; +}