X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkappchooserdialog.c;h=556486997621fda5835a125f16bc0a43632aa731;hb=9d0febc9a64a5bfb0fcfc3a88de4757f6c1ff090;hp=e8edea8c52a22895a38d705f19a5aac2b7a62b26;hpb=627f9b70a7d9d24c3a206c6866292a141d41b731;p=~andy%2Fgtk diff --git a/gtk/gtkappchooserdialog.c b/gtk/gtkappchooserdialog.c index e8edea8c5..556486997 100644 --- a/gtk/gtkappchooserdialog.c +++ b/gtk/gtkappchooserdialog.c @@ -15,16 +15,29 @@ * 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: Dave Camp * Alexander Larsson * Cosimo Cecchi */ -#include +/** + * SECTION:gtkappchooserdialog + * @Title: GtkAppChooserDialog + * @Short_description: An application chooser dialog + * + * #GtkAppChooserDialog shows a #GtkAppChooserWidget inside a #GtkDialog. + * + * Note that #GtkAppChooserDialog does not have any interesting methods + * of its own. Instead, you should get the embedded #GtkAppChooserWidget + * using gtk_app_chooser_dialog_get_widget() and call its methods if + * the generic #GtkAppChooser interface is not sufficient for your needs. + * + * To set the heading that is shown above the #GtkAppChooserWidget, + * use gtk_app_chooser_dialog_set_heading(). + */ +#include "config.h" #include "gtkappchooserdialog.h" @@ -32,10 +45,17 @@ #include "gtkappchooser.h" #include "gtkappchooseronline.h" #include "gtkappchooserprivate.h" +#include "gtkappchooserprivate.h" + +#include "gtkmessagedialog.h" +#include "gtklabel.h" +#include "gtkbbox.h" +#include "gtkbutton.h" +#include "gtkmenuitem.h" +#include "gtkstock.h" #include #include -#include #include #define sure_string(s) ((const char *) ((s) != NULL ? (s) : "")) @@ -43,6 +63,7 @@ struct _GtkAppChooserDialogPrivate { char *content_type; GFile *gfile; + char *heading; GtkWidget *label; GtkWidget *button; @@ -53,82 +74,142 @@ struct _GtkAppChooserDialogPrivate { GtkWidget *app_chooser_widget; GtkWidget *show_more_button; + GtkAppChooserOnline *online; + GCancellable *online_cancellable; + gboolean show_more_clicked; + gboolean dismissed; }; enum { PROP_GFILE = 1, PROP_CONTENT_TYPE, - N_PROPERTIES + PROP_HEADING }; static void gtk_app_chooser_dialog_iface_init (GtkAppChooserIface *iface); G_DEFINE_TYPE_WITH_CODE (GtkAppChooserDialog, gtk_app_chooser_dialog, GTK_TYPE_DIALOG, - G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER, - gtk_app_chooser_dialog_iface_init)); + G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER, + gtk_app_chooser_dialog_iface_init)); static void show_error_dialog (const gchar *primary, - const gchar *secondary, - GtkWindow *parent) + const gchar *secondary, + GtkWindow *parent) { GtkWidget *message_dialog; message_dialog = gtk_message_dialog_new (parent, 0, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - NULL); + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + NULL); g_object_set (message_dialog, - "text", primary, - "secondary-text", secondary, - NULL); + "text", primary, + "secondary-text", secondary, + NULL); gtk_dialog_set_default_response (GTK_DIALOG (message_dialog), GTK_RESPONSE_OK); gtk_widget_show (message_dialog); g_signal_connect (message_dialog, "response", - G_CALLBACK (gtk_widget_destroy), NULL); + G_CALLBACK (gtk_widget_destroy), NULL); } static void -search_for_mimetype_ready_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) +search_for_mimetype_ready_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) { GtkAppChooserOnline *online = GTK_APP_CHOOSER_ONLINE (source); GtkAppChooserDialog *self = user_data; GError *error = NULL; - gtk_app_chooser_online_search_for_mimetype_finish (online, res, &error); + gdk_threads_enter (); + + _gtk_app_chooser_online_search_for_mimetype_finish (online, res, &error); - if (error != NULL) + if (self->priv->dismissed) + goto out; + + if (error != NULL && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { show_error_dialog (_("Failed to look for applications online"), - error->message, GTK_WINDOW (self)); - g_error_free (error); + error->message, GTK_WINDOW (self)); } else { + gtk_widget_set_sensitive (self->priv->online_button, TRUE); gtk_app_chooser_refresh (GTK_APP_CHOOSER (self->priv->app_chooser_widget)); } - g_object_unref (online); + out: + g_clear_object (&self->priv->online_cancellable); + g_clear_error (&error); + g_object_unref (self); + + gdk_threads_leave (); } static void online_button_clicked_cb (GtkButton *b, - gpointer user_data) + gpointer user_data) { - GtkAppChooserOnline *online; GtkAppChooserDialog *self = user_data; - online = gtk_app_chooser_online_get_default (); + self->priv->online_cancellable = g_cancellable_new (); + gtk_widget_set_sensitive (self->priv->online_button, FALSE); - gtk_app_chooser_online_search_for_mimetype_async (online, - self->priv->content_type, - GTK_WINDOW (self), - search_for_mimetype_ready_cb, - self); + _gtk_app_chooser_online_search_for_mimetype_async (self->priv->online, + self->priv->content_type, + GTK_WINDOW (self), + self->priv->online_cancellable, + search_for_mimetype_ready_cb, + g_object_ref (self)); +} + +static void +app_chooser_online_get_default_ready_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + GtkAppChooserDialog *self = user_data; + + gdk_threads_enter (); + + self->priv->online = _gtk_app_chooser_online_get_default_finish (source, res); + + if (self->priv->online != NULL && + !self->priv->dismissed) + { + GtkWidget *action_area; + + action_area = gtk_dialog_get_action_area (GTK_DIALOG (self)); + self->priv->online_button = gtk_button_new_with_label (_("Find applications online")); + gtk_box_pack_start (GTK_BOX (action_area), self->priv->online_button, + FALSE, FALSE, 0); + gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (action_area), self->priv->online_button, + TRUE); + g_signal_connect (self->priv->online_button, "clicked", + G_CALLBACK (online_button_clicked_cb), self); + + + if (!self->priv->content_type) + gtk_widget_set_sensitive (self->priv->online_button, FALSE); + + gtk_widget_show (self->priv->online_button); + } + + g_object_unref (self); + + gdk_threads_leave (); +} + +static void +ensure_online_button (GtkAppChooserDialog *self) +{ + _gtk_app_chooser_online_get_default_async (app_chooser_online_get_default_ready_cb, + g_object_ref (self)); } /* An application is valid if: @@ -137,8 +218,8 @@ online_button_clicked_cb (GtkButton *b, * 2) The user has permissions to run the file */ static gboolean -check_application (GtkAppChooserDialog *self, - GAppInfo **app_out) +check_application (GtkAppChooserDialog *self, + GAppInfo **app_out) { const char *command; char *path = NULL; @@ -151,6 +232,12 @@ check_application (GtkAppChooserDialog *self, command = NULL; info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (self->priv->app_chooser_widget)); + if (info == NULL) + { + *app_out = NULL; + return FALSE; + } + command = g_app_info_get_executable (info); g_shell_parse_argv (command, &argc, &argv, &error); @@ -158,8 +245,8 @@ check_application (GtkAppChooserDialog *self, if (error) { show_error_dialog (_("Could not run application"), - error->message, - GTK_WINDOW (self)); + error->message, + GTK_WINDOW (self)); g_error_free (error); retval = FALSE; goto cleanup; @@ -171,11 +258,11 @@ check_application (GtkAppChooserDialog *self, char *error_message; error_message = g_strdup_printf (_("Could not find '%s'"), - argv[0]); + argv[0]); show_error_dialog (_("Could not find application"), - error_message, - GTK_WINDOW (self)); + error_message, + GTK_WINDOW (self)); g_free (error_message); retval = FALSE; goto cleanup; @@ -197,18 +284,31 @@ add_or_find_application (GtkAppChooserDialog *self) app = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (self)); - /* we don't care about reporting errors here */ - g_app_info_add_supports_type (app, - self->priv->content_type, - NULL); + if (app) + { + /* we don't care about reporting errors here */ + if (self->priv->content_type) + g_app_info_set_as_last_used_for_type (app, + self->priv->content_type, + NULL); + g_object_unref (app); + } +} - g_object_unref (app); +static void +cancel_and_clear_cancellable (GtkAppChooserDialog *self) +{ + if (self->priv->online_cancellable != NULL) + { + g_cancellable_cancel (self->priv->online_cancellable); + g_clear_object (&self->priv->online_cancellable); + } } static void gtk_app_chooser_dialog_response (GtkDialog *dialog, - gint response_id, - gpointer user_data) + gint response_id, + gpointer user_data) { GtkAppChooserDialog *self = GTK_APP_CHOOSER_DIALOG (dialog); @@ -217,6 +317,10 @@ gtk_app_chooser_dialog_response (GtkDialog *dialog, case GTK_RESPONSE_OK: add_or_find_application (self); break; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + cancel_and_clear_cancellable (self); + self->priv->dismissed = TRUE; default : break; } @@ -224,8 +328,8 @@ gtk_app_chooser_dialog_response (GtkDialog *dialog, static void widget_application_selected_cb (GtkAppChooserWidget *widget, - GAppInfo *app_info, - gpointer user_data) + GAppInfo *app_info, + gpointer user_data) { GtkAppChooserDialog *self = user_data; @@ -234,8 +338,8 @@ widget_application_selected_cb (GtkAppChooserWidget *widget, static void widget_application_activated_cb (GtkAppChooserWidget *widget, - GAppInfo *app_info, - gpointer user_data) + GAppInfo *app_info, + gpointer user_data) { GtkAppChooserDialog *self = user_data; @@ -258,13 +362,20 @@ get_extension (const char *basename) static void set_dialog_properties (GtkAppChooserDialog *self) { - char *label, *name, *extension, *description, *default_text, *string; + gchar *label; + gchar *name; + gchar *extension; + gchar *description; + gchar *default_text; + gchar *string; + gboolean unknown; PangoFontDescription *font_desc; name = NULL; extension = NULL; label = NULL; description = NULL; + unknown = TRUE; if (self->priv->gfile != NULL) { @@ -272,7 +383,12 @@ set_dialog_properties (GtkAppChooserDialog *self) extension = get_extension (name); } - description = g_content_type_get_description (self->priv->content_type); + if (self->priv->content_type) + { + description = g_content_type_get_description (self->priv->content_type); + unknown = g_content_type_is_unknown (self->priv->content_type); + } + gtk_window_set_title (GTK_WINDOW (self), ""); if (name != NULL) @@ -280,33 +396,34 @@ set_dialog_properties (GtkAppChooserDialog *self) /* Translators: %s is a filename */ label = g_strdup_printf (_("Select an application to open \"%s\""), name); string = g_strdup_printf (_("No applications available to open \"%s\""), - name); + name); } else { /* Translators: %s is a file type description */ label = g_strdup_printf (_("Select an application for \"%s\" files"), - g_content_type_is_unknown (self->priv->content_type) ? - self->priv->content_type : description); + unknown ? self->priv->content_type : description); string = g_strdup_printf (_("No applications available to open \"%s\" files"), - g_content_type_is_unknown (self->priv->content_type) ? - self->priv->content_type : description); + unknown ? self->priv->content_type : description); } font_desc = pango_font_description_new (); pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); - gtk_widget_modify_font (self->priv->label, font_desc); + gtk_widget_override_font (self->priv->label, font_desc); pango_font_description_free (font_desc); - gtk_label_set_markup (GTK_LABEL (self->priv->label), label); + if (self->priv->heading != NULL) + gtk_label_set_markup (GTK_LABEL (self->priv->label), self->priv->heading); + else + gtk_label_set_markup (GTK_LABEL (self->priv->label), label); default_text = g_strdup_printf ("%s\n%s", - string, - _("Click \"Show other applications\", for more options, or " - "\"Find applications online\" to install a new application")); + string, + _("Click \"Show other applications\", for more options, or " + "\"Find applications online\" to install a new application")); gtk_app_chooser_widget_set_default_text (GTK_APP_CHOOSER_WIDGET (self->priv->app_chooser_widget), - default_text); + default_text); g_free (label); g_free (name); @@ -318,30 +435,30 @@ set_dialog_properties (GtkAppChooserDialog *self) static void show_more_button_clicked_cb (GtkButton *button, - gpointer user_data) + gpointer user_data) { GtkAppChooserDialog *self = user_data; g_object_set (self->priv->app_chooser_widget, - "show-recommended", TRUE, - "show-fallback", TRUE, - "show-other", TRUE, - NULL); + "show-recommended", TRUE, + "show-fallback", TRUE, + "show-other", TRUE, + NULL); gtk_widget_hide (self->priv->show_more_button); self->priv->show_more_clicked = TRUE; } static void -widget_notify_for_button_cb (GObject *source, - GParamSpec *pspec, - gpointer user_data) +widget_notify_for_button_cb (GObject *source, + GParamSpec *pspec, + gpointer user_data) { GtkAppChooserDialog *self = user_data; GtkAppChooserWidget *widget = GTK_APP_CHOOSER_WIDGET (source); gboolean should_hide; - should_hide = gtk_app_chooser_widget_get_show_all (widget) || + should_hide = gtk_app_chooser_widget_get_show_other (widget) || self->priv->show_more_clicked; if (should_hide) @@ -350,7 +467,7 @@ widget_notify_for_button_cb (GObject *source, static void forget_menu_item_activate_cb (GtkMenuItem *item, - gpointer user_data) + gpointer user_data) { GtkAppChooserDialog *self = user_data; GAppInfo *info; @@ -359,8 +476,7 @@ forget_menu_item_activate_cb (GtkMenuItem *item, if (info != NULL) { - g_app_info_remove_supports_type (info, self->priv->content_type, - NULL); + g_app_info_remove_supports_type (info, self->priv->content_type, NULL); gtk_app_chooser_refresh (GTK_APP_CHOOSER (self)); @@ -377,16 +493,16 @@ build_forget_menu_item (GtkAppChooserDialog *self) gtk_widget_show (retval); g_signal_connect (retval, "activate", - G_CALLBACK (forget_menu_item_activate_cb), self); + G_CALLBACK (forget_menu_item_activate_cb), self); return retval; } static void widget_populate_popup_cb (GtkAppChooserWidget *widget, - GtkMenu *menu, - GAppInfo *info, - gpointer user_data) + GtkMenu *menu, + GAppInfo *info, + gpointer user_data) { GtkAppChooserDialog *self = user_data; GtkWidget *menu_item; @@ -403,8 +519,8 @@ build_dialog_ui (GtkAppChooserDialog *self) { GtkWidget *vbox; GtkWidget *vbox2; - GtkWidget *label; - GtkWidget *action_area, *button, *w; + GtkWidget *button, *w; + GAppInfo *info; gtk_container_set_border_width (GTK_CONTAINER (self), 5); @@ -412,16 +528,17 @@ build_dialog_ui (GtkAppChooserDialog *self) gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), vbox, TRUE, TRUE, 0); gtk_widget_show (vbox); - + vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_box_pack_start (GTK_BOX (vbox), vbox2, TRUE, TRUE, 0); gtk_widget_show (vbox2); self->priv->label = gtk_label_new (""); - gtk_misc_set_alignment (GTK_MISC (self->priv->label), 0, 0.5); + gtk_widget_set_halign (self->priv->label, GTK_ALIGN_START); + gtk_widget_set_valign (self->priv->label, GTK_ALIGN_CENTER); gtk_label_set_line_wrap (GTK_LABEL (self->priv->label), TRUE); gtk_box_pack_start (GTK_BOX (vbox2), self->priv->label, - FALSE, FALSE, 0); + FALSE, FALSE, 0); gtk_widget_show (self->priv->label); self->priv->app_chooser_widget = @@ -430,64 +547,45 @@ build_dialog_ui (GtkAppChooserDialog *self) gtk_widget_show (self->priv->app_chooser_widget); g_signal_connect (self->priv->app_chooser_widget, "application-selected", - G_CALLBACK (widget_application_selected_cb), self); + G_CALLBACK (widget_application_selected_cb), self); g_signal_connect (self->priv->app_chooser_widget, "application-activated", - G_CALLBACK (widget_application_activated_cb), self); - g_signal_connect (self->priv->app_chooser_widget, "notify::show-all", - G_CALLBACK (widget_notify_for_button_cb), self); + G_CALLBACK (widget_application_activated_cb), self); + g_signal_connect (self->priv->app_chooser_widget, "notify::show-other", + G_CALLBACK (widget_notify_for_button_cb), self); g_signal_connect (self->priv->app_chooser_widget, "populate-popup", - G_CALLBACK (widget_populate_popup_cb), self); + G_CALLBACK (widget_populate_popup_cb), self); button = gtk_button_new_with_label (_("Show other applications")); self->priv->show_more_button = button; w = gtk_image_new_from_stock (GTK_STOCK_ADD, - GTK_ICON_SIZE_BUTTON); + GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button), w); gtk_box_pack_start (GTK_BOX (self->priv->app_chooser_widget), button, FALSE, FALSE, 6); gtk_widget_show_all (button); g_signal_connect (button, "clicked", - G_CALLBACK (show_more_button_clicked_cb), self); + G_CALLBACK (show_more_button_clicked_cb), self); gtk_dialog_add_button (GTK_DIALOG (self), - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL); - - /* Create a custom stock icon */ - self->priv->button = gtk_button_new (); - - label = gtk_label_new_with_mnemonic (_("_Open")); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (self->priv->button)); - gtk_widget_set_halign (label, GTK_ALIGN_CENTER); - gtk_widget_show (label); - self->priv->open_label = label; - - gtk_container_add (GTK_CONTAINER (self->priv->button), - self->priv->open_label); - - gtk_widget_show (self->priv->button); - gtk_widget_set_can_default (self->priv->button, TRUE); + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); - gtk_dialog_add_action_widget (GTK_DIALOG (self), - self->priv->button, GTK_RESPONSE_OK); + self->priv->button = gtk_dialog_add_button (GTK_DIALOG (self), + _("_Select"), + GTK_RESPONSE_OK); - action_area = gtk_dialog_get_action_area (GTK_DIALOG (self)); - self->priv->online_button = gtk_button_new_with_label (_("Find applications online")); - gtk_box_pack_start (GTK_BOX (action_area), self->priv->online_button, - FALSE, FALSE, 0); - gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (action_area), self->priv->online_button, - TRUE); - gtk_widget_show (self->priv->online_button); - g_signal_connect (self->priv->online_button, "clicked", - G_CALLBACK (online_button_clicked_cb), self); + info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (self->priv->app_chooser_widget)); + gtk_widget_set_sensitive (self->priv->button, info != NULL); + if (info) + g_object_unref (info); gtk_dialog_set_default_response (GTK_DIALOG (self), - GTK_RESPONSE_OK); + GTK_RESPONSE_OK); } static void set_gfile_and_content_type (GtkAppChooserDialog *self, - GFile *file) + GFile *file) { GFileInfo *info; @@ -497,8 +595,8 @@ set_gfile_and_content_type (GtkAppChooserDialog *self, self->priv->gfile = g_object_ref (file); info = g_file_query_info (self->priv->gfile, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - 0, NULL, NULL); + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + 0, NULL, NULL); self->priv->content_type = g_strdup (g_file_info_get_content_type (info)); g_object_unref (info); @@ -529,23 +627,30 @@ gtk_app_chooser_dialog_constructed (GObject *object) { GtkAppChooserDialog *self = GTK_APP_CHOOSER_DIALOG (object); - g_assert (self->priv->content_type != NULL || - self->priv->gfile != NULL); - if (G_OBJECT_CLASS (gtk_app_chooser_dialog_parent_class)->constructed != NULL) G_OBJECT_CLASS (gtk_app_chooser_dialog_parent_class)->constructed (object); build_dialog_ui (self); set_dialog_properties (self); + ensure_online_button (self); } static void -gtk_app_chooser_dialog_finalize (GObject *object) +gtk_app_chooser_dialog_dispose (GObject *object) { GtkAppChooserDialog *self = GTK_APP_CHOOSER_DIALOG (object); + + g_clear_object (&self->priv->gfile); + cancel_and_clear_cancellable (self); + g_clear_object (&self->priv->online); + + G_OBJECT_CLASS (gtk_app_chooser_dialog_parent_class)->dispose (object); +} - if (self->priv->gfile) - g_object_unref (self->priv->gfile); +static void +gtk_app_chooser_dialog_finalize (GObject *object) +{ + GtkAppChooserDialog *self = GTK_APP_CHOOSER_DIALOG (object); g_free (self->priv->content_type); @@ -553,10 +658,10 @@ gtk_app_chooser_dialog_finalize (GObject *object) } static void -gtk_app_chooser_dialog_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) +gtk_app_chooser_dialog_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { GtkAppChooserDialog *self = GTK_APP_CHOOSER_DIALOG (object); @@ -568,7 +673,10 @@ gtk_app_chooser_dialog_set_property (GObject *object, case PROP_CONTENT_TYPE: /* don't try to override a value previously set with the GFile */ if (self->priv->content_type == NULL) - self->priv->content_type = g_value_dup_string (value); + self->priv->content_type = g_value_dup_string (value); + break; + case PROP_HEADING: + gtk_app_chooser_dialog_set_heading (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -577,10 +685,10 @@ gtk_app_chooser_dialog_set_property (GObject *object, } static void -gtk_app_chooser_dialog_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) +gtk_app_chooser_dialog_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { GtkAppChooserDialog *self = GTK_APP_CHOOSER_DIALOG (object); @@ -588,11 +696,14 @@ gtk_app_chooser_dialog_get_property (GObject *object, { case PROP_GFILE: if (self->priv->gfile != NULL) - g_value_set_object (value, self->priv->gfile); + g_value_set_object (value, self->priv->gfile); break; case PROP_CONTENT_TYPE: g_value_set_string (value, self->priv->content_type); break; + case PROP_HEADING: + g_value_set_string (value, self->priv->heading); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -613,6 +724,7 @@ gtk_app_chooser_dialog_class_init (GtkAppChooserDialogClass *klass) GParamSpec *pspec; gobject_class = G_OBJECT_CLASS (klass); + gobject_class->dispose = gtk_app_chooser_dialog_dispose; gobject_class->finalize = gtk_app_chooser_dialog_finalize; gobject_class->set_property = gtk_app_chooser_dialog_set_property; gobject_class->get_property = gtk_app_chooser_dialog_get_property; @@ -620,14 +732,35 @@ gtk_app_chooser_dialog_class_init (GtkAppChooserDialogClass *klass) g_object_class_override_property (gobject_class, PROP_CONTENT_TYPE, "content-type"); + /** + * GtkAppChooserDialog:gfile: + * + * The GFile used by the #GtkAppChooserDialog. + * The dialog's #GtkAppChooserWidget content type will be guessed from the + * file, if present. + */ pspec = g_param_spec_object ("gfile", - P_("GFile"), - P_("The GFile used by the open with dialog"), - G_TYPE_FILE, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); + P_("GFile"), + P_("The GFile used by the app chooser dialog"), + G_TYPE_FILE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); g_object_class_install_property (gobject_class, PROP_GFILE, pspec); + /** + * GtkAppChooserDialog:heading: + * + * The text to show at the top of the dialog. + * 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 (gobject_class, PROP_HEADING, pspec); + + g_type_class_add_private (klass, sizeof (GtkAppChooserDialogPrivate)); } @@ -635,24 +768,23 @@ static void gtk_app_chooser_dialog_init (GtkAppChooserDialog *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_APP_CHOOSER_DIALOG, - GtkAppChooserDialogPrivate); + GtkAppChooserDialogPrivate); /* we can't override the class signal handler here, as it's a RUN_LAST; * we want our signal handler instead to be executed before any user code. */ g_signal_connect (self, "response", - G_CALLBACK (gtk_app_chooser_dialog_response), NULL); + G_CALLBACK (gtk_app_chooser_dialog_response), NULL); } static void -set_parent_and_flags (GtkWidget *dialog, - GtkWindow *parent, - GtkDialogFlags flags) +set_parent_and_flags (GtkWidget *dialog, + GtkWindow *parent, + GtkDialogFlags flags) { if (parent != NULL) - gtk_window_set_transient_for (GTK_WINDOW (dialog), - parent); - + gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); + if (flags & GTK_DIALOG_MODAL) gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); @@ -666,25 +798,25 @@ set_parent_and_flags (GtkWidget *dialog, * @flags: flags for this dialog * @file: a #GFile * - * Creates a new #GtkAppChooserDialog for the provided #GFile, to allow - * the user to select an application for it. + * Creates a new #GtkAppChooserDialog for the provided #GFile, + * to allow the user to select an application for it. * * Returns: a newly created #GtkAppChooserDialog * * Since: 3.0 **/ GtkWidget * -gtk_app_chooser_dialog_new (GtkWindow *parent, - GtkDialogFlags flags, - GFile *file) +gtk_app_chooser_dialog_new (GtkWindow *parent, + GtkDialogFlags flags, + GFile *file) { GtkWidget *retval; g_return_val_if_fail (G_IS_FILE (file), NULL); retval = g_object_new (GTK_TYPE_APP_CHOOSER_DIALOG, - "gfile", file, - NULL); + "gfile", file, + NULL); set_parent_and_flags (retval, parent, flags); @@ -697,31 +829,41 @@ gtk_app_chooser_dialog_new (GtkWindow *parent, * @flags: flags for this dialog * @content_type: a content type string * - * Creates a new #GtkAppChooserDialog for the provided content type, to allow - * the user to select an application for it. + * Creates a new #GtkAppChooserDialog for the provided content type, + * to allow the user to select an application for it. * * Returns: a newly created #GtkAppChooserDialog * * Since: 3.0 **/ GtkWidget * -gtk_app_chooser_dialog_new_for_content_type (GtkWindow *parent, - GtkDialogFlags flags, - const gchar *content_type) +gtk_app_chooser_dialog_new_for_content_type (GtkWindow *parent, + GtkDialogFlags flags, + const gchar *content_type) { GtkWidget *retval; g_return_val_if_fail (content_type != NULL, NULL); retval = g_object_new (GTK_TYPE_APP_CHOOSER_DIALOG, - "content-type", content_type, - NULL); + "content-type", content_type, + NULL); set_parent_and_flags (retval, parent, flags); return retval; } +/** + * gtk_app_chooser_dialog_get_widget: + * @self: a #GtkAppChooserDialog + * + * Returns the #GtkAppChooserWidget of this dialog. + * + * Returns: (transfer none): the #GtkAppChooserWidget of @self + * + * Since: 3.0 + */ GtkWidget * gtk_app_chooser_dialog_get_widget (GtkAppChooserDialog *self) { @@ -729,3 +871,43 @@ gtk_app_chooser_dialog_get_widget (GtkAppChooserDialog *self) return self->priv->app_chooser_widget; } + +/** + * gtk_app_chooser_dialog_set_heading: + * @self: a #GtkAppChooserDialog + * @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_dialog_set_heading (GtkAppChooserDialog *self, + const gchar *heading) +{ + g_return_if_fail (GTK_IS_APP_CHOOSER_DIALOG (self)); + + g_free (self->priv->heading); + self->priv->heading = g_strdup (heading); + + if (self->priv->label && self->priv->heading) + gtk_label_set_markup (GTK_LABEL (self->priv->label), self->priv->heading); + + g_object_notify (G_OBJECT (self), "heading"); +} + +/** + * gtk_app_chooser_dialog_get_heading: + * @self: a #GtkAppChooserDialog + * + * 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_dialog_get_heading (GtkAppChooserDialog *self) +{ + g_return_val_if_fail (GTK_IS_APP_CHOOSER_DIALOG (self), NULL); + + return self->priv->heading; +}