
Like GtkFileChooser does; GtkOpenWith is a generic interface, which is now implemented by both GtkOpenWithDialog and GtkOpenWithWidget (and in the future also by GtkOpenWithComboBox).
794 lines
20 KiB
C
794 lines
20 KiB
C
/*
|
|
* gtkopenwithwidget.c: an open-with 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 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.
|
|
*
|
|
* Authors: Dave Camp <dave@novell.com>
|
|
* Alexander Larsson <alexl@redhat.com>
|
|
* Cosimo Cecchi <ccecchi@redhat.com>
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "gtkopenwithwidget.h"
|
|
|
|
#include "gtkintl.h"
|
|
#include "gtkmarshalers.h"
|
|
#include "gtkopenwith.h"
|
|
#include "gtkopenwithprivate.h"
|
|
|
|
#include <string.h>
|
|
#include <glib/gi18n-lib.h>
|
|
#include <gtk/gtk.h>
|
|
#include <gio/gio.h>
|
|
|
|
struct _GtkOpenWithWidgetPrivate {
|
|
GAppInfo *selected_app_info;
|
|
|
|
char *content_type;
|
|
GtkOpenWithWidgetShowMode show_mode;
|
|
|
|
GtkWidget *program_list;
|
|
GtkListStore *program_list_store;
|
|
|
|
GtkCellRenderer *padding_renderer;
|
|
};
|
|
|
|
enum {
|
|
COLUMN_APP_INFO,
|
|
COLUMN_GICON,
|
|
COLUMN_NAME,
|
|
COLUMN_COMMENT,
|
|
COLUMN_EXEC,
|
|
COLUMN_HEADING,
|
|
COLUMN_HEADING_TEXT,
|
|
COLUMN_RECOMMENDED,
|
|
NUM_COLUMNS
|
|
};
|
|
|
|
|
|
enum {
|
|
PROP_CONTENT_TYPE = 1,
|
|
PROP_GFILE,
|
|
PROP_SHOW_MODE,
|
|
N_PROPERTIES
|
|
};
|
|
|
|
enum {
|
|
SIGNAL_APPLICATION_SELECTED,
|
|
SIGNAL_APPLICATION_ACTIVATED,
|
|
N_SIGNALS
|
|
};
|
|
|
|
static guint signals[N_SIGNALS] = { 0, };
|
|
|
|
static void gtk_open_with_widget_iface_init (GtkOpenWithIface *iface);
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GtkOpenWithWidget, gtk_open_with_widget, GTK_TYPE_BOX,
|
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_OPEN_WITH,
|
|
gtk_open_with_widget_iface_init));
|
|
|
|
static void
|
|
refresh_and_emit_app_selected (GtkOpenWithWidget *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->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);
|
|
|
|
self->priv->selected_app_info = info;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
should_emit = TRUE;
|
|
self->priv->selected_app_info = info;
|
|
}
|
|
|
|
if (should_emit)
|
|
g_signal_emit (self, signals[SIGNAL_APPLICATION_SELECTED], 0,
|
|
self->priv->selected_app_info);
|
|
}
|
|
|
|
static void
|
|
program_list_selection_activated (GtkTreeView *view,
|
|
GtkTreePath *path,
|
|
GtkTreeViewColumn *column,
|
|
gpointer user_data)
|
|
{
|
|
GtkOpenWithWidget *self = user_data;
|
|
GtkTreeSelection *selection;
|
|
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->program_list));
|
|
|
|
refresh_and_emit_app_selected (self, selection);
|
|
|
|
g_signal_emit (self, signals[SIGNAL_APPLICATION_ACTIVATED], 0,
|
|
self->priv->selected_app_info);
|
|
}
|
|
|
|
static gboolean
|
|
gtk_open_with_search_equal_func (GtkTreeModel *model,
|
|
int column,
|
|
const char *key,
|
|
GtkTreeIter *iter,
|
|
gpointer user_data)
|
|
{
|
|
char *normalized_key;
|
|
char *name, *normalized_name;
|
|
char *path, *normalized_path;
|
|
char *basename, *normalized_basename;
|
|
gboolean ret;
|
|
|
|
if (key != NULL)
|
|
{
|
|
normalized_key = g_utf8_casefold (key, -1);
|
|
g_assert (normalized_key != NULL);
|
|
|
|
ret = TRUE;
|
|
|
|
gtk_tree_model_get (model, iter,
|
|
COLUMN_NAME, &name,
|
|
COLUMN_EXEC, &path,
|
|
-1);
|
|
|
|
if (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;
|
|
}
|
|
|
|
g_free (normalized_name);
|
|
}
|
|
|
|
if (ret && path != NULL)
|
|
{
|
|
normalized_path = g_utf8_casefold (path, -1);
|
|
g_assert (normalized_path != NULL);
|
|
|
|
basename = g_path_get_basename (path);
|
|
g_assert (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;
|
|
}
|
|
|
|
g_free (basename);
|
|
g_free (normalized_basename);
|
|
g_free (normalized_path);
|
|
}
|
|
|
|
g_free (name);
|
|
g_free (path);
|
|
g_free (normalized_key);
|
|
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
static gint
|
|
gtk_open_with_sort_func (GtkTreeModel *model,
|
|
GtkTreeIter *a,
|
|
GtkTreeIter *b,
|
|
gpointer user_data)
|
|
{
|
|
gboolean a_recommended, b_recommended;
|
|
gchar *a_name, *b_name, *a_casefold, *b_casefold;
|
|
gint retval;
|
|
|
|
/* 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,
|
|
-1);
|
|
|
|
gtk_tree_model_get (model, b,
|
|
COLUMN_NAME, &b_name,
|
|
COLUMN_RECOMMENDED, &b_recommended,
|
|
-1);
|
|
|
|
/* the recommended one always wins */
|
|
if (a_recommended && !b_recommended)
|
|
{
|
|
retval = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (b_recommended && !a_recommended)
|
|
{
|
|
retval = 1;
|
|
goto out;
|
|
}
|
|
|
|
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
|
|
heading_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);
|
|
|
|
g_object_set (cell,
|
|
"visible", heading,
|
|
NULL);
|
|
}
|
|
|
|
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_open_with_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 gint
|
|
compare_apps_func (gconstpointer a,
|
|
gconstpointer b)
|
|
{
|
|
return !g_app_info_equal (G_APP_INFO (a), G_APP_INFO (b));
|
|
}
|
|
|
|
static void
|
|
gtk_open_with_widget_real_add_items (GtkOpenWithWidget *self)
|
|
{
|
|
GList *all_applications = NULL, *content_type_apps = NULL, *l;
|
|
gboolean heading_added;
|
|
gboolean show_recommended, show_headings, show_all;
|
|
|
|
if (self->priv->show_mode == GTK_OPEN_WITH_WIDGET_SHOW_MODE_RECOMMENDED)
|
|
{
|
|
show_all = FALSE;
|
|
show_headings = FALSE;
|
|
show_recommended = TRUE;
|
|
}
|
|
else if (self->priv->show_mode == GTK_OPEN_WITH_WIDGET_SHOW_MODE_ALL)
|
|
{
|
|
show_all = TRUE;
|
|
show_headings = FALSE;
|
|
show_recommended = FALSE;
|
|
}
|
|
else
|
|
{
|
|
show_all = TRUE;
|
|
show_headings = TRUE;
|
|
show_recommended = TRUE;
|
|
}
|
|
|
|
if (show_recommended)
|
|
content_type_apps = g_app_info_get_all_for_type (self->priv->content_type);
|
|
|
|
if (show_all)
|
|
all_applications = g_app_info_get_all ();
|
|
|
|
heading_added = FALSE;
|
|
|
|
for (l = content_type_apps; l != NULL; l = l->next)
|
|
{
|
|
GAppInfo *app = l->data;
|
|
GtkTreeIter iter;
|
|
|
|
if (!g_app_info_supports_uris (app) &&
|
|
!g_app_info_supports_files (app))
|
|
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, _("Recommended Applications"),
|
|
COLUMN_HEADING, TRUE,
|
|
COLUMN_RECOMMENDED, TRUE,
|
|
-1);
|
|
|
|
heading_added = 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, g_app_info_get_icon (app),
|
|
COLUMN_NAME, g_app_info_get_display_name (app),
|
|
COLUMN_COMMENT, g_app_info_get_description (app),
|
|
COLUMN_EXEC, g_app_info_get_executable,
|
|
COLUMN_HEADING, FALSE,
|
|
COLUMN_RECOMMENDED, TRUE,
|
|
-1);
|
|
}
|
|
|
|
heading_added = FALSE;
|
|
|
|
for (l = all_applications; l != NULL && show_all; l = l->next)
|
|
{
|
|
GAppInfo *app = l->data;
|
|
GtkTreeIter iter;
|
|
|
|
if (!g_app_info_supports_uris (app) &&
|
|
!g_app_info_supports_files (app))
|
|
continue;
|
|
|
|
if (content_type_apps != NULL &&
|
|
g_list_find_custom (content_type_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, _("Other Applications"),
|
|
COLUMN_HEADING, TRUE,
|
|
COLUMN_RECOMMENDED, FALSE,
|
|
-1);
|
|
|
|
heading_added = 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, g_app_info_get_icon (app),
|
|
COLUMN_NAME, g_app_info_get_display_name (app),
|
|
COLUMN_COMMENT, g_app_info_get_description (app),
|
|
COLUMN_EXEC, g_app_info_get_executable,
|
|
COLUMN_HEADING, FALSE,
|
|
COLUMN_RECOMMENDED, FALSE,
|
|
-1);
|
|
}
|
|
|
|
if (content_type_apps != NULL)
|
|
g_list_free_full (content_type_apps, g_object_unref);
|
|
|
|
if (all_applications != NULL)
|
|
g_list_free_full (all_applications, g_object_unref);
|
|
}
|
|
|
|
static void
|
|
gtk_open_with_widget_add_items (GtkOpenWithWidget *self)
|
|
{
|
|
GtkCellRenderer *renderer;
|
|
GtkTreeViewColumn *column;
|
|
GtkTreeModel *sort;
|
|
|
|
/* 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_STRING,
|
|
G_TYPE_BOOLEAN);
|
|
sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (self->priv->program_list_store));
|
|
|
|
/* populate the widget */
|
|
gtk_open_with_widget_real_add_items (self);
|
|
|
|
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);
|
|
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sort),
|
|
COLUMN_NAME,
|
|
gtk_open_with_sort_func,
|
|
self, NULL);
|
|
gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (self->priv->program_list),
|
|
gtk_open_with_search_equal_func,
|
|
NULL, NULL);
|
|
|
|
column = gtk_tree_view_column_new ();
|
|
|
|
/* initial padding */
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
gtk_tree_view_column_pack_start (column, renderer, FALSE);
|
|
g_object_set (renderer,
|
|
"xpad", (self->priv->show_mode == GTK_OPEN_WITH_WIDGET_SHOW_MODE_HEADINGS) ? 6 : 0,
|
|
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,
|
|
"text", COLUMN_HEADING_TEXT,
|
|
NULL);
|
|
g_object_set (renderer,
|
|
"weight", PANGO_WEIGHT_BOLD,
|
|
"weight-set", TRUE,
|
|
"ypad", 6,
|
|
"xpad", 0,
|
|
NULL);
|
|
gtk_tree_view_column_set_cell_data_func (column, renderer,
|
|
heading_cell_renderer_func,
|
|
NULL, 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);
|
|
|
|
/* 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);
|
|
|
|
/* 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,
|
|
"text", COLUMN_NAME,
|
|
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_open_with_widget_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GtkOpenWithWidget *self = GTK_OPEN_WITH_WIDGET (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_CONTENT_TYPE:
|
|
self->priv->content_type = g_value_dup_string (value);
|
|
break;
|
|
case PROP_SHOW_MODE:
|
|
gtk_open_with_widget_set_show_mode (self,
|
|
g_value_get_enum (value));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_open_with_widget_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GtkOpenWithWidget *self = GTK_OPEN_WITH_WIDGET (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_CONTENT_TYPE:
|
|
g_value_set_string (value, self->priv->content_type);
|
|
break;
|
|
case PROP_SHOW_MODE:
|
|
g_value_set_enum (value, self->priv->show_mode);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_open_with_widget_constructed (GObject *object)
|
|
{
|
|
GtkOpenWithWidget *self = GTK_OPEN_WITH_WIDGET (object);
|
|
|
|
g_assert (self->priv->content_type != NULL);
|
|
|
|
if (G_OBJECT_CLASS (gtk_open_with_widget_parent_class)->constructed != NULL)
|
|
G_OBJECT_CLASS (gtk_open_with_widget_parent_class)->constructed (object);
|
|
|
|
gtk_open_with_widget_add_items (self);
|
|
}
|
|
|
|
static void
|
|
gtk_open_with_widget_finalize (GObject *object)
|
|
{
|
|
GtkOpenWithWidget *self = GTK_OPEN_WITH_WIDGET (object);
|
|
|
|
g_free (self->priv->content_type);
|
|
|
|
G_OBJECT_CLASS (gtk_open_with_widget_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gtk_open_with_widget_dispose (GObject *object)
|
|
{
|
|
GtkOpenWithWidget *self = GTK_OPEN_WITH_WIDGET (object);
|
|
|
|
if (self->priv->selected_app_info != NULL)
|
|
{
|
|
g_object_unref (self->priv->selected_app_info);
|
|
self->priv->selected_app_info = NULL;
|
|
}
|
|
|
|
G_OBJECT_CLASS (gtk_open_with_widget_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gtk_open_with_widget_class_init (GtkOpenWithWidgetClass *klass)
|
|
{
|
|
GObjectClass *gobject_class;
|
|
GParamSpec *pspec;
|
|
|
|
gobject_class = G_OBJECT_CLASS (klass);
|
|
gobject_class->dispose = gtk_open_with_widget_dispose;
|
|
gobject_class->finalize = gtk_open_with_widget_finalize;
|
|
gobject_class->set_property = gtk_open_with_widget_set_property;
|
|
gobject_class->get_property = gtk_open_with_widget_get_property;
|
|
gobject_class->constructed = gtk_open_with_widget_constructed;
|
|
|
|
g_object_class_override_property (gobject_class, PROP_CONTENT_TYPE, "content-type");
|
|
|
|
/**
|
|
* GtkOpenWithWidget::show-mode:
|
|
*
|
|
* The #GtkOpenWithWidgetShowMode for this widget.
|
|
**/
|
|
pspec =
|
|
g_param_spec_enum ("show-mode",
|
|
P_("The widget show mode"),
|
|
P_("The show mode for this widget"),
|
|
GTK_TYPE_OPEN_WITH_WIDGET_SHOW_MODE,
|
|
GTK_OPEN_WITH_WIDGET_SHOW_MODE_HEADINGS,
|
|
G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
g_object_class_install_property (gobject_class, PROP_SHOW_MODE, pspec);
|
|
|
|
signals[SIGNAL_APPLICATION_SELECTED] =
|
|
g_signal_new ("application-selected",
|
|
GTK_TYPE_OPEN_WITH_WIDGET,
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (GtkOpenWithWidgetClass, application_selected),
|
|
NULL, NULL,
|
|
_gtk_marshal_VOID__OBJECT,
|
|
G_TYPE_NONE,
|
|
1, G_TYPE_APP_INFO);
|
|
|
|
signals[SIGNAL_APPLICATION_ACTIVATED] =
|
|
g_signal_new ("application-activated",
|
|
GTK_TYPE_OPEN_WITH_WIDGET,
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (GtkOpenWithWidgetClass, application_activated),
|
|
NULL, NULL,
|
|
_gtk_marshal_VOID__OBJECT,
|
|
G_TYPE_NONE,
|
|
1, G_TYPE_APP_INFO);
|
|
|
|
g_type_class_add_private (klass, sizeof (GtkOpenWithWidgetPrivate));
|
|
}
|
|
|
|
static void
|
|
gtk_open_with_widget_init (GtkOpenWithWidget *self)
|
|
{
|
|
GtkWidget *scrolled_window;
|
|
GtkTreeSelection *selection;
|
|
|
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_OPEN_WITH_WIDGET,
|
|
GtkOpenWithWidgetPrivate);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (self), 5);
|
|
|
|
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_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
|
|
GTK_POLICY_NEVER,
|
|
GTK_POLICY_AUTOMATIC);
|
|
|
|
self->priv->program_list = gtk_tree_view_new ();
|
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (self->priv->program_list),
|
|
FALSE);
|
|
gtk_container_add (GTK_CONTAINER (scrolled_window), self->priv->program_list);
|
|
gtk_box_pack_start (GTK_BOX (self), scrolled_window, TRUE, TRUE, 0);
|
|
|
|
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_select_function (selection, gtk_open_with_selection_func,
|
|
self, NULL);
|
|
g_signal_connect_swapped (selection, "changed",
|
|
G_CALLBACK (refresh_and_emit_app_selected),
|
|
self);
|
|
g_signal_connect (self->priv->program_list, "row-activated",
|
|
G_CALLBACK (program_list_selection_activated),
|
|
self);
|
|
}
|
|
|
|
static GAppInfo *
|
|
gtk_open_with_widget_get_app_info (GtkOpenWith *object)
|
|
{
|
|
GtkOpenWithWidget *self = GTK_OPEN_WITH_WIDGET (object);
|
|
|
|
if (self->priv->selected_app_info == NULL)
|
|
return NULL;
|
|
|
|
return g_object_ref (self->priv->selected_app_info);
|
|
}
|
|
|
|
static void
|
|
gtk_open_with_widget_iface_init (GtkOpenWithIface *iface)
|
|
{
|
|
iface->get_app_info = gtk_open_with_widget_get_app_info;
|
|
}
|
|
|
|
void
|
|
_gtk_open_with_widget_refilter (GtkOpenWithWidget *self)
|
|
{
|
|
if (self->priv->program_list_store != NULL)
|
|
{
|
|
gtk_list_store_clear (self->priv->program_list_store);
|
|
|
|
/* don't add additional xpad if we don't have headings */
|
|
g_object_set (self->priv->padding_renderer,
|
|
"visible", self->priv->show_mode == GTK_OPEN_WITH_WIDGET_SHOW_MODE_HEADINGS,
|
|
NULL);
|
|
|
|
gtk_open_with_widget_real_add_items (self);
|
|
}
|
|
}
|
|
|
|
GtkWidget *
|
|
gtk_open_with_widget_new (const gchar *content_type)
|
|
{
|
|
return g_object_new (GTK_TYPE_OPEN_WITH_WIDGET,
|
|
"content-type", content_type,
|
|
NULL);
|
|
}
|
|
|
|
/**
|
|
* gtk_open_with_widget_set_show_mode:
|
|
* @self: a #GtkOpenWithWidget
|
|
* @show_mode: the new show mode for this widget
|
|
*
|
|
* Sets the mode for the widget to show the list of applications.
|
|
* See #GtkOpenWithWidgetShowMode for more details.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
void
|
|
gtk_open_with_widget_set_show_mode (GtkOpenWithWidget *self,
|
|
GtkOpenWithWidgetShowMode show_mode)
|
|
{
|
|
g_return_if_fail (GTK_IS_OPEN_WITH_WIDGET (self));
|
|
|
|
if (self->priv->show_mode != show_mode)
|
|
{
|
|
self->priv->show_mode = show_mode;
|
|
g_object_notify (G_OBJECT (self), "show-mode");
|
|
|
|
_gtk_open_with_widget_refilter (self);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gtk_open_with_widget_get_show_mode:
|
|
* @self: a #GtkOpenWithWidget
|
|
*
|
|
* Returns the current mode for the widget to show the list of applications.
|
|
* See #GtkOpenWithWidgetShowMode for mode details.
|
|
*
|
|
* Returns: a #GtkOpenWithWidgetShowMode
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
GtkOpenWithWidgetShowMode
|
|
gtk_open_with_widget_get_show_mode (GtkOpenWithWidget *self)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_OPEN_WITH_WIDGET (self), FALSE);
|
|
|
|
return self->priv->show_mode;
|
|
}
|