[gtk+] GtkAppChooserButton: Add a way to include the default app



commit f9379adca22fe0399a3fe4b43370e0a70a4edfb5
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Sep 10 01:40:05 2011 -0400

    GtkAppChooserButton: Add a way to include the default app
    
    This is necessary to use an app chooser button for selecting
    default apps in the control center. Also, beef up the docs
    for this widget family.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=642706

 docs/reference/gtk/gtk3-sections.txt |    2 +
 gtk/gtk.symbols                      |    2 +
 gtk/gtkappchooser.c                  |   14 +++
 gtk/gtkappchooserbutton.c            |  172 ++++++++++++++++++++++++++++-----
 gtk/gtkappchooserbutton.h            |    3 +
 gtk/gtkappchooserdialog.c            |    3 +
 gtk/gtkappchooserwidget.c            |   47 ++++++---
 tests/testappchooser.c               |   10 ++-
 tests/testappchooserbutton.c         |    5 +-
 9 files changed, 215 insertions(+), 43 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index aca18e9..63b0941 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -7070,6 +7070,8 @@ gtk_app_chooser_button_new
 gtk_app_chooser_button_append_custom_item
 gtk_app_chooser_button_append_separator
 gtk_app_chooser_button_set_active_custom_item
+gtk_app_chooser_button_get_show_default_item
+gtk_app_chooser_button_set_show_default_item
 gtk_app_chooser_button_get_show_dialog_item
 gtk_app_chooser_button_set_show_dialog_item
 gtk_app_chooser_button_get_heading
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index c21babf..3624280 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -185,10 +185,12 @@ gtk_app_chooser_get_type
 gtk_app_chooser_refresh
 gtk_app_chooser_button_append_custom_item
 gtk_app_chooser_button_append_separator
+gtk_app_chooser_button_get_show_default_item
 gtk_app_chooser_button_get_show_dialog_item
 gtk_app_chooser_button_get_type
 gtk_app_chooser_button_new
 gtk_app_chooser_button_set_active_custom_item
+gtk_app_chooser_button_set_show_default_item
 gtk_app_chooser_button_set_show_dialog_item
 gtk_app_chooser_button_get_heading
 gtk_app_chooser_button_set_heading
diff --git a/gtk/gtkappchooser.c b/gtk/gtkappchooser.c
index a517002..e3f8a98 100644
--- a/gtk/gtkappchooser.c
+++ b/gtk/gtkappchooser.c
@@ -25,11 +25,25 @@
  * SECTION:gtkappchooser
  * @Title: GtkAppChooser
  * @Short_description: Interface implemented by widgets for choosing an application
+ * @See_also: #GAppInfo
  *
  * #GtkAppChooser is an interface that can be implemented by widgets which
  * allow the user to choose an application (typically for the purpose of
  * opening a file). The main objects that implement this interface are
  * #GtkAppChooserWidget, #GtkAppChooserDialog and #GtkAppChooserButton.
+ *
+ * Applications are represented by GIO #GAppInfo objects here.
+ * GIO has a concept of recommended and fallback applications for a
+ * given content type. Recommended applications are those that claim
+ * to handle the content type itself, while fallback also includes
+ * applications that handle a more generic content type. GIO also
+ * knows the default and last-used application for a given content
+ * type. The #GtkAppChooserWidget provides detailed control over
+ * whether the shown list of applications should include default,
+ * recommended or fallback applications.
+ *
+ * To obtain the application that has been selected in a #GtkAppChooser,
+ * use gtk_app_chooser_get_app_info().
  */
 
 #include "config.h"
diff --git a/gtk/gtkappchooserbutton.c b/gtk/gtkappchooserbutton.c
index fbcd99d..bd1d335 100644
--- a/gtk/gtkappchooserbutton.c
+++ b/gtk/gtkappchooserbutton.c
@@ -28,6 +28,26 @@
  *
  * 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"
 
@@ -47,6 +67,7 @@
 enum {
   PROP_CONTENT_TYPE = 1,
   PROP_SHOW_DIALOG_ITEM,
+  PROP_SHOW_DEFAULT_ITEM,
   PROP_HEADING
 };
 
@@ -93,6 +114,7 @@ struct _GtkAppChooserButtonPrivate {
   gchar *heading;
   gint last_active;
   gboolean show_dialog_item;
+  gboolean show_default_item;
 
   GHashTable *custom_item_names;
 };
@@ -272,12 +294,35 @@ gtk_app_chooser_button_ensure_dialog_item (GtkAppChooserButton *self,
 }
 
 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);
+}
+
+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 cycled_recommended;
 
 #ifndef G_OS_WIN32
@@ -286,16 +331,27 @@ gtk_app_chooser_button_populate (GtkAppChooserButton *self)
 #endif
   cycled_recommended = FALSE;
 
+  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 (cycled_recommended)
         {
@@ -308,16 +364,12 @@ gtk_app_chooser_button_populate (GtkAppChooserButton *self)
           cycled_recommended = TRUE;
         }
 
