forked from AuroraMiddleware/gtk
a546ae32d7
Those property features don't seem to be in use anywhere. They are redundant since the docs cover the same information and more. They also created unnecessary translation work. Closes #4904
1381 lines
42 KiB
C
1381 lines
42 KiB
C
/*
|
|
* gtkappchooserwidget.c: an app-chooser widget
|
|
*
|
|
* Copyright (C) 2004 Novell, Inc.
|
|
* Copyright (C) 2007, 2010 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* 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 "gtkappchooserwidget.h"
|
|
|
|
#include "gtkintl.h"
|
|
#include "gtkmarshalers.h"
|
|
#include "gtkappchooserwidget.h"
|
|
#include "gtkappchooserprivate.h"
|
|
#include "gtkliststore.h"
|
|
#include "gtktreeview.h"
|
|
#include "gtktreeselection.h"
|
|
#include "gtktreemodelsort.h"
|
|
#include "gtkorientable.h"
|
|
#include "gtkscrolledwindow.h"
|
|
#include "gtklabel.h"
|
|
#include "gtkgestureclick.h"
|
|
#include "gtkwidgetprivate.h"
|
|
|
|
#include <string.h>
|
|
#include <glib/gi18n-lib.h>
|
|
#include <gio/gio.h>
|
|
|
|
/**
|
|
* GtkAppChooserWidget:
|
|
*
|
|
* `GtkAppChooserWidget` is a widget for selecting applications.
|
|
*
|
|
* It is the main building block for [class@Gtk.AppChooserDialog].
|
|
* 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
|
|
* [property@Gtk.AppChooserWidget:show-default],
|
|
* [property@Gtk.AppChooserWidget:show-recommended],
|
|
* [property@Gtk.AppChooserWidget:show-fallback],
|
|
* [property@Gtk.AppChooserWidget:show-other] and
|
|
* [property@Gtk.AppChooserWidget:show-all] properties. See the
|
|
* [iface@Gtk.AppChooser] documentation for more information about these
|
|
* groups of applications.
|
|
*
|
|
* To keep track of the selected application, use the
|
|
* [signal@Gtk.AppChooserWidget::application-selected] and
|
|
* [signal@Gtk.AppChooserWidget::application-activated] signals.
|
|
*
|
|
* # CSS nodes
|
|
*
|
|
* `GtkAppChooserWidget` has a single CSS node with name appchooser.
|
|
*/
|
|
|
|
typedef struct _GtkAppChooserWidgetClass GtkAppChooserWidgetClass;
|
|
|
|
struct _GtkAppChooserWidget {
|
|
GtkWidget parent_instance;
|
|
|
|
GAppInfo *selected_app_info;
|
|
|
|
GtkWidget *overlay;
|
|
|
|
char *content_type;
|
|
char *default_text;
|
|
|
|
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;
|
|
GtkWidget *no_apps_label;
|
|
GtkWidget *no_apps;
|
|
|
|
GtkTreeViewColumn *column;
|
|
GtkCellRenderer *padding_renderer;
|
|
GtkCellRenderer *secondary_padding;
|
|
|
|
GAppInfoMonitor *monitor;
|
|
|
|
GtkWidget *popup_menu;
|
|
};
|
|
|
|
struct _GtkAppChooserWidgetClass {
|
|
GtkWidgetClass parent_class;
|
|
|
|
void (* application_selected) (GtkAppChooserWidget *self,
|
|
GAppInfo *app_info);
|
|
|
|
void (* application_activated) (GtkAppChooserWidget *self,
|
|
GAppInfo *app_info);
|
|
};
|
|
|
|
enum {
|
|
COLUMN_APP_INFO,
|
|
COLUMN_GICON,
|
|
COLUMN_NAME,
|
|
COLUMN_DESC,
|
|
COLUMN_EXEC,
|
|
COLUMN_DEFAULT,
|
|
COLUMN_HEADING,
|
|
COLUMN_HEADING_TEXT,
|
|
COLUMN_RECOMMENDED,
|
|
COLUMN_FALLBACK,
|
|
NUM_COLUMNS
|
|
};
|
|
|
|
|
|
enum {
|
|
PROP_CONTENT_TYPE = 1,
|
|
PROP_GFILE,
|
|
PROP_SHOW_DEFAULT,
|
|
PROP_SHOW_RECOMMENDED,
|
|
PROP_SHOW_FALLBACK,
|
|
PROP_SHOW_OTHER,
|
|
PROP_SHOW_ALL,
|
|
PROP_DEFAULT_TEXT,
|
|
N_PROPERTIES
|
|
};
|
|
|
|
enum {
|
|
SIGNAL_APPLICATION_SELECTED,
|
|
SIGNAL_APPLICATION_ACTIVATED,
|
|
N_SIGNALS
|
|
};
|
|
|
|
static guint signals[N_SIGNALS] = { 0, };
|
|
|
|
static void gtk_app_chooser_widget_iface_init (GtkAppChooserIface *iface);
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GtkAppChooserWidget, gtk_app_chooser_widget, GTK_TYPE_WIDGET,
|
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER,
|
|
gtk_app_chooser_widget_iface_init));
|
|
|
|
static void
|
|
refresh_and_emit_app_selected (GtkAppChooserWidget *self,
|
|
GtkTreeSelection *selection)
|
|
{
|
|
GtkTreeModel *model;
|
|
GtkTreeIter iter;
|
|
GAppInfo *info = NULL;
|
|
gboolean should_emit = FALSE;
|
|
|
|
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
|
gtk_tree_model_get (model, &iter, COLUMN_APP_INFO, &info, -1);
|
|
|
|
if (info == NULL)
|
|
return;
|
|
|
|
if (self->selected_app_info)
|
|
{
|
|
if (!g_app_info_equal (self->selected_app_info, info))
|
|
{
|
|
should_emit = TRUE;
|
|
g_set_object (&self->selected_app_info, info);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
should_emit = TRUE;
|
|
g_set_object (&self->selected_app_info, info);
|
|
}
|
|
|
|
g_object_unref (info);
|
|
|
|
if (should_emit)
|
|
g_signal_emit (self, signals[SIGNAL_APPLICATION_SELECTED], 0,
|
|
self->selected_app_info);
|
|
}
|
|
|
|
static gboolean
|
|
path_is_heading (GtkTreeView *view,
|
|
GtkTreePath *path)
|
|
{
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *model;
|
|
gboolean res;
|
|
|
|
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);
|
|
|
|
return res;
|
|
}
|
|
|
|
static void
|
|
program_list_selection_activated (GtkTreeView *view,
|
|
GtkTreePath *path,
|
|
GtkTreeViewColumn *column,
|
|
gpointer user_data)
|
|
{
|
|
GtkAppChooserWidget *self = user_data;
|
|
GtkTreeSelection *selection;
|
|
|
|
if (path_is_heading (view, path))
|
|
return;
|
|
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->program_list));
|
|
|
|
refresh_and_emit_app_selected (self, selection);
|
|
|
|
g_signal_emit (self, signals[SIGNAL_APPLICATION_ACTIVATED], 0,
|
|
self->selected_app_info);
|
|
}
|
|
|
|
static gboolean
|
|
gtk_app_chooser_search_equal_func (GtkTreeModel *model,
|
|
int column,
|
|
const char *key,
|
|
GtkTreeIter *iter,
|
|
gpointer user_data)
|
|
{
|
|
char *name;
|
|
char *exec_name;
|
|
gboolean ret;
|
|
|
|
if (key != NULL)
|
|
{
|
|
ret = TRUE;
|
|
|
|
gtk_tree_model_get (model, iter,
|
|
COLUMN_NAME, &name,
|
|
COLUMN_EXEC, &exec_name,
|
|
-1);
|
|
|
|
if ((name != NULL && g_str_match_string (key, name, TRUE)) ||
|
|
(exec_name != NULL && g_str_match_string (key, exec_name, FALSE)))
|
|
ret = FALSE;
|
|
|
|
g_free (name);
|
|
g_free (exec_name);
|
|
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
static int
|
|
gtk_app_chooser_sort_func (GtkTreeModel *model,
|
|
GtkTreeIter *a,
|
|
GtkTreeIter *b,
|
|
gpointer user_data)
|
|
{
|
|
gboolean a_recommended, b_recommended;
|
|
gboolean a_fallback, b_fallback;
|
|
gboolean a_heading, b_heading;
|
|
gboolean a_default, b_default;
|
|
char *a_name, *b_name, *a_casefold, *b_casefold;
|
|
int retval = 0;
|
|
|
|
/* this returns:
|
|
* - <0 if a should show before b
|
|
* - =0 if a is the same as b
|
|
* - >0 if a should show after b
|
|
*/
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
/* the default one always wins */
|
|
if (a_default && !b_default)
|
|
{
|
|
retval = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (b_default && !a_default)
|
|
{
|
|
retval = 1;
|
|
goto out;
|
|
}
|
|
|
|
/* the recommended one always wins */
|
|
if (a_recommended && !b_recommended)
|
|
{
|
|
retval = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (b_recommended && !a_recommended)
|
|
{
|
|
retval = 1;
|
|
goto out;
|
|
}
|
|
|
|
/* the recommended one always wins */
|
|
if (a_fallback && !b_fallback)
|
|
{
|
|
retval = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (b_fallback && !a_fallback)
|
|
{
|
|
retval = 1;
|
|
goto out;
|
|
}
|
|
|
|
/* they're both recommended/fallback or not, so if one is a heading, wins */
|
|
if (a_heading)
|
|
{
|
|
retval = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (b_heading)
|
|
{
|
|
retval = 1;
|
|
goto out;
|
|
}
|
|
|
|
/* don't order by name recommended applications, but use GLib's ordering */
|
|
if (!a_recommended)
|
|
{
|
|
a_casefold = a_name != NULL ?
|
|
g_utf8_casefold (a_name, -1) : NULL;
|
|
b_casefold = b_name != NULL ?
|
|
g_utf8_casefold (b_name, -1) : NULL;
|
|
|
|
retval = g_strcmp0 (a_casefold, b_casefold);
|
|
|
|
g_free (a_casefold);
|
|
g_free (b_casefold);
|
|
}
|
|
|
|
out:
|
|
g_free (a_name);
|
|
g_free (b_name);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static void
|
|
padding_cell_renderer_func (GtkTreeViewColumn *column,
|
|
GtkCellRenderer *cell,
|
|
GtkTreeModel *model,
|
|
GtkTreeIter *iter,
|
|
gpointer user_data)
|
|
{
|
|
gboolean heading;
|
|
|
|
gtk_tree_model_get (model, iter,
|
|
COLUMN_HEADING, &heading,
|
|
-1);
|
|
if (heading)
|
|
g_object_set (cell,
|
|
"visible", FALSE,
|
|
"xpad", 0,
|
|
"ypad", 0,
|
|
NULL);
|
|
else
|
|
g_object_set (cell,
|
|
"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)
|
|
{
|
|
GtkTreeIter iter;
|
|
gboolean heading;
|
|
|
|
gtk_tree_model_get_iter (model, &iter, path);
|
|
gtk_tree_model_get (model, &iter,
|
|
COLUMN_HEADING, &heading,
|
|
-1);
|
|
|
|
return !heading;
|
|
}
|
|
|
|
static int
|
|
compare_apps_func (gconstpointer a,
|
|
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 char *heading_title,
|
|
gboolean show_headings,
|
|
gboolean recommended,
|
|
gboolean fallback,
|
|
GList *applications,
|
|
GList *exclude_apps)
|
|
{
|
|
gboolean heading_added, unref_icon;
|
|
GtkTreeIter iter;
|
|
GAppInfo *app;
|
|
char *app_string, *bold_string;
|
|
GIcon *icon;
|
|
GList *l;
|
|
gboolean retval;
|
|
|
|
retval = FALSE;
|
|
heading_added = FALSE;
|
|
bold_string = g_strdup_printf ("<b>%s</b>", heading_title);
|
|
|
|
for (l = applications; l != NULL; l = l->next)
|
|
{
|
|
app = l->data;
|
|
|
|
if (self->content_type != NULL &&
|
|
!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->program_list_store, &iter);
|
|
gtk_list_store_set (self->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;
|
|
}
|
|
|
|
gtk_list_store_append (self->program_list_store, &iter);
|
|
gtk_list_store_set (self->program_list_store, &iter,
|
|
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);
|
|
}
|
|
|
|
g_free (bold_string);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
static void
|
|
gtk_app_chooser_add_default (GtkAppChooserWidget *self,
|
|
GAppInfo *app)
|
|
{
|
|
GtkTreeIter iter;
|
|
GIcon *icon;
|
|
char *string;
|
|
gboolean unref_icon;
|
|
|
|
unref_icon = FALSE;
|
|
string = g_strdup_printf ("<b>%s</b>", _("Default Application"));
|
|
|
|
gtk_list_store_append (self->program_list_store, &iter);
|
|
gtk_list_store_set (self->program_list_store, &iter,
|
|
COLUMN_HEADING_TEXT, string,
|
|
COLUMN_HEADING, TRUE,
|
|
COLUMN_DEFAULT, TRUE,
|
|
-1);
|
|
|
|
g_free (string);
|
|
|
|
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)
|
|
{
|
|
icon = g_themed_icon_new ("application-x-executable");
|
|
unref_icon = TRUE;
|
|
}
|
|
|
|
gtk_list_store_append (self->program_list_store, &iter);
|
|
gtk_list_store_set (self->program_list_store, &iter,
|
|
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);
|
|
|
|
if (unref_icon)
|
|
g_object_unref (icon);
|
|
}
|
|
|
|
static void
|
|
update_no_applications_label (GtkAppChooserWidget *self)
|
|
{
|
|
char *text = NULL, *desc = NULL;
|
|
const char *string;
|
|
|
|
if (self->default_text == NULL)
|
|
{
|
|
if (self->content_type)
|
|
desc = g_content_type_get_description (self->content_type);
|
|
|
|
string = text = g_strdup_printf (_("No applications found for “%s”."), desc);
|
|
g_free (desc);
|
|
}
|
|
else
|
|
{
|
|
string = self->default_text;
|
|
}
|
|
|
|
gtk_label_set_text (GTK_LABEL (self->no_apps_label), string);
|
|
|
|
g_free (text);
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_select_first (GtkAppChooserWidget *self)
|
|
{
|
|
GtkTreeIter iter;
|
|
GAppInfo *info = NULL;
|
|
GtkTreeModel *model;
|
|
|
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->program_list));
|
|
if (!gtk_tree_model_get_iter_first (model, &iter))
|
|
return;
|
|
|
|
while (info == NULL)
|
|
{
|
|
gtk_tree_model_get (model, &iter,
|
|
COLUMN_APP_INFO, &info,
|
|
-1);
|
|
|
|
if (info != NULL)
|
|
break;
|
|
|
|
if (!gtk_tree_model_iter_next (model, &iter))
|
|
break;
|
|
}
|
|
|
|
if (info != NULL)
|
|
{
|
|
GtkTreeSelection *selection;
|
|
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->program_list));
|
|
gtk_tree_selection_select_iter (selection, &iter);
|
|
|
|
g_object_unref (info);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_real_add_items (GtkAppChooserWidget *self)
|
|
{
|
|
GList *all_applications = NULL;
|
|
GList *recommended_apps = NULL;
|
|
GList *fallback_apps = NULL;
|
|
GList *exclude_apps = NULL;
|
|
GAppInfo *default_app = NULL;
|
|
gboolean show_headings;
|
|
gboolean apps_added;
|
|
|
|
show_headings = TRUE;
|
|
apps_added = FALSE;
|
|
|
|
if (self->show_all)
|
|
show_headings = FALSE;
|
|
|
|
if (self->show_default && self->content_type)
|
|
{
|
|
default_app = g_app_info_get_default_for_type (self->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);
|
|
}
|
|
}
|
|
|
|
#ifndef G_OS_WIN32
|
|
if ((self->content_type && self->show_recommended) || self->show_all)
|
|
{
|
|
if (self->content_type)
|
|
recommended_apps = g_app_info_get_recommended_for_type (self->content_type);
|
|
|
|
apps_added |= gtk_app_chooser_widget_add_section (self, _("Recommended Applications"),
|
|
show_headings,
|
|
!self->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));
|
|
}
|
|
|
|
if ((self->content_type && self->show_fallback) || self->show_all)
|
|
{
|
|
if (self->content_type)
|
|
fallback_apps = g_app_info_get_fallback_for_type (self->content_type);
|
|
|
|
apps_added |= gtk_app_chooser_widget_add_section (self, _("Related Applications"),
|
|
show_headings,
|
|
FALSE, /* mark as recommended */
|
|
!self->show_all, /* mark as fallback */
|
|
fallback_apps, exclude_apps);
|
|
exclude_apps = g_list_concat (exclude_apps,
|
|
g_list_copy (fallback_apps));
|
|
}
|
|
#endif
|
|
|
|
if (self->show_other || self->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);
|
|
}
|
|
|
|
if (!apps_added)
|
|
update_no_applications_label (self);
|
|
|
|
gtk_widget_set_visible (self->no_apps, !apps_added);
|
|
|
|
gtk_app_chooser_widget_select_first (self);
|
|
|
|
if (default_app != NULL)
|
|
g_object_unref (default_app);
|
|
|
|
g_list_free_full (all_applications, g_object_unref);
|
|
g_list_free_full (recommended_apps, g_object_unref);
|
|
g_list_free_full (fallback_apps, g_object_unref);
|
|
g_list_free (exclude_apps);
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_initialize_items (GtkAppChooserWidget *self)
|
|
{
|
|
/* initial padding */
|
|
g_object_set (self->padding_renderer,
|
|
"xpad", self->show_all ? 0 : 6,
|
|
NULL);
|
|
|
|
/* populate the widget */
|
|
gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
|
|
}
|
|
|
|
static void
|
|
app_info_changed (GAppInfoMonitor *monitor,
|
|
GtkAppChooserWidget *self)
|
|
{
|
|
gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_CONTENT_TYPE:
|
|
self->content_type = g_value_dup_string (value);
|
|
break;
|
|
case PROP_SHOW_DEFAULT:
|
|
gtk_app_chooser_widget_set_show_default (self, g_value_get_boolean (value));
|
|
break;
|
|
case PROP_SHOW_RECOMMENDED:
|
|
gtk_app_chooser_widget_set_show_recommended (self, g_value_get_boolean (value));
|
|
break;
|
|
case PROP_SHOW_FALLBACK:
|
|
gtk_app_chooser_widget_set_show_fallback (self, g_value_get_boolean (value));
|
|
break;
|
|
case PROP_SHOW_OTHER:
|
|
gtk_app_chooser_widget_set_show_other (self, g_value_get_boolean (value));
|
|
break;
|
|
case PROP_SHOW_ALL:
|
|
gtk_app_chooser_widget_set_show_all (self, g_value_get_boolean (value));
|
|
break;
|
|
case PROP_DEFAULT_TEXT:
|
|
gtk_app_chooser_widget_set_default_text (self, g_value_get_string (value));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_CONTENT_TYPE:
|
|
g_value_set_string (value, self->content_type);
|
|
break;
|
|
case PROP_SHOW_DEFAULT:
|
|
g_value_set_boolean (value, self->show_default);
|
|
break;
|
|
case PROP_SHOW_RECOMMENDED:
|
|
g_value_set_boolean (value, self->show_recommended);
|
|
break;
|
|
case PROP_SHOW_FALLBACK:
|
|
g_value_set_boolean (value, self->show_fallback);
|
|
break;
|
|
case PROP_SHOW_OTHER:
|
|
g_value_set_boolean (value, self->show_other);
|
|
break;
|
|
case PROP_SHOW_ALL:
|
|
g_value_set_boolean (value, self->show_all);
|
|
break;
|
|
case PROP_DEFAULT_TEXT:
|
|
g_value_set_string (value, self->default_text);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_constructed (GObject *object)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
|
|
|
|
if (G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->constructed != NULL)
|
|
G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->constructed (object);
|
|
|
|
gtk_app_chooser_widget_initialize_items (self);
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_finalize (GObject *object)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
|
|
|
|
g_free (self->content_type);
|
|
g_free (self->default_text);
|
|
g_signal_handlers_disconnect_by_func (self->monitor, app_info_changed, self);
|
|
g_object_unref (self->monitor);
|
|
|
|
G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_dispose (GObject *object)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
|
|
|
|
g_clear_object (&self->selected_app_info);
|
|
|
|
if (self->overlay)
|
|
{
|
|
gtk_widget_unparent (self->overlay);
|
|
self->overlay = NULL;
|
|
}
|
|
|
|
G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_measure (GtkWidget *widget,
|
|
GtkOrientation orientation,
|
|
int for_size,
|
|
int *minimum,
|
|
int *natural,
|
|
int *minimum_baseline,
|
|
int *natural_baseline)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (widget);
|
|
|
|
gtk_widget_measure (self->overlay, orientation, for_size,
|
|
minimum, natural,
|
|
minimum_baseline, natural_baseline);
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_snapshot (GtkWidget *widget,
|
|
GtkSnapshot *snapshot)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (widget);
|
|
|
|
gtk_widget_snapshot_child (widget, self->overlay, snapshot);
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_size_allocate (GtkWidget *widget,
|
|
int width,
|
|
int height,
|
|
int baseline)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (widget);
|
|
|
|
GTK_WIDGET_CLASS (gtk_app_chooser_widget_parent_class)->size_allocate (widget, width, height, baseline);
|
|
|
|
gtk_widget_size_allocate (self->overlay,
|
|
&(GtkAllocation) {
|
|
0, 0,
|
|
width, height
|
|
},baseline);
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass)
|
|
{
|
|
GtkWidgetClass *widget_class;
|
|
GObjectClass *gobject_class;
|
|
GParamSpec *pspec;
|
|
|
|
gobject_class = G_OBJECT_CLASS (klass);
|
|
gobject_class->dispose = gtk_app_chooser_widget_dispose;
|
|
gobject_class->finalize = gtk_app_chooser_widget_finalize;
|
|
gobject_class->set_property = gtk_app_chooser_widget_set_property;
|
|
gobject_class->get_property = gtk_app_chooser_widget_get_property;
|
|
gobject_class->constructed = gtk_app_chooser_widget_constructed;
|
|
|
|
widget_class = GTK_WIDGET_CLASS (klass);
|
|
widget_class->measure = gtk_app_chooser_widget_measure;
|
|
widget_class->size_allocate = gtk_app_chooser_widget_size_allocate;
|
|
widget_class->snapshot = gtk_app_chooser_widget_snapshot;
|
|
|
|
g_object_class_override_property (gobject_class, PROP_CONTENT_TYPE, "content-type");
|
|
|
|
/**
|
|
* GtkAppChooserWidget:show-default: (attributes org.gtk.Property.get=gtk_app_chooser_widget_get_show_default org.gtk.Property.set=gtk_app_chooser_widget_set_show_default)
|
|
*
|
|
* 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", NULL, NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
|
g_object_class_install_property (gobject_class, PROP_SHOW_DEFAULT, pspec);
|
|
|
|
/**
|
|
* GtkAppChooserWidget:show-recommended: (attributes org.gtk.Property.get=gtk_app_chooser_widget_get_show_recommended org.gtk.Property.set=gtk_app_chooser_widget_set_show_recommended)
|
|
*
|
|
* 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", NULL, NULL,
|
|
TRUE,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
|
g_object_class_install_property (gobject_class, PROP_SHOW_RECOMMENDED, pspec);
|
|
|
|
/**
|
|
* GtkAppChooserWidget:show-fallback: (attributes org.gtk.Property.get=gtk_app_chooser_widget_get_show_fallback org.gtk.Property.set=gtk_app_chooser_widget_set_show_fallback)
|
|
*
|
|
* 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", NULL, NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
|
g_object_class_install_property (gobject_class, PROP_SHOW_FALLBACK, pspec);
|
|
|
|
/**
|
|
* GtkAppChooserWidget:show-other: (attributes org.gtk.Property.get=gtk_app_chooser_widget_get_show_other org.gtk.Property.set=gtk_app_chooser_widget_set_show_other)
|
|
*
|
|
* Determines whether the app chooser should show a section
|
|
* for other applications.
|
|
*/
|
|
pspec = g_param_spec_boolean ("show-other", NULL, NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
|
g_object_class_install_property (gobject_class, PROP_SHOW_OTHER, pspec);
|
|
|
|
/**
|
|
* GtkAppChooserWidget:show-all: (attributes org.gtk.Property.get=gtk_app_chooser_widget_get_show_all org.gtk.Property.set=gtk_app_chooser_widget_set_show_all)
|
|
*
|
|
* If %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", NULL, NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
|
g_object_class_install_property (gobject_class, PROP_SHOW_ALL, pspec);
|
|
|
|
/**
|
|
* GtkAppChooserWidget:default-text: (attributes org.gtk.Property.get=gtk_app_chooser_widget_get_default_text org.gtk.Property.set=gtk_app_chooser_widget_set_default_text)
|
|
*
|
|
* The text that appears in the widget when there are no applications
|
|
* for the given content type.
|
|
*/
|
|
pspec = g_param_spec_string ("default-text", NULL, NULL,
|
|
NULL,
|
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
|
|
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 (I_("application-selected"),
|
|
GTK_TYPE_APP_CHOOSER_WIDGET,
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (GtkAppChooserWidgetClass, application_selected),
|
|
NULL, NULL,
|
|
NULL,
|
|
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 (I_("application-activated"),
|
|
GTK_TYPE_APP_CHOOSER_WIDGET,
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (GtkAppChooserWidgetClass, application_activated),
|
|
NULL, NULL,
|
|
NULL,
|
|
G_TYPE_NONE,
|
|
1, G_TYPE_APP_INFO);
|
|
|
|
/* Bind class to template
|
|
*/
|
|
gtk_widget_class_set_template_from_resource (widget_class,
|
|
"/org/gtk/libgtk/ui/gtkappchooserwidget.ui");
|
|
gtk_widget_class_bind_template_child (widget_class, GtkAppChooserWidget, program_list);
|
|
gtk_widget_class_bind_template_child (widget_class, GtkAppChooserWidget, program_list_store);
|
|
gtk_widget_class_bind_template_child (widget_class, GtkAppChooserWidget, column);
|
|
gtk_widget_class_bind_template_child (widget_class, GtkAppChooserWidget, padding_renderer);
|
|
gtk_widget_class_bind_template_child (widget_class, GtkAppChooserWidget, secondary_padding);
|
|
gtk_widget_class_bind_template_child (widget_class, GtkAppChooserWidget, no_apps_label);
|
|
gtk_widget_class_bind_template_child (widget_class, GtkAppChooserWidget, no_apps);
|
|
gtk_widget_class_bind_template_child (widget_class, GtkAppChooserWidget, overlay);
|
|
gtk_widget_class_bind_template_callback (widget_class, refresh_and_emit_app_selected);
|
|
gtk_widget_class_bind_template_callback (widget_class, program_list_selection_activated);
|
|
|
|
gtk_widget_class_set_css_name (widget_class, I_("appchooser"));
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_init (GtkAppChooserWidget *self)
|
|
{
|
|
GtkTreeSelection *selection;
|
|
GtkTreeModel *sort;
|
|
|
|
gtk_widget_init_template (GTK_WIDGET (self));
|
|
|
|
/* Various parts of the GtkTreeView code need custom code to setup, mostly
|
|
* because we lack signals to connect to, or properties to set.
|
|
*/
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->program_list));
|
|
gtk_tree_selection_set_select_function (selection, gtk_app_chooser_selection_func,
|
|
self, NULL);
|
|
|
|
sort = gtk_tree_view_get_model (GTK_TREE_VIEW (self->program_list));
|
|
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort),
|
|
COLUMN_NAME,
|
|
GTK_SORT_ASCENDING);
|
|
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sort),
|
|
COLUMN_NAME,
|
|
gtk_app_chooser_sort_func,
|
|
self, NULL);
|
|
|
|
gtk_tree_view_set_search_column (GTK_TREE_VIEW (self->program_list), COLUMN_NAME);
|
|
gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (self->program_list),
|
|
gtk_app_chooser_search_equal_func,
|
|
NULL, NULL);
|
|
|
|
gtk_tree_view_column_set_cell_data_func (self->column,
|
|
self->secondary_padding,
|
|
padding_cell_renderer_func,
|
|
NULL, NULL);
|
|
|
|
self->monitor = g_app_info_monitor_get ();
|
|
g_signal_connect (self->monitor, "changed",
|
|
G_CALLBACK (app_info_changed), self);
|
|
}
|
|
|
|
static GAppInfo *
|
|
gtk_app_chooser_widget_get_app_info (GtkAppChooser *object)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
|
|
|
|
if (self->selected_app_info == NULL)
|
|
return NULL;
|
|
|
|
return g_object_ref (self->selected_app_info);
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_refresh (GtkAppChooser *object)
|
|
{
|
|
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
|
|
|
|
if (self->program_list_store != NULL)
|
|
{
|
|
gtk_list_store_clear (self->program_list_store);
|
|
|
|
/* don't add additional xpad if we don't have headings */
|
|
g_object_set (self->padding_renderer,
|
|
"visible", !self->show_all,
|
|
NULL);
|
|
|
|
gtk_app_chooser_widget_real_add_items (self);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_app_chooser_widget_iface_init (GtkAppChooserIface *iface)
|
|
{
|
|
iface->get_app_info = gtk_app_chooser_widget_get_app_info;
|
|
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`
|
|
*/
|
|
GtkWidget *
|
|
gtk_app_chooser_widget_new (const char *content_type)
|
|
{
|
|
return g_object_new (GTK_TYPE_APP_CHOOSER_WIDGET,
|
|
"content-type", content_type,
|
|
NULL);
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_set_show_default: (attributes org.gtk.Method.set_property=show-default)
|
|
* @self: a `GtkAppChooserWidget`
|
|
* @setting: the new value for [property@Gtk.AppChooserWidget:show-default]
|
|
*
|
|
* Sets whether the app chooser should show the default handler
|
|
* for the content type in a separate section.
|
|
*/
|
|
void
|
|
gtk_app_chooser_widget_set_show_default (GtkAppChooserWidget *self,
|
|
gboolean setting)
|
|
{
|
|
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
|
|
|
|
if (self->show_default != setting)
|
|
{
|
|
self->show_default = setting;
|
|
|
|
g_object_notify (G_OBJECT (self), "show-default");
|
|
|
|
gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_get_show_default: (attributes org.gtk.Method.get_property=show-default)
|
|
* @self: a `GtkAppChooserWidget`
|
|
*
|
|
* Gets whether the app chooser should show the default handler
|
|
* for the content type in a separate section.
|
|
*
|
|
* Returns: the value of [property@Gtk.AppChooserWidget:show-default]
|
|
*/
|
|
gboolean
|
|
gtk_app_chooser_widget_get_show_default (GtkAppChooserWidget *self)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
|
|
|
|
return self->show_default;
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_set_show_recommended: (attributes org.gtk.Method.set_property=show-recommended)
|
|
* @self: a `GtkAppChooserWidget`
|
|
* @setting: the new value for [property@Gtk.AppChooserWidget:show-recommended]
|
|
*
|
|
* Sets whether the app chooser should show recommended applications
|
|
* for the content type in a separate section.
|
|
*/
|
|
void
|
|
gtk_app_chooser_widget_set_show_recommended (GtkAppChooserWidget *self,
|
|
gboolean setting)
|
|
{
|
|
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
|
|
|
|
if (self->show_recommended != setting)
|
|
{
|
|
self->show_recommended = setting;
|
|
|
|
g_object_notify (G_OBJECT (self), "show-recommended");
|
|
|
|
gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_get_show_recommended: (attributes org.gtk.Method.get_property=show-recommended)
|
|
* @self: a `GtkAppChooserWidget`
|
|
*
|
|
* Gets whether the app chooser should show recommended applications
|
|
* for the content type in a separate section.
|
|
*
|
|
* Returns: the value of [property@Gtk.AppChooserWidget:show-recommended]
|
|
*/
|
|
gboolean
|
|
gtk_app_chooser_widget_get_show_recommended (GtkAppChooserWidget *self)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
|
|
|
|
return self->show_recommended;
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_set_show_fallback: (attributes org.gtk.Method.set_property=show-fallback)
|
|
* @self: a `GtkAppChooserWidget`
|
|
* @setting: the new value for [property@Gtk.AppChooserWidget:show-fallback]
|
|
*
|
|
* Sets whether the app chooser should show related applications
|
|
* for the content type in a separate section.
|
|
*/
|
|
void
|
|
gtk_app_chooser_widget_set_show_fallback (GtkAppChooserWidget *self,
|
|
gboolean setting)
|
|
{
|
|
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
|
|
|
|
if (self->show_fallback != setting)
|
|
{
|
|
self->show_fallback = setting;
|
|
|
|
g_object_notify (G_OBJECT (self), "show-fallback");
|
|
|
|
gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_get_show_fallback: (attributes org.gtk.Method.get_property=show-fallback)
|
|
* @self: a `GtkAppChooserWidget`
|
|
*
|
|
* Gets whether the app chooser should show related applications
|
|
* for the content type in a separate section.
|
|
*
|
|
* Returns: the value of [property@Gtk.AppChooserWidget:show-fallback]
|
|
*/
|
|
gboolean
|
|
gtk_app_chooser_widget_get_show_fallback (GtkAppChooserWidget *self)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
|
|
|
|
return self->show_fallback;
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_set_show_other: (attributes org.gtk.Method.set_property=show-other)
|
|
* @self: a `GtkAppChooserWidget`
|
|
* @setting: the new value for [property@Gtk.AppChooserWidget:show-other]
|
|
*
|
|
* Sets whether the app chooser should show applications
|
|
* which are unrelated to the content type.
|
|
*/
|
|
void
|
|
gtk_app_chooser_widget_set_show_other (GtkAppChooserWidget *self,
|
|
gboolean setting)
|
|
{
|
|
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
|
|
|
|
if (self->show_other != setting)
|
|
{
|
|
self->show_other = setting;
|
|
|
|
g_object_notify (G_OBJECT (self), "show-other");
|
|
|
|
gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_get_show_other: (attributes org.gtk.Method.get_property=show-other)
|
|
* @self: a `GtkAppChooserWidget`
|
|
*
|
|
* Gets whether the app chooser should show applications
|
|
* which are unrelated to the content type.
|
|
*
|
|
* Returns: the value of [property@Gtk.AppChooserWidget:show-other]
|
|
*/
|
|
gboolean
|
|
gtk_app_chooser_widget_get_show_other (GtkAppChooserWidget *self)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
|
|
|
|
return self->show_other;
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_set_show_all: (attributes org.gtk.Method.set_property=show-all)
|
|
* @self: a `GtkAppChooserWidget`
|
|
* @setting: the new value for [property@Gtk.AppChooserWidget:show-all]
|
|
*
|
|
* Sets whether the app chooser should show all applications
|
|
* in a flat list.
|
|
*/
|
|
void
|
|
gtk_app_chooser_widget_set_show_all (GtkAppChooserWidget *self,
|
|
gboolean setting)
|
|
{
|
|
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
|
|
|
|
if (self->show_all != setting)
|
|
{
|
|
self->show_all = setting;
|
|
|
|
g_object_notify (G_OBJECT (self), "show-all");
|
|
|
|
gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_get_show_all: (attributes org.gtk.Method.get_property=show-all)
|
|
* @self: a `GtkAppChooserWidget`
|
|
*
|
|
* Gets whether the app chooser should show all applications
|
|
* in a flat list.
|
|
*
|
|
* Returns: the value of [property@Gtk.AppChooserWidget:show-all]
|
|
*/
|
|
gboolean
|
|
gtk_app_chooser_widget_get_show_all (GtkAppChooserWidget *self)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
|
|
|
|
return self->show_all;
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_set_default_text: (attributes org.gtk.Method.set_property=default-text)
|
|
* @self: a `GtkAppChooserWidget`
|
|
* @text: the new value for [property@Gtk.AppChooserWidget: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 char *text)
|
|
{
|
|
g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
|
|
|
|
if (g_strcmp0 (text, self->default_text) != 0)
|
|
{
|
|
g_free (self->default_text);
|
|
self->default_text = g_strdup (text);
|
|
|
|
g_object_notify (G_OBJECT (self), "default-text");
|
|
|
|
gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gtk_app_chooser_widget_get_default_text: (attributes org.gtk.Method.get_property=default-text)
|
|
* @self: a `GtkAppChooserWidget`
|
|
*
|
|
* Returns the text that is shown if there are not applications
|
|
* that can handle the content type.
|
|
*
|
|
* Returns: (nullable): the value of [property@Gtk.AppChooserWidget:default-text]
|
|
*/
|
|
const char *
|
|
gtk_app_chooser_widget_get_default_text (GtkAppChooserWidget *self)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), NULL);
|
|
|
|
return self->default_text;
|
|
}
|
|
|
|
void
|
|
_gtk_app_chooser_widget_set_search_entry (GtkAppChooserWidget *self,
|
|
GtkEditable *entry)
|
|
{
|
|
gtk_tree_view_set_search_entry (GTK_TREE_VIEW (self->program_list), entry);
|
|
|
|
g_object_bind_property (self->no_apps, "visible",
|
|
entry, "sensitive",
|
|
G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
|
|
}
|