* 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 <http://www.gnu.org/licenses/>.
*
* Authors: Dave Camp <dave@novell.com>
* Alexander Larsson <alexl@redhat.com>
* Cosimo Cecchi <ccecchi@redhat.com>
*/
-#include <config.h>
+#include "config.h"
#include "gtkappchooserwidget.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
-#include "gtkappchooser.h"
+#include "gtkappchooserwidget.h"
#include "gtkappchooserprivate.h"
+#include "gtkliststore.h"
+#include "gtkcellrenderertext.h"
+#include "gtkcellrendererpixbuf.h"
+#include "gtktreeview.h"
+#include "gtktreeselection.h"
+#include "gtktreemodelsort.h"
+#include "gtkorientable.h"
+#include "gtkscrolledwindow.h"
#include <string.h>
#include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
#include <gio/gio.h>
+/**
+ * SECTION:gtkappchooserwidget
+ * @Title: GtkAppChooserWidget
+ * @Short_description: Application chooser widget that can be embedded in other widgets
+ *
+ * #GtkAppChooserWidget is a widget for selecting applications.
+ * 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 {
GAppInfo *selected_app_info;
gchar *content_type;
gchar *default_text;
- gboolean show_default;
- gboolean show_recommended;
- gboolean show_fallback;
- gboolean show_other;
- gboolean show_all;
+
+ guint show_default : 1;
+ guint show_recommended : 1;
+ guint show_fallback : 1;
+ guint show_other : 1;
+ guint show_all : 1;
GtkWidget *program_list;
GtkListStore *program_list_store;
enum {
SIGNAL_APPLICATION_SELECTED,
SIGNAL_APPLICATION_ACTIVATED,
+ SIGNAL_POPULATE_POPUP,
N_SIGNALS
};
static void gtk_app_chooser_widget_iface_init (GtkAppChooserIface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkAppChooserWidget, gtk_app_chooser_widget, GTK_TYPE_BOX,
- G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER,
- gtk_app_chooser_widget_iface_init));
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER,
+ gtk_app_chooser_widget_iface_init));
static void
refresh_and_emit_app_selected (GtkAppChooserWidget *self,
- GtkTreeSelection *selection)
+ GtkTreeSelection *selection)
{
GtkTreeModel *model;
GtkTreeIter iter;
gboolean should_emit = FALSE;
if (gtk_tree_selection_get_selected (selection, &model, &iter))
- {
- gtk_tree_model_get (model, &iter,
- COLUMN_APP_INFO, &info,
- -1);
- }
+ gtk_tree_model_get (model, &iter, COLUMN_APP_INFO, &info, -1);
if (info == NULL)
return;
- if (self->priv->selected_app_info != NULL)
+ if (self->priv->selected_app_info)
{
if (!g_app_info_equal (self->priv->selected_app_info, info))
- {
- should_emit = TRUE;
- g_object_unref (self->priv->selected_app_info);
+ {
+ should_emit = TRUE;
+ g_object_unref (self->priv->selected_app_info);
- self->priv->selected_app_info = info;
- }
+ self->priv->selected_app_info = info;
+ }
}
else
{
if (should_emit)
g_signal_emit (self, signals[SIGNAL_APPLICATION_SELECTED], 0,
- self->priv->selected_app_info);
+ self->priv->selected_app_info);
+}
+
+static GAppInfo *
+get_app_info_for_event (GtkAppChooserWidget *self,
+ GdkEventButton *event)
+{
+ GtkTreePath *path = NULL;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GAppInfo *info;
+ gboolean recommended;
+
+ if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (self->priv->program_list),
+ event->x, event->y,
+ &path,
+ NULL, NULL, NULL))
+ return NULL;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->program_list));
+
+ if (!gtk_tree_model_get_iter (model, &iter, path))
+ {
+ gtk_tree_path_free (path);
+ return NULL;
+ }
+
+ /* we only allow interaction with recommended applications */
+ gtk_tree_model_get (model, &iter,
+ COLUMN_APP_INFO, &info,
+ COLUMN_RECOMMENDED, &recommended,
+ -1);
+
+ if (!recommended)
+ g_clear_object (&info);
+
+ return info;
+}
+
+static gboolean
+widget_button_press_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ GtkAppChooserWidget *self = user_data;
+
+ if (event->button == GDK_BUTTON_SECONDARY && event->type == GDK_BUTTON_PRESS)
+ {
+ GAppInfo *info;
+ GtkWidget *menu;
+ GList *children;
+ gint n_children;
+
+ info = get_app_info_for_event (self, event);
+
+ if (info == NULL)
+ return FALSE;
+
+ menu = gtk_menu_new ();
+
+ g_signal_emit (self, signals[SIGNAL_POPULATE_POPUP], 0,
+ menu, info);
+
+ g_object_unref (info);
+
+ /* see if clients added menu items to this container */
+ children = gtk_container_get_children (GTK_CONTAINER (menu));
+ n_children = g_list_length (children);
+
+ if (n_children > 0)
+ {
+ /* actually popup the menu */
+ gtk_menu_attach_to_widget (GTK_MENU (menu), self->priv->program_list, NULL);
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+ event->button, event->time);
+ }
+
+ g_list_free (children);
+ }
+
+ return FALSE;
}
static gboolean
path_is_heading (GtkTreeView *view,
- GtkTreePath *path)
+ GtkTreePath *path)
{
GtkTreeIter iter;
GtkTreeModel *model;
model = gtk_tree_view_get_model (view);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter,
- COLUMN_HEADING, &res,
- -1);
+ COLUMN_HEADING, &res,
+ -1);
return res;
}
static void
-program_list_selection_activated (GtkTreeView *view,
- GtkTreePath *path,
- GtkTreeViewColumn *column,
- gpointer user_data)
+program_list_selection_activated (GtkTreeView *view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ gpointer user_data)
{
GtkAppChooserWidget *self = user_data;
GtkTreeSelection *selection;
refresh_and_emit_app_selected (self, selection);
g_signal_emit (self, signals[SIGNAL_APPLICATION_ACTIVATED], 0,
- self->priv->selected_app_info);
+ self->priv->selected_app_info);
}
static gboolean
gtk_app_chooser_search_equal_func (GtkTreeModel *model,
- int column,
- const char *key,
- GtkTreeIter *iter,
- gpointer user_data)
+ gint column,
+ const gchar *key,
+ GtkTreeIter *iter,
+ gpointer user_data)
{
- char *normalized_key;
- char *name, *normalized_name;
- char *path, *normalized_path;
- char *basename, *normalized_basename;
+ gchar *normalized_key;
+ gchar *name, *normalized_name;
+ gchar *path, *normalized_path;
+ gchar *basename, *normalized_basename;
gboolean ret;
if (key != NULL)
ret = TRUE;
gtk_tree_model_get (model, iter,
- COLUMN_NAME, &name,
- COLUMN_EXEC, &path,
- -1);
+ COLUMN_NAME, &name,
+ COLUMN_EXEC, &path,
+ -1);
if (name != NULL)
- {
- normalized_name = g_utf8_casefold (name, -1);
- g_assert (normalized_name != NULL);
+ {
+ normalized_name = g_utf8_casefold (name, -1);
+ g_assert (normalized_name != NULL);
- if (strncmp (normalized_name, normalized_key, strlen (normalized_key)) == 0) {
- ret = FALSE;
- }
+ if (strncmp (normalized_name, normalized_key, strlen (normalized_key)) == 0)
+ ret = FALSE;
- g_free (normalized_name);
- }
+ g_free (normalized_name);
+ }
if (ret && path != NULL)
- {
- normalized_path = g_utf8_casefold (path, -1);
- g_assert (normalized_path != NULL);
+ {
+ normalized_path = g_utf8_casefold (path, -1);
+ g_assert (normalized_path != NULL);
- basename = g_path_get_basename (path);
- g_assert (basename != NULL);
+ basename = g_path_get_basename (path);
+ g_assert (basename != NULL);
- normalized_basename = g_utf8_casefold (basename, -1);
- g_assert (normalized_basename != NULL);
+ normalized_basename = g_utf8_casefold (basename, -1);
+ g_assert (normalized_basename != NULL);
- if (strncmp (normalized_path, normalized_key, strlen (normalized_key)) == 0 ||
- strncmp (normalized_basename, normalized_key, strlen (normalized_key)) == 0) {
- ret = FALSE;
- }
+ if (strncmp (normalized_path, normalized_key, strlen (normalized_key)) == 0 ||
+ strncmp (normalized_basename, normalized_key, strlen (normalized_key)) == 0)
+ ret = FALSE;
- g_free (basename);
- g_free (normalized_basename);
- g_free (normalized_path);
- }
+ g_free (basename);
+ g_free (normalized_basename);
+ g_free (normalized_path);
+ }
g_free (name);
g_free (path);
static gint
gtk_app_chooser_sort_func (GtkTreeModel *model,
- GtkTreeIter *a,
- GtkTreeIter *b,
- gpointer user_data)
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
{
gboolean a_recommended, b_recommended;
gboolean a_fallback, b_fallback;
*/
gtk_tree_model_get (model, a,
- COLUMN_NAME, &a_name,
- COLUMN_RECOMMENDED, &a_recommended,
- COLUMN_FALLBACK, &a_fallback,
- COLUMN_HEADING, &a_heading,
- COLUMN_DEFAULT, &a_default,
- -1);
+ COLUMN_NAME, &a_name,
+ COLUMN_RECOMMENDED, &a_recommended,
+ COLUMN_FALLBACK, &a_fallback,
+ COLUMN_HEADING, &a_heading,
+ COLUMN_DEFAULT, &a_default,
+ -1);
gtk_tree_model_get (model, b,
- COLUMN_NAME, &b_name,
- COLUMN_RECOMMENDED, &b_recommended,
- COLUMN_FALLBACK, &b_fallback,
- COLUMN_HEADING, &b_heading,
- COLUMN_DEFAULT, &b_default,
- -1);
+ COLUMN_NAME, &b_name,
+ COLUMN_RECOMMENDED, &b_recommended,
+ COLUMN_FALLBACK, &b_fallback,
+ COLUMN_HEADING, &b_heading,
+ COLUMN_DEFAULT, &b_default,
+ -1);
/* the default one always wins */
if (a_default && !b_default)
/* they're both recommended/falback or not, so if one is a heading, wins */
if (a_heading)
{
- return -1;
+ retval = -1;
goto out;
}
if (b_heading)
{
- return 1;
+ retval = 1;
goto out;
}
if (!a_recommended)
{
a_casefold = a_name != NULL ?
- g_utf8_casefold (a_name, -1) : NULL;
+ g_utf8_casefold (a_name, -1) : NULL;
b_casefold = b_name != NULL ?
- g_utf8_casefold (b_name, -1) : NULL;
+ g_utf8_casefold (b_name, -1) : NULL;
retval = g_strcmp0 (a_casefold, b_casefold);
static void
padding_cell_renderer_func (GtkTreeViewColumn *column,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer user_data)
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
{
gboolean heading;
gtk_tree_model_get (model, iter,
- COLUMN_HEADING, &heading,
- -1);
+ COLUMN_HEADING, &heading,
+ -1);
if (heading)
g_object_set (cell,
- "visible", FALSE,
- "xpad", 0,
- "ypad", 0,
- NULL);
+ "visible", FALSE,
+ "xpad", 0,
+ "ypad", 0,
+ NULL);
else
g_object_set (cell,
- "visible", TRUE,
- "xpad", 3,
- "ypad", 3,
- NULL);
+ "visible", TRUE,
+ "xpad", 3,
+ "ypad", 3,
+ NULL);
}
static gboolean
gtk_app_chooser_selection_func (GtkTreeSelection *selection,
- GtkTreeModel *model,
- GtkTreePath *path,
- gboolean path_currently_selected,
- gpointer user_data)
+ GtkTreeModel *model,
+ GtkTreePath *path,
+ gboolean path_currently_selected,
+ gpointer user_data)
{
GtkTreeIter iter;
gboolean heading;
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter,
- COLUMN_HEADING, &heading,
- -1);
+ COLUMN_HEADING, &heading,
+ -1);
return !heading;
}
static gint
compare_apps_func (gconstpointer a,
- gconstpointer b)
+ gconstpointer b)
{
return !g_app_info_equal (G_APP_INFO (a), G_APP_INFO (b));
}
static gboolean
gtk_app_chooser_widget_add_section (GtkAppChooserWidget *self,
- const gchar *heading_title,
- gboolean show_headings,
- gboolean recommended,
- gboolean fallback,
- GList *applications,
- GList *exclude_apps)
+ const gchar *heading_title,
+ gboolean show_headings,
+ gboolean recommended,
+ gboolean fallback,
+ GList *applications,
+ GList *exclude_apps)
{
gboolean heading_added, unref_icon;
GtkTreeIter iter;
{
app = l->data;
- if (exclude_apps != NULL &&
- g_list_find_custom (exclude_apps, app,
- (GCompareFunc) compare_apps_func))
- continue;
+ if (!g_app_info_supports_uris (app) &&
+ !g_app_info_supports_files (app))
+ continue;
+
+ if (g_list_find_custom (exclude_apps, app,
+ (GCompareFunc) compare_apps_func))
+ continue;
if (!heading_added && show_headings)
- {
- gtk_list_store_append (self->priv->program_list_store, &iter);
- gtk_list_store_set (self->priv->program_list_store, &iter,
- COLUMN_HEADING_TEXT, bold_string,
- COLUMN_HEADING, TRUE,
- COLUMN_RECOMMENDED, recommended,
- COLUMN_FALLBACK, fallback,
- -1);
-
- heading_added = TRUE;
- }
-
- app_string = g_strdup_printf ("<b>%s</b>\n%s",
- g_app_info_get_display_name (app) != NULL ?
- g_app_info_get_display_name (app) : "",
- g_app_info_get_description (app) != NULL ?
- g_app_info_get_description (app) : "");
+ {
+ gtk_list_store_append (self->priv->program_list_store, &iter);
+ gtk_list_store_set (self->priv->program_list_store, &iter,
+ COLUMN_HEADING_TEXT, bold_string,
+ COLUMN_HEADING, TRUE,
+ COLUMN_RECOMMENDED, recommended,
+ COLUMN_FALLBACK, fallback,
+ -1);
+
+ heading_added = TRUE;
+ }
+
+ app_string = g_markup_printf_escaped ("%s",
+ g_app_info_get_name (app) != NULL ?
+ g_app_info_get_name (app) : "");
icon = g_app_info_get_icon (app);
+ unref_icon = FALSE;
if (icon == NULL)
- {
- icon = g_themed_icon_new ("application-x-executable");
- unref_icon = TRUE;
- }
+ {
+ icon = g_themed_icon_new ("application-x-executable");
+ unref_icon = TRUE;
+ }
gtk_list_store_append (self->priv->program_list_store, &iter);
gtk_list_store_set (self->priv->program_list_store, &iter,
- COLUMN_APP_INFO, app,
- COLUMN_GICON, icon,
- COLUMN_NAME, g_app_info_get_display_name (app),
- COLUMN_DESC, app_string,
- COLUMN_EXEC, g_app_info_get_executable (app),
- COLUMN_HEADING, FALSE,
- COLUMN_RECOMMENDED, recommended,
- COLUMN_FALLBACK, fallback,
- -1);
+ COLUMN_APP_INFO, app,
+ COLUMN_GICON, icon,
+ COLUMN_NAME, g_app_info_get_name (app),
+ COLUMN_DESC, app_string,
+ COLUMN_EXEC, g_app_info_get_executable (app),
+ COLUMN_HEADING, FALSE,
+ COLUMN_RECOMMENDED, recommended,
+ COLUMN_FALLBACK, fallback,
+ -1);
retval = TRUE;
g_free (app_string);
if (unref_icon)
- g_object_unref (icon);
-
- unref_icon = FALSE;
+ g_object_unref (icon);
}
g_free (bold_string);
static void
gtk_app_chooser_add_default (GtkAppChooserWidget *self,
- GAppInfo *app)
+ GAppInfo *app)
{
GtkTreeIter iter;
GIcon *icon;
gtk_list_store_append (self->priv->program_list_store, &iter);
gtk_list_store_set (self->priv->program_list_store, &iter,
- COLUMN_HEADING_TEXT, string,
- COLUMN_HEADING, TRUE,
- COLUMN_DEFAULT, TRUE,
- -1);
+ COLUMN_HEADING_TEXT, string,
+ COLUMN_HEADING, TRUE,
+ COLUMN_DEFAULT, TRUE,
+ -1);
g_free (string);
- string = g_strdup_printf ("<b>%s</b>\n%s",
- g_app_info_get_display_name (app) != NULL ?
- g_app_info_get_display_name (app) : "",
- g_app_info_get_description (app) != NULL ?
- g_app_info_get_description (app) : "");
+ string = g_markup_printf_escaped ("%s",
+ g_app_info_get_name (app) != NULL ?
+ g_app_info_get_name (app) : "");
icon = g_app_info_get_icon (app);
if (icon == NULL)
gtk_list_store_append (self->priv->program_list_store, &iter);
gtk_list_store_set (self->priv->program_list_store, &iter,
- COLUMN_APP_INFO, app,
- COLUMN_GICON, icon,
- COLUMN_NAME, g_app_info_get_display_name (app),
- COLUMN_DESC, string,
- COLUMN_EXEC, g_app_info_get_executable (app),
- COLUMN_HEADING, FALSE,
- COLUMN_DEFAULT, TRUE,
- -1);
+ COLUMN_APP_INFO, app,
+ COLUMN_GICON, icon,
+ COLUMN_NAME, g_app_info_get_name (app),
+ COLUMN_DESC, string,
+ COLUMN_EXEC, g_app_info_get_executable (app),
+ COLUMN_HEADING, FALSE,
+ COLUMN_DEFAULT, TRUE,
+ -1);
g_free (string);
static void
add_no_applications_label (GtkAppChooserWidget *self)
{
- gchar *text = NULL, *desc;
+ gchar *text = NULL, *desc = NULL;
const gchar *string;
GtkTreeIter iter;
if (self->priv->default_text == NULL)
{
- desc = g_content_type_get_description (self->priv->content_type);
+ if (self->priv->content_type)
+ desc = g_content_type_get_description (self->priv->content_type);
+
string = text = g_strdup_printf (_("No applications available to open \"%s\""),
- desc);
+ desc);
g_free (desc);
}
else
gtk_list_store_append (self->priv->program_list_store, &iter);
gtk_list_store_set (self->priv->program_list_store, &iter,
- COLUMN_HEADING_TEXT, string,
- COLUMN_HEADING, TRUE,
- -1);
+ COLUMN_HEADING_TEXT, string,
+ COLUMN_HEADING, TRUE,
+ -1);
- g_free (text);
+ g_free (text);
}
static void
while (info == NULL)
{
gtk_tree_model_get (model, &iter,
- COLUMN_APP_INFO, &info,
- -1);
+ COLUMN_APP_INFO, &info,
+ -1);
if (info != NULL)
- break;
+ break;
if (!gtk_tree_model_iter_next (model, &iter))
- break;
+ break;
}
if (info != NULL)
static void
gtk_app_chooser_widget_real_add_items (GtkAppChooserWidget *self)
{
- GList *all_applications = NULL, *recommended_apps = NULL, *fallback_apps = NULL;
+ GList *all_applications = NULL;
+ GList *recommended_apps = NULL;
+ GList *fallback_apps = NULL;
GList *exclude_apps = NULL;
GAppInfo *default_app = NULL;
gboolean show_headings;
if (self->priv->show_all)
show_headings = FALSE;
- if (self->priv->show_default)
+ if (self->priv->show_default && self->priv->content_type)
{
default_app = g_app_info_get_default_for_type (self->priv->content_type, FALSE);
if (default_app != NULL)
- {
- gtk_app_chooser_add_default (self, default_app);
- apps_added = TRUE;
- exclude_apps = g_list_prepend (exclude_apps, default_app);
- }
+ {
+ gtk_app_chooser_add_default (self, default_app);
+ apps_added = TRUE;
+ exclude_apps = g_list_prepend (exclude_apps, default_app);
+ }
}
- if (self->priv->show_recommended || self->priv->show_all)
+#ifndef G_OS_WIN32
+ if ((self->priv->content_type && self->priv->show_recommended) || self->priv->show_all)
{
- recommended_apps = g_app_info_get_recommended_for_type (self->priv->content_type);
+ if (self->priv->content_type)
+ recommended_apps = g_app_info_get_recommended_for_type (self->priv->content_type);
apps_added |= gtk_app_chooser_widget_add_section (self, _("Recommended Applications"),
- show_headings,
- !self->priv->show_all, /* mark as recommended */
- FALSE, /* mark as fallback */
- recommended_apps, exclude_apps);
+ show_headings,
+ !self->priv->show_all, /* mark as recommended */
+ FALSE, /* mark as fallback */
+ recommended_apps, exclude_apps);
exclude_apps = g_list_concat (exclude_apps,
- g_list_copy (recommended_apps));
+ g_list_copy (recommended_apps));
}
- if (self->priv->show_fallback || self->priv->show_all)
+ if ((self->priv->content_type && self->priv->show_fallback) || self->priv->show_all)
{
- fallback_apps = g_app_info_get_fallback_for_type (self->priv->content_type);
+ if (self->priv->content_type)
+ fallback_apps = g_app_info_get_fallback_for_type (self->priv->content_type);
apps_added |= gtk_app_chooser_widget_add_section (self, _("Related Applications"),
- show_headings,
- FALSE, /* mark as recommended */
- !self->priv->show_all, /* mark as fallback */
- fallback_apps, exclude_apps);
+ show_headings,
+ FALSE, /* mark as recommended */
+ !self->priv->show_all, /* mark as fallback */
+ fallback_apps, exclude_apps);
exclude_apps = g_list_concat (exclude_apps,
- g_list_copy (fallback_apps));
+ g_list_copy (fallback_apps));
}
+#endif
if (self->priv->show_other || self->priv->show_all)
{
all_applications = g_app_info_get_all ();
apps_added |= gtk_app_chooser_widget_add_section (self, _("Other Applications"),
- show_headings,
- FALSE,
- FALSE,
- all_applications, exclude_apps);
+ show_headings,
+ FALSE,
+ FALSE,
+ all_applications, exclude_apps);
}
if (!apps_added)
/* create list store */
self->priv->program_list_store = gtk_list_store_new (NUM_COLUMNS,
- G_TYPE_APP_INFO,
- G_TYPE_ICON,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN,
- G_TYPE_STRING,
- G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN);
+ G_TYPE_APP_INFO,
+ G_TYPE_ICON,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (self->priv->program_list_store));
- gtk_tree_view_set_model (GTK_TREE_VIEW (self->priv->program_list),
- GTK_TREE_MODEL (sort));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (self->priv->program_list),
+ GTK_TREE_MODEL (sort));
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort),
- COLUMN_NAME,
- GTK_SORT_ASCENDING);
+ COLUMN_NAME,
+ GTK_SORT_ASCENDING);
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sort),
- COLUMN_NAME,
- gtk_app_chooser_sort_func,
- self, NULL);
+ COLUMN_NAME,
+ gtk_app_chooser_sort_func,
+ self, NULL);
gtk_tree_view_set_search_column (GTK_TREE_VIEW (self->priv->program_list),
- COLUMN_NAME);
+ COLUMN_NAME);
gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (self->priv->program_list),
- gtk_app_chooser_search_equal_func,
- NULL, NULL);
+ gtk_app_chooser_search_equal_func,
+ NULL, NULL);
column = gtk_tree_view_column_new ();
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
g_object_set (renderer,
- "xpad", self->priv->show_all ? 0 : 6,
- NULL);
+ "xpad", self->priv->show_all ? 0 : 6,
+ NULL);
self->priv->padding_renderer = renderer;
/* heading text renderer */
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
gtk_tree_view_column_set_attributes (column, renderer,
- "markup", COLUMN_HEADING_TEXT,
- "visible", COLUMN_HEADING,
- NULL);
+ "markup", COLUMN_HEADING_TEXT,
+ "visible", COLUMN_HEADING,
+ NULL);
g_object_set (renderer,
- "ypad", 6,
- "xpad", 0,
- "wrap-width", 350,
- "wrap-mode", PANGO_WRAP_WORD,
- NULL);
+ "ypad", 6,
+ "xpad", 0,
+ "wrap-width", 350,
+ "wrap-mode", PANGO_WRAP_WORD,
+ NULL);
/* padding renderer for non-heading cells */
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
gtk_tree_view_column_set_cell_data_func (column, renderer,
- padding_cell_renderer_func,
- NULL, NULL);
+ padding_cell_renderer_func,
+ NULL, NULL);
/* app icon renderer */
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
gtk_tree_view_column_set_attributes (column, renderer,
- "gicon", COLUMN_GICON,
- NULL);
+ "gicon", COLUMN_GICON,
+ NULL);
g_object_set (renderer,
- "stock-size", GTK_ICON_SIZE_DIALOG,
- NULL);
+ "stock-size", GTK_ICON_SIZE_MENU,
+ NULL);
/* app name renderer */
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer, TRUE);
gtk_tree_view_column_set_attributes (column, renderer,
- "markup", COLUMN_DESC,
- NULL);
+ "markup", COLUMN_DESC,
+ NULL);
g_object_set (renderer,
- "ellipsize", PANGO_ELLIPSIZE_END,
- "ellipsize-set", TRUE,
- NULL);
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "ellipsize-set", TRUE,
+ NULL);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->program_list), column);
}
static void
-gtk_app_chooser_widget_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+gtk_app_chooser_widget_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
}
static void
-gtk_app_chooser_widget_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+gtk_app_chooser_widget_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
{
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
- g_assert (self->priv->content_type != NULL);
-
if (G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->constructed != NULL)
G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->constructed (object);
{
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
- if (self->priv->selected_app_info != NULL)
- {
- g_object_unref (self->priv->selected_app_info);
- self->priv->selected_app_info = NULL;
- }
+ g_clear_object (&self->priv->selected_app_info);
G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->dispose (object);
}
g_object_class_override_property (gobject_class, PROP_CONTENT_TYPE, "content-type");
+ /**
+ * GtkAppChooserWidget:show-default:
+ *
+ * The ::show-default property determines whether the app chooser
+ * should show the default handler for the content type in a
+ * separate section. If %FALSE, the default handler is listed
+ * among the recommended applications.
+ */
pspec = g_param_spec_boolean ("show-default",
- P_("Show default app"),
- P_("Whether the widget should show the default application"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ P_("Show default app"),
+ P_("Whether the widget should show the default application"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (gobject_class, PROP_SHOW_DEFAULT, pspec);
+ /**
+ * 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.
+ */
pspec = g_param_spec_boolean ("show-recommended",
- P_("Show recommended apps"),
- P_("Whether the widget should show recommended applications"),
- TRUE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ P_("Show recommended apps"),
+ P_("Whether the widget should show recommended applications"),
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (gobject_class, PROP_SHOW_RECOMMENDED, pspec);
+ /**
+ * GtkAppChooserWidget:show-fallback:
+ *
+ * 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"),
- P_("Whether the widget should show fallback applications"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ P_("Show fallback apps"),
+ P_("Whether the widget should show fallback applications"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (gobject_class, PROP_SHOW_FALLBACK, pspec);
+ /**
+ * GtkAppChooserWidget:show-other:
+ *
+ * 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"),
- P_("Whether the widget should show other applications"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ P_("Show other apps"),
+ P_("Whether the widget should show other applications"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (gobject_class, PROP_SHOW_OTHER, pspec);
+ /**
+ * 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.
+ */
pspec = g_param_spec_boolean ("show-all",
- P_("Show all apps"),
- P_("Whether the widget should show all applications"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ P_("Show all apps"),
+ P_("Whether the widget should show all applications"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (gobject_class, PROP_SHOW_ALL, pspec);
+ /**
+ * 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.
+ * See also gtk_app_chooser_widget_set_default_text().
+ */
pspec = g_param_spec_string ("default-text",
- P_("Widget's default text"),
- P_("The default text appearing when there are no applications"),
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ P_("Widget's default text"),
+ P_("The default text appearing when there are no applications"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (gobject_class, PROP_DEFAULT_TEXT, pspec);
+ /**
+ * GtkAppChooserWidget::application-selected:
+ * @self: the object which received the signal
+ * @application: the selected #GAppInfo
+ *
+ * Emitted when an application item is selected from the widget's list.
+ */
signals[SIGNAL_APPLICATION_SELECTED] =
g_signal_new ("application-selected",
- GTK_TYPE_APP_CHOOSER_WIDGET,
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GtkAppChooserWidgetClass, application_selected),
- NULL, NULL,
- _gtk_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1, G_TYPE_APP_INFO);
-
+ GTK_TYPE_APP_CHOOSER_WIDGET,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkAppChooserWidgetClass, application_selected),
+ NULL, NULL,
+ _gtk_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1, G_TYPE_APP_INFO);
+
+ /**
+ * GtkAppChooserWidget::application-activated:
+ * @self: the object which received the signal
+ * @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.
+ */
signals[SIGNAL_APPLICATION_ACTIVATED] =
g_signal_new ("application-activated",
- GTK_TYPE_APP_CHOOSER_WIDGET,
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GtkAppChooserWidgetClass, application_activated),
- NULL, NULL,
- _gtk_marshal_VOID__OBJECT,
- G_TYPE_NONE,
- 1, G_TYPE_APP_INFO);
+ GTK_TYPE_APP_CHOOSER_WIDGET,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkAppChooserWidgetClass, application_activated),
+ NULL, NULL,
+ _gtk_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1, G_TYPE_APP_INFO);
+
+ /**
+ * GtkAppChooserWidget::populate-popup:
+ * @self: the object which received the signal
+ * @menu: the #GtkMenu to populate
+ * @application: the current #GAppInfo
+ *
+ * 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.
+ */
+ signals[SIGNAL_POPULATE_POPUP] =
+ g_signal_new ("populate-popup",
+ GTK_TYPE_APP_CHOOSER_WIDGET,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkAppChooserWidgetClass, populate_popup),
+ NULL, NULL,
+ _gtk_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE,
+ 2, GTK_TYPE_MENU, G_TYPE_APP_INFO);
g_type_class_add_private (klass, sizeof (GtkAppChooserWidgetPrivate));
}
GtkTreeSelection *selection;
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_APP_CHOOSER_WIDGET,
- GtkAppChooserWidgetPrivate);
+ GtkAppChooserWidgetPrivate);
gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL);
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_size_request (scrolled_window, 400, 300);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
- GTK_SHADOW_IN);
+ GTK_SHADOW_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
- GTK_POLICY_NEVER,
- GTK_POLICY_AUTOMATIC);
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
gtk_widget_show (scrolled_window);
self->priv->program_list = gtk_tree_view_new ();
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (self->priv->program_list),
- FALSE);
+ FALSE);
gtk_container_add (GTK_CONTAINER (scrolled_window), self->priv->program_list);
gtk_box_pack_start (GTK_BOX (self), scrolled_window, TRUE, TRUE, 0);
gtk_widget_show (self->priv->program_list);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->program_list));
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
gtk_tree_selection_set_select_function (selection, gtk_app_chooser_selection_func,
- self, NULL);
+ self, NULL);
g_signal_connect_swapped (selection, "changed",
- G_CALLBACK (refresh_and_emit_app_selected),
- self);
+ G_CALLBACK (refresh_and_emit_app_selected),
+ self);
g_signal_connect (self->priv->program_list, "row-activated",
- G_CALLBACK (program_list_selection_activated),
- self);
+ G_CALLBACK (program_list_selection_activated),
+ self);
+ g_signal_connect (self->priv->program_list, "button-press-event",
+ G_CALLBACK (widget_button_press_event_cb),
+ self);
}
static GAppInfo *
/* don't add additional xpad if we don't have headings */
g_object_set (self->priv->padding_renderer,
- "visible", !self->priv->show_all,
- NULL);
+ "visible", !self->priv->show_all,
+ NULL);
gtk_app_chooser_widget_real_add_items (self);
}
iface->refresh = gtk_app_chooser_widget_refresh;
}
+/**
+ * gtk_app_chooser_widget_new:
+ * @content_type: the content type to show applications for
+ *
+ * Creates a new #GtkAppChooserWidget for applications
+ * that can handle content of the given type.
+ *
+ * Returns: a newly created #GtkAppChooserWidget
+ *
+ * Since: 3.0
+ */
GtkWidget *
gtk_app_chooser_widget_new (const gchar *content_type)
{
return g_object_new (GTK_TYPE_APP_CHOOSER_WIDGET,
- "content-type", content_type,
- NULL);
+ "content-type", content_type,
+ NULL);
}
+/**
+ * gtk_app_chooser_widget_set_show_default:
+ * @self: a #GtkAppChooserWidget
+ * @setting: the new value for #GtkAppChooserWidget:show-default
+ *
+ * Sets whether the app chooser should show the default handler
+ * for the content type in a separate section.
+ *
+ * Since: 3.0
+ */
void
gtk_app_chooser_widget_set_show_default (GtkAppChooserWidget *self,
- gboolean setting)
+ gboolean setting)
{
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
}
}
+/**
+ * gtk_app_chooser_widget_get_show_default:
+ * @self: a #GtkAppChooserWidget
+ *
+ * Returns the current value of the #GtkAppChooserWidget:show-default
+ * property.
+ *
+ * Returns: the value of #GtkAppChooserWidget:show-default
+ *
+ * Since: 3.0
+ */
gboolean
gtk_app_chooser_widget_get_show_default (GtkAppChooserWidget *self)
{
return self->priv->show_default;
}
+/**
+ * gtk_app_chooser_widget_set_show_recommended:
+ * @self: a #GtkAppChooserWidget
+ * @setting: the new value for #GtkAppChooserWidget:show-recommended
+ *
+ * Sets whether the app chooser should show recommended applications
+ * for the content type in a separate section.
+ *
+ * Since: 3.0
+ */
void
gtk_app_chooser_widget_set_show_recommended (GtkAppChooserWidget *self,
- gboolean setting)
+ gboolean setting)
{
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
}
}
+/**
+ * gtk_app_chooser_widget_get_show_recommended:
+ * @self: a #GtkAppChooserWidget
+ *
+ * Returns the current value of the #GtkAppChooserWidget:show-recommended
+ * property.
+ *
+ * Returns: the value of #GtkAppChooserWidget:show-recommended
+ *
+ * Since: 3.0
+ */
gboolean
gtk_app_chooser_widget_get_show_recommended (GtkAppChooserWidget *self)
{
return self->priv->show_recommended;
}
+/**
+ * gtk_app_chooser_widget_set_show_fallback:
+ * @self: a #GtkAppChooserWidget
+ * @setting: the new value for #GtkAppChooserWidget:show-fallback
+ *
+ * Sets whether the app chooser should show related applications
+ * for the content type in a separate section.
+ *
+ * Since: 3.0
+ */
void
gtk_app_chooser_widget_set_show_fallback (GtkAppChooserWidget *self,
- gboolean setting)
+ gboolean setting)
{
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
}
}
+/**
+ * gtk_app_chooser_widget_get_show_fallback:
+ * @self: a #GtkAppChooserWidget
+ *
+ * Returns the current value of the #GtkAppChooserWidget:show-fallback
+ * property.
+ *
+ * Returns: the value of #GtkAppChooserWidget:show-fallback
+ *
+ * Since: 3.0
+ */
gboolean
gtk_app_chooser_widget_get_show_fallback (GtkAppChooserWidget *self)
{
return self->priv->show_fallback;
}
+/**
+ * gtk_app_chooser_widget_set_show_other:
+ * @self: a #GtkAppChooserWidget
+ * @setting: the new value for #GtkAppChooserWidget:show-other
+ *
+ * Sets whether the app chooser should show applications
+ * which are unrelated to the content type.
+ *
+ * Since: 3.0
+ */
void
gtk_app_chooser_widget_set_show_other (GtkAppChooserWidget *self,
- gboolean setting)
+ gboolean setting)
{
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
}
}
-gboolean gtk_app_chooser_widget_get_show_other (GtkAppChooserWidget *self)
+/**
+ * gtk_app_chooser_widget_get_show_other:
+ * @self: a #GtkAppChooserWidget
+ *
+ * Returns the current value of the #GtkAppChooserWidget:show-other
+ * property.
+ *
+ * Returns: the value of #GtkAppChooserWidget:show-other
+ *
+ * Since: 3.0
+ */
+gboolean
+gtk_app_chooser_widget_get_show_other (GtkAppChooserWidget *self)
{
g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
return self->priv->show_other;
}
+/**
+ * gtk_app_chooser_widget_set_show_all:
+ * @self: a #GtkAppChooserWidget
+ * @setting: the new value for #GtkAppChooserWidget:show-all
+ *
+ * Sets whether the app chooser should show all applications
+ * in a flat list.
+ *
+ * Since: 3.0
+ */
void
gtk_app_chooser_widget_set_show_all (GtkAppChooserWidget *self,
- gboolean setting)
+ gboolean setting)
{
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
}
}
+/**
+ * gtk_app_chooser_widget_get_show_all:
+ * @self: a #GtkAppChooserWidget
+ *
+ * Returns the current value of the #GtkAppChooserWidget:show-all
+ * property.
+ *
+ * Returns: the value of #GtkAppChooserWidget:show-all
+ *
+ * Since: 3.0
+ */
gboolean
gtk_app_chooser_widget_get_show_all (GtkAppChooserWidget *self)
{
g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
- return self->priv->show_all;
+ return self->priv->show_all;
}
+/**
+ * gtk_app_chooser_widget_set_default_text:
+ * @self: a #GtkAppChooserWidget
+ * @text: the new value for #GtkAppChooserWidget:default-text
+ *
+ * Sets the text that is shown if there are not applications
+ * that can handle the content type.
+ */
void
gtk_app_chooser_widget_set_default_text (GtkAppChooserWidget *self,
- const gchar *text)
+ const gchar *text)
{
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
}
}
+/**
+ * gtk_app_chooser_widget_get_default_text:
+ * @self: a #GtkAppChooserWidget
+ *
+ * Returns the text that is shown if there are not applications
+ * that can handle the content type.
+ *
+ * Returns: the value of #GtkAppChooserWidget:default-text
+ *
+ * Since: 3.0
+ */
const gchar *
gtk_app_chooser_widget_get_default_text (GtkAppChooserWidget *self)
{