-      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);
+      insert_one_application (self, app, &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
@@ -475,6 +527,9 @@ 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;
@@ -500,6 +555,9 @@ 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;
@@ -549,8 +607,9 @@ gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
   /**
    * 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.
+   * 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",
@@ -561,6 +620,24 @@ gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
   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
@@ -616,8 +693,8 @@ gtk_app_chooser_button_init (GtkAppChooserButton *self)
 
 static gboolean
 app_chooser_button_iter_from_custom_name (GtkAppChooserButton *self,
-                                          const gchar *name,
-                                          GtkTreeIter *set_me)
+                                          const gchar         *name,
+                                          GtkTreeIter         *set_me)
 {
   GtkTreeIter iter;
   gchar *custom_name = NULL;
@@ -737,9 +814,9 @@ gtk_app_chooser_button_append_separator (GtkAppChooserButton *self)
  *
  * Appends a custom item to the list of applications that is shown
  * in the popup; the item name must be unique per-widget.
- * Clients can use the provided name as a detail for the ::custom-item-activated
- * signal, to add a callback for the activation of a particular
- * custom item in the list.
+ * 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
@@ -823,7 +900,7 @@ gtk_app_chooser_button_get_show_dialog_item (GtkAppChooserButton *self)
  */
 void
 gtk_app_chooser_button_set_show_dialog_item (GtkAppChooserButton *self,
-                                             gboolean setting)
+                                             gboolean             setting)
 {
   if (self->priv->show_dialog_item != setting)
     {
@@ -836,6 +913,49 @@ gtk_app_chooser_button_set_show_dialog_item (GtkAppChooserButton *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
@@ -861,8 +981,8 @@ gtk_app_chooser_button_set_heading (GtkAppChooserButton *self,
  *
  * 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
+ * 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)
diff --git a/gtk/gtkappchooserbutton.h b/gtk/gtkappchooserbutton.h
index dd9e9cf..aeb9d9c 100644
--- a/gtk/gtkappchooserbutton.h
+++ b/gtk/gtkappchooserbutton.h
@@ -80,6 +80,9 @@ void     gtk_app_chooser_button_set_heading           (GtkAppChooserButton *self
                                                        const gchar         *heading);
 const gchar *
          gtk_app_chooser_button_get_heading           (GtkAppChooserButton *self);
+void     gtk_app_chooser_button_set_show_default_item (GtkAppChooserButton *self,
+                                                       gboolean             setting);
+gboolean gtk_app_chooser_button_get_show_default_item (GtkAppChooserButton *self);
 
 G_END_DECLS
 
diff --git a/gtk/gtkappchooserdialog.c b/gtk/gtkappchooserdialog.c
index 5412e7a..28c6bc0 100644
--- a/gtk/gtkappchooserdialog.c
+++ b/gtk/gtkappchooserdialog.c
@@ -35,6 +35,9 @@
  * 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"
 
diff --git a/gtk/gtkappchooserwidget.c b/gtk/gtkappchooserwidget.c
index 551c1dd..3ba1b59 100644
--- a/gtk/gtkappchooserwidget.c
+++ b/gtk/gtkappchooserwidget.c
@@ -54,6 +54,19 @@
  * It is the main building block for #GtkAppChooserDialog. Most
  * applications only need to use the latter; but you can use
  * this widget as part of a larger widget if you have special needs.
+ *
+ * #GtkAppChooserWidget offers detailed control over what applications
+ * are shown, using the
+ * #GtkAppChooserWidget:show-default,
+ * #GtkAppChooserWidget:show-recommended,
+ * #GtkAppChooserWidget:show-fallback,
+ * #GtkAppChooserWidget:show-other and
+ * #GtkAppChooserWidget:show-all
+ * properties. See the #GtkAppChooser documentation for more information
+ * about these groups of applications.
+ *
+ * To keep track of the selected application, use the
+ * #GtkAppChooserWidget::application-selected and #GtkAppChooserWidget::application-activated signals.
  */
 
 struct _GtkAppChooserWidgetPrivate {
@@ -1022,9 +1035,10 @@ gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass)
   /**
    * GtkAppChooserWidget:show-recommended:
    *
-   * The #GtkAppChooserWidget:show-recommended property determines whether the app chooser
-   * should show a section for recommended applications. If %FALSE, the
-   * recommended applications are listed among the other applications.
+   * The #GtkAppChooserWidget:show-recommended property determines
+   * whether the app chooser should show a section for recommended
+   * applications. If %FALSE, the recommended applications are listed
+   * among the other applications.
    */
   pspec = g_param_spec_boolean ("show-recommended",
                                 P_("Show recommended apps"),
@@ -1036,9 +1050,10 @@ gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass)
   /**
    * GtkAppChooserWidget:show-fallback:
    *
-   * The #GtkAppChooserWidget:show-fallback property determines whether the app chooser
-   * should show a section for related applications. If %FALSE, the
-   * related applications are listed among the other applications.
+   * The #GtkAppChooserWidget:show-fallback property determines whether
+   * the app chooser should show a section for fallback applications.
+   * If %FALSE, the fallback applications are listed among the other
+   * applications.
    */
   pspec = g_param_spec_boolean ("show-fallback",
                                 P_("Show fallback apps"),
@@ -1050,8 +1065,8 @@ gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass)
   /**
    * GtkAppChooserWidget:show-other:
    *
-   * The #GtkAppChooserWidget:show-other property determines whether the app chooser
-   * should show a section for other applications.
+   * The #GtkAppChooserWidget:show-other property determines whether
+   * the app chooser should show a section for other applications.
    */
   pspec = g_param_spec_boolean ("show-other",
                                 P_("Show other apps"),
@@ -1063,9 +1078,9 @@ gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass)
   /**
    * GtkAppChooserWidget:show-all:
    *
-   * If the #GtkAppChooserWidget:show-all property is %TRUE, the app chooser presents
-   * all applications in a single list, without subsections for
-   * default, recommended or related applications.
+   * If the #GtkAppChooserWidget:show-all property is %TRUE, the app
+   * chooser presents all applications in a single list, without
+   * subsections for default, recommended or related applications.
    */
   pspec = g_param_spec_boolean ("show-all",
                                 P_("Show all apps"),
@@ -1077,8 +1092,9 @@ gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass)
   /**
    * GtkAppChooserWidget:default-text:
    *
-   * The #GtkAppChooserWidget:default-text property determines the text that appears
-   * in the widget when there are no applications for the given content type.
+   * The #GtkAppChooserWidget:default-text property determines the text
+   * that appears in the widget when there are no applications for the
+   * given content type.
    * See also gtk_app_chooser_widget_set_default_text().
    */
   pspec = g_param_spec_string ("default-text",
@@ -1111,6 +1127,7 @@ gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass)
    * @application: the activated #GAppInfo
    *
    * Emitted when an application item is activated from the widget's list.
+   *
    * This usually happens when the user double clicks an item, or an item
    * is selected and the user presses one of the keys Space, Shift+Space,
    * Return or Enter.
@@ -1133,8 +1150,8 @@ gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass)
    *
    * Emitted when a context menu is about to popup over an application item.
    * Clients can insert menu items into the provided #GtkMenu object in the
-   * callback of this signal; the context menu will be shown over the item if
-   * at least one item has been added to the menu.
+   * callback of this signal; the context menu will be shown over the item
+   * if at least one item has been added to the menu.
    */
   signals[SIGNAL_POPULATE_POPUP] =
     g_signal_new ("populate-popup",
diff --git a/tests/testappchooser.c b/tests/testappchooser.c
index dd40ed6..2695c57 100644
--- a/tests/testappchooser.c
+++ b/tests/testappchooser.c
@@ -26,7 +26,7 @@ static GFile *file;
 static GtkWidget *grid, *file_l, *open;
 static GtkWidget *radio_file, *radio_content, *dialog;
 static GtkWidget *app_chooser_widget;
-static GtkWidget *recommended, *fallback, *other, *all;
+static GtkWidget *def, *recommended, *fallback, *other, *all;
 
 static void
 dialog_response (GtkDialog *d,
@@ -58,6 +58,9 @@ dialog_response (GtkDialog *d,
 static void
 bind_props (void)
 {
+  g_object_bind_property (def, "active",
+                          app_chooser_widget, "show-default",
+                          G_BINDING_SYNC_CREATE);
   g_object_bind_property (recommended, "active",
                           app_chooser_widget, "show-recommended",
                           G_BINDING_SYNC_CREATE);
@@ -208,6 +211,11 @@ main (int argc, char **argv)
   gtk_grid_attach_next_to (GTK_GRID (grid), all,
                            other, GTK_POS_RIGHT, 1, 1);
 
+  def = gtk_check_button_new_with_label ("Show default");
+  gtk_grid_attach_next_to (GTK_GRID (grid), def,
+                           all, GTK_POS_RIGHT, 1, 1);
+
+  g_object_set (recommended, "active", TRUE, NULL);
   prepare_dialog ();
   g_signal_connect (open, "clicked",
                     G_CALLBACK (display_dialog), NULL);
diff --git a/tests/testappchooserbutton.c b/tests/testappchooserbutton.c
index 664a329..d46eb2d 100644
--- a/tests/testappchooserbutton.c
+++ b/tests/testappchooserbutton.c
@@ -111,6 +111,8 @@ main (int argc,
 
   gtk_app_chooser_button_set_show_dialog_item (GTK_APP_CHOOSER_BUTTON (combobox),
                                                TRUE);
+  gtk_app_chooser_button_set_show_default_item (GTK_APP_CHOOSER_BUTTON (combobox),
+                                                TRUE);
 
   /* connect to the detailed signal */
   g_signal_connect (combobox, "custom-item-activated::" CUSTOM_ITEM,
@@ -123,9 +125,10 @@ main (int argc,
   /* test refresh on a combo */
   gtk_app_chooser_refresh (GTK_APP_CHOOSER (combobox));
 
+#if 0
   gtk_app_chooser_button_set_active_custom_item (GTK_APP_CHOOSER_BUTTON (combobox),
                                                  CUSTOM_ITEM);
-
+#endif
   gtk_widget_show_all (toplevel);
 
   g_signal_connect (toplevel, "delete-event",



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]