]> Pileus Git - ~andy/gtk/commitdiff
GtkAppChooserButton: Add a way to include the default app
authorMatthias Clasen <mclasen@redhat.com>
Sat, 10 Sep 2011 05:40:05 +0000 (01:40 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 10 Sep 2011 05:42:07 +0000 (01:42 -0400)
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
gtk/gtk.symbols
gtk/gtkappchooser.c
gtk/gtkappchooserbutton.c
gtk/gtkappchooserbutton.h
gtk/gtkappchooserdialog.c
gtk/gtkappchooserwidget.c
tests/testappchooser.c
tests/testappchooserbutton.c

index aca18e9a2d6dc7763897b3d4fefe44b18ed8072c..63b09412765b45a3af23ad1f78eab158ade1b2e5 100644 (file)
@@ -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
index c21babf4f7cc2d393bbf1f76e883c65fa42a2593..3624280116e85b4089f3fda8e8e80b7f0f52d662 100644 (file)
@@ -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
index a517002cc69d145cadfb71348f95e4a51c819659..e3f8a98821da359dfb8673eb43e6ba9daf80feb1 100644 (file)
  * 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"
index fbcd99dde6b6740ac84548edec75d38fad9c8e27..bd1d335d3da2a27a5032ea739d8a457f662fb7fc 100644 (file)
  *
  * 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;
 };
@@ -271,13 +293,36 @@ gtk_app_chooser_button_ensure_dialog_item (GtkAppChooserButton *self,
                            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);
+}
+
 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",
@@ -560,6 +619,24 @@ gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
                           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:
    *
@@ -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)
     {
@@ -835,6 +912,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
@@ -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)
index dd9e9cf6a3f068af05e935fad91dad0dc686da04..aeb9d9c62363261f7bb3e2361be135721cd58f80 100644 (file)
@@ -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
 
index 5412e7a91e2a5c894dd6375d2d0d2a7291a4ed13..28c6bc0a50855343bd8d2821bd2e7aa2346c7f36 100644 (file)
@@ -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"
 
index 551c1ddbb60ccd4af3f2e8bd7a66d43c58356df2..3ba1b59716421a1b0147d4d0a48858c866ee1a7a 100644 (file)
  * 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",
index dd40ed6b874acb8aff2c6ce4477ce2d674f884a6..2695c57d2909d19d7cdbc5eb3d28dc86d964d5ea 100644 (file)
@@ -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);
index 664a3291d243b384707ba212b407f6fccd0f61c2..d46eb2d46d8b79854157d65eacbd1dd4c5ef6056 100644 (file)
@@ -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",