Gimp/app/widgets/gimpsearchpopup.c
Jehan 7f83b27c3c Issue #5601: help icon in the action search.
Additionally to the F1 shortcut, a secondary icon is now shown in the
action search entry. It works exactly the same as F1, i.e. that by
default, it shows the action search manual page (when nothing is
selected), or the manual page for the specific action currently selected
otherwise.
2023-06-11 23:56:55 +02:00

837 lines
29 KiB
C

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpsearchpopup.c
* Copyright (C) 2015 Jehan <jehan at girinstud.io>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "widgets-types.h"
#include "core/gimp.h"
#include "gimpaction.h"
#include "gimphelp-ids.h"
#include "gimppopup.h"
#include "gimpsearchpopup.h"
#include "gimptoggleaction.h"
#include "gimp-intl.h"
enum
{
COLUMN_ICON,
COLUMN_MARKUP,
COLUMN_TOOLTIP,
COLUMN_ACTION,
COLUMN_SENSITIVE,
COLUMN_SECTION,
N_COL
};
enum
{
PROP_0,
PROP_GIMP,
PROP_CALLBACK,
PROP_CALLBACK_DATA
};
struct _GimpSearchPopupPrivate
{
Gimp *gimp;
GtkWidget *keyword_entry;
GtkWidget *results_list;
GtkWidget *list_view;
GimpSearchPopupCallback build_results;
gpointer build_results_data;
};
static void gimp_search_popup_constructed (GObject *object);
static void gimp_search_popup_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_search_popup_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_search_popup_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gimp_search_popup_confirm (GimpPopup *popup);
/* Signal handlers on the search entry */
static void keyword_entry_icon_press (GtkEntry *entry,
GtkEntryIconPosition icon_pos,
GdkEvent *event,
GimpSearchPopup *popup);
static gboolean keyword_entry_key_press_event (GtkWidget *widget,
GdkEventKey *event,
GimpSearchPopup *popup);
static gboolean keyword_entry_key_release_event (GtkWidget *widget,
GdkEventKey *event,
GimpSearchPopup *popup);
/* Signal handlers on the results list */
static gboolean results_list_key_press_event (GtkWidget *widget,
GdkEventKey *kevent,
GimpSearchPopup *popup);
static void results_list_row_activated (GtkTreeView *treeview,
GtkTreePath *path,
GtkTreeViewColumn *col,
GimpSearchPopup *popup);
/* Utils */
static void gimp_search_popup_run_selected (GimpSearchPopup *popup);
static void gimp_search_popup_setup_results (GtkWidget **results_list,
GtkWidget **list_view);
static void gimp_search_popup_help (GimpSearchPopup *popup);
G_DEFINE_TYPE_WITH_PRIVATE (GimpSearchPopup, gimp_search_popup, GIMP_TYPE_POPUP)
#define parent_class gimp_search_popup_parent_class
static gint window_height = 0;
static void
gimp_search_popup_class_init (GimpSearchPopupClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GimpPopupClass *popup_class = GIMP_POPUP_CLASS (klass);
object_class->constructed = gimp_search_popup_constructed;
object_class->set_property = gimp_search_popup_set_property;
object_class->get_property = gimp_search_popup_get_property;
widget_class->size_allocate = gimp_search_popup_size_allocate;
popup_class->confirm = gimp_search_popup_confirm;
/**
* GimpSearchPopup:gimp:
*
* The #Gimp object.
*/
g_object_class_install_property (object_class, PROP_GIMP,
g_param_spec_object ("gimp",
NULL, NULL,
G_TYPE_OBJECT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
/**
* GimpSearchPopup:callback:
*
* The #GimpSearchPopupCallback used to fill in results.
*/
g_object_class_install_property (object_class, PROP_CALLBACK,
g_param_spec_pointer ("callback", NULL, NULL,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
/**
* GimpSearchPopup:callback-data:
*
* The #GPointer fed as last parameter to the #GimpSearchPopupCallback.
*/
g_object_class_install_property (object_class, PROP_CALLBACK_DATA,
g_param_spec_pointer ("callback-data", NULL, NULL,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
}
static void
gimp_search_popup_init (GimpSearchPopup *search_popup)
{
search_popup->priv = gimp_search_popup_get_instance_private (search_popup);
}
/************ Public Functions ****************/
/**
* gimp_search_popup_new:
* @gimp: #Gimp object.
* @role: the role to give to the #GtkWindow.
* @title: the #GtkWindow title.
* @callback: the #GimpSearchPopupCallback used to fill in results.
* @callback_data: data fed to @callback.
*
* Returns: a new #GimpSearchPopup.
*/
GtkWidget *
gimp_search_popup_new (Gimp *gimp,
const gchar *role,
const gchar *title,
GimpSearchPopupCallback callback,
gpointer callback_data)
{
GtkWidget *widget;
widget = g_object_new (GIMP_TYPE_SEARCH_POPUP,
"type", GTK_WINDOW_TOPLEVEL,
"type-hint", GDK_WINDOW_TYPE_HINT_DIALOG,
"decorated", TRUE,
"modal", TRUE,
"role", role,
"title", title,
"gimp", gimp,
"callback", callback,
"callback-data", callback_data,
NULL);
gtk_window_set_modal (GTK_WINDOW (widget), FALSE);
return widget;
}
/**
* gimp_search_popup_add_result:
* @popup: the #GimpSearchPopup.
* @action: a #GimpAction to add in results list.
* @section: the section to add @action.
*
* Adds @action in the @popup's results at @section.
* The section only indicates relative order. If you want some items
* to appear before other, simply use lower @section.
*/
void
gimp_search_popup_add_result (GimpSearchPopup *popup,
GimpAction *action,
gint section)
{
gchar **accels;
GtkTreeIter iter;
GtkTreeIter next_section;
GtkListStore *store;
GtkTreeModel *model;
gchar *markup;
gchar *action_name;
gchar *label;
gchar *escaped_label = NULL;
const gchar *icon_name;
gchar *shortcut_helper = NULL;
const gchar *menu_path;
gchar *menu_path_helper = NULL;
const gchar *tooltip;
gchar *escaped_tooltip = NULL;
gboolean has_tooltip = FALSE;
gboolean sensitive = FALSE;
const gchar *sensitive_reason = NULL;
gchar *escaped_reason = NULL;
label = g_strstrip (gimp_strip_uline (gimp_action_get_label (action)));
if (! label || strlen (label) == 0)
{
g_free (label);
return;
}
escaped_label = g_markup_escape_text (label, -1);
if (GIMP_IS_TOGGLE_ACTION (action))
{
if (gimp_toggle_action_get_active (GIMP_TOGGLE_ACTION (action)))
icon_name = "gtk-ok";
else
icon_name = "gtk-no";
}
else
{
icon_name = gimp_action_get_icon_name (action);
}
accels = gimp_action_get_display_accels (action);
if (accels && accels[0])
{
gchar *formatted_label;
gchar *formatted_value;
/* TRANSLATORS: a helper label indicating the shortcut for an action,
* it will be used within the generic "%s: %s" (also localized) string.
* e.g.: "shortcut: Ctrl+Alt+O"
*/
formatted_label = g_markup_printf_escaped ("<u>%s</u>", _("shortcut"));
formatted_value = g_markup_escape_text (accels[0], -1);
/* TRANSLATORS: generic "title: value" label which will be used in various ways. */
shortcut_helper = g_strdup_printf (_("%s: %s"), formatted_label, formatted_value);
g_free (formatted_label);
g_free (formatted_value);
}
g_strfreev (accels);
if ((menu_path = gimp_action_get_menu_path (action)) != NULL)
{
if (strlen (menu_path) > 0)
{
gchar *formatted_label;
gchar *formatted_value;
/* TRANSLATORS: a helper label indicating the menu path for an action,
* it will be used within the generic "%s: %s" (also localized) string.
* e.g.: "Menu: Filters > Generic"
*/
formatted_label = g_markup_printf_escaped ("<u>%s</u>", _("menu"));
formatted_value = g_markup_escape_text (menu_path, -1);
/* TRANSLATORS: generic "title: value" label which will be used in various ways. */
menu_path_helper = g_strdup_printf (_("%s: %s"), formatted_label, formatted_value);
g_free (formatted_label);
g_free (formatted_value);
}
}
tooltip = gimp_action_get_tooltip (action);
if (tooltip != NULL)
{
escaped_tooltip = g_markup_escape_text (tooltip, -1);
has_tooltip = TRUE;
}
sensitive = gimp_action_is_sensitive (action, &sensitive_reason);
if (sensitive_reason != NULL)
{
escaped_reason = g_markup_escape_text (sensitive_reason, -1);
}
markup = g_strdup_printf ("%s" /* Label */
"<small>%s%s" /* Shortcut */
"%s%s" /* Menu path */
"%s<span weight='light'>%s</span>" /* Tooltip */
"%s<i><span weight='ultralight'>%s</span></i>" /* Inactive reason */
"</small>",
escaped_label,
shortcut_helper ? " | " : "",
shortcut_helper ? shortcut_helper : "",
menu_path_helper ? " | " : "",
menu_path_helper ? menu_path_helper : "",
has_tooltip ? "\n" : "",
has_tooltip ? escaped_tooltip : "",
escaped_reason ? "\n" : "",
escaped_reason ? escaped_reason : "");
action_name = g_markup_escape_text (gimp_action_get_name (action), -1);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (popup->priv->results_list));
store = GTK_LIST_STORE (model);
if (gtk_tree_model_get_iter_first (model, &next_section))
{
while (TRUE)
{
gint iter_section;
gtk_tree_model_get (model, &next_section,
COLUMN_SECTION, &iter_section, -1);
if (iter_section > section)
{
gtk_list_store_insert_before (store, &iter, &next_section);
break;
}
else if (! gtk_tree_model_iter_next (model, &next_section))
{
gtk_list_store_append (store, &iter);
break;
}
}
}
else
{
gtk_list_store_append (store, &iter);
}
gtk_list_store_set (store, &iter,
COLUMN_ICON, icon_name,
COLUMN_MARKUP, markup,
COLUMN_TOOLTIP, action_name,
COLUMN_ACTION, action,
COLUMN_SECTION, section,
COLUMN_SENSITIVE, sensitive,
-1);
g_free (markup);
g_free (action_name);
g_free (label);
g_free (escaped_label);
g_free (escaped_tooltip);
g_free (escaped_reason);
g_free (menu_path_helper);
g_free (shortcut_helper);
}
/************ Private Functions ****************/
static void
gimp_search_popup_constructed (GObject *object)
{
GimpSearchPopup *popup = GIMP_SEARCH_POPUP (object);
GtkWidget *main_vbox;
G_OBJECT_CLASS (parent_class)->constructed (object);
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_container_add (GTK_CONTAINER (popup), main_vbox);
gtk_widget_show (main_vbox);
popup->priv->keyword_entry = gtk_entry_new ();
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (popup->priv->keyword_entry),
GTK_ENTRY_ICON_PRIMARY, "edit-find");
gtk_entry_set_icon_activatable (GTK_ENTRY (popup->priv->keyword_entry),
GTK_ENTRY_ICON_PRIMARY, FALSE);
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (popup->priv->keyword_entry),
GTK_ENTRY_ICON_SECONDARY, GIMP_ICON_HELP);
gtk_entry_set_icon_activatable (GTK_ENTRY (popup->priv->keyword_entry),
GTK_ENTRY_ICON_SECONDARY, TRUE);
gtk_box_pack_start (GTK_BOX (main_vbox),
popup->priv->keyword_entry,
FALSE, FALSE, 0);
gtk_widget_show (popup->priv->keyword_entry);
gimp_search_popup_setup_results (&popup->priv->results_list,
&popup->priv->list_view);
gtk_box_pack_start (GTK_BOX (main_vbox),
popup->priv->list_view, TRUE, TRUE, 0);
gtk_widget_set_events (GTK_WIDGET (object),
GDK_KEY_RELEASE_MASK |
GDK_KEY_PRESS_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_SCROLL_MASK |
GDK_SMOOTH_SCROLL_MASK);
g_signal_connect (popup->priv->keyword_entry, "icon-press",
G_CALLBACK (keyword_entry_icon_press),
popup);
g_signal_connect (popup->priv->keyword_entry, "key-press-event",
G_CALLBACK (keyword_entry_key_press_event),
popup);
g_signal_connect (popup->priv->keyword_entry, "key-release-event",
G_CALLBACK (keyword_entry_key_release_event),
popup);
g_signal_connect (popup->priv->results_list, "key-press-event",
G_CALLBACK (results_list_key_press_event),
popup);
g_signal_connect (popup->priv->results_list, "row-activated",
G_CALLBACK (results_list_row_activated),
popup);
}
static void
gimp_search_popup_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpSearchPopup *search_popup = GIMP_SEARCH_POPUP (object);
switch (property_id)
{
case PROP_GIMP:
search_popup->priv->gimp = g_value_get_object (value);
break;
case PROP_CALLBACK:
search_popup->priv->build_results = g_value_get_pointer (value);
break;
case PROP_CALLBACK_DATA:
search_popup->priv->build_results_data = g_value_get_pointer (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_search_popup_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpSearchPopup *search_popup = GIMP_SEARCH_POPUP (object);
switch (property_id)
{
case PROP_GIMP:
g_value_set_object (value, search_popup->priv->gimp);
break;
case PROP_CALLBACK:
g_value_set_pointer (value, search_popup->priv->build_results);
break;
case PROP_CALLBACK_DATA:
g_value_set_pointer (value, search_popup->priv->build_results_data);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_search_popup_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GimpSearchPopup *popup = GIMP_SEARCH_POPUP (widget);
GdkRectangle workarea;
GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
gdk_monitor_get_workarea (gimp_widget_get_monitor (widget),
&workarea);
if (window_height == 0)
{
/* Default to half the monitor */
window_height = workarea.height / 2;
}
if (gtk_widget_get_visible (widget) &&
gtk_widget_get_visible (popup->priv->list_view))
{
/* Save the window height when results are shown so that resizes
* by the user are saved across searches.
*/
window_height = MAX (workarea.height / 4, allocation->height);
}
}
static void
gimp_search_popup_confirm (GimpPopup *popup)
{
GimpSearchPopup *search_popup = GIMP_SEARCH_POPUP (popup);
gimp_search_popup_run_selected (search_popup);
}
static void
keyword_entry_icon_press (GtkEntry *entry,
GtkEntryIconPosition icon_pos,
GdkEvent *event,
GimpSearchPopup *popup)
{
if (icon_pos == GTK_ENTRY_ICON_SECONDARY)
gimp_search_popup_help (popup);
}
static gboolean
keyword_entry_key_press_event (GtkWidget *widget,
GdkEventKey *event,
GimpSearchPopup *popup)
{
gboolean event_processed = FALSE;
if (event->keyval == GDK_KEY_Down &&
gtk_widget_get_visible (popup->priv->list_view))
{
GtkTreeView *tree_view = GTK_TREE_VIEW (popup->priv->results_list);
GtkTreePath *path;
/* When hitting the down key while editing, select directly the
* second item, since the first could have run directly with
* Enter. */
path = gtk_tree_path_new_from_string ("1");
gtk_tree_selection_select_path (gtk_tree_view_get_selection (tree_view), path);
gtk_tree_path_free (path);
gtk_widget_grab_focus (GTK_WIDGET (popup->priv->results_list));
event_processed = TRUE;
}
return event_processed;
}
static gboolean
keyword_entry_key_release_event (GtkWidget *widget,
GdkEventKey *event,
GimpSearchPopup *popup)
{
GtkTreeView *tree_view = GTK_TREE_VIEW (popup->priv->results_list);
GtkTreePath *path;
gchar *entry_text;
gint width;
/* These keys are already managed by key bindings. */
if (event->keyval == GDK_KEY_Escape ||
event->keyval == GDK_KEY_Return ||
event->keyval == GDK_KEY_KP_Enter ||
event->keyval == GDK_KEY_ISO_Enter)
{
return FALSE;
}
gtk_window_get_size (GTK_WINDOW (popup), &width, NULL);
entry_text = g_strstrip (gtk_editable_get_chars (GTK_EDITABLE (widget), 0, -1));
if (event->keyval == GDK_KEY_F1)
{
gimp_search_popup_help (popup);
}
else if (strcmp (entry_text, "") != 0)
{
path = gtk_tree_path_new_from_string ("0");
gtk_window_resize (GTK_WINDOW (popup),
width, window_height);
gtk_list_store_clear (GTK_LIST_STORE (gtk_tree_view_get_model (tree_view)));
gtk_widget_show_all (popup->priv->list_view);
popup->priv->build_results (popup, entry_text,
popup->priv->build_results_data);
gtk_tree_selection_select_path (gtk_tree_view_get_selection (tree_view), path);
gtk_tree_path_free (path);
}
else if (strcmp (entry_text, "") == 0 && (event->keyval == GDK_KEY_Down))
{
path = gtk_tree_path_new_from_string ("0");
gtk_window_resize (GTK_WINDOW (popup),
width, window_height);
gtk_list_store_clear (GTK_LIST_STORE (gtk_tree_view_get_model (tree_view)));
gtk_widget_show_all (popup->priv->list_view);
popup->priv->build_results (popup, NULL,
popup->priv->build_results_data);
gtk_tree_selection_select_path (gtk_tree_view_get_selection (tree_view), path);
gtk_tree_path_free (path);
}
else
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection (tree_view);
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
path = gtk_tree_model_get_path (model, &iter);
gtk_tree_selection_unselect_path (selection, path);
gtk_tree_path_free (path);
}
gtk_widget_hide (popup->priv->list_view);
gtk_window_resize (GTK_WINDOW (popup), width, 1);
}
g_free (entry_text);
return TRUE;
}
static gboolean
results_list_key_press_event (GtkWidget *widget,
GdkEventKey *kevent,
GimpSearchPopup *popup)
{
/* These keys are already managed by key bindings. */
g_return_val_if_fail (kevent->keyval != GDK_KEY_Escape &&
kevent->keyval != GDK_KEY_Return &&
kevent->keyval != GDK_KEY_KP_Enter &&
kevent->keyval != GDK_KEY_ISO_Enter,
FALSE);
switch (kevent->keyval)
{
case GDK_KEY_Up:
{
gboolean event_processed = FALSE;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (popup->priv->results_list));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
gchar *path_str;
path_str = gtk_tree_path_to_string (path);
if (strcmp (path_str, "0") == 0)
{
gint start_pos;
gint end_pos;
gtk_editable_get_selection_bounds (GTK_EDITABLE (popup->priv->keyword_entry),
&start_pos, &end_pos);
gtk_widget_grab_focus ((GTK_WIDGET (popup->priv->keyword_entry)));
gtk_editable_select_region (GTK_EDITABLE (popup->priv->keyword_entry),
start_pos, end_pos);
event_processed = TRUE;
}
g_free (path_str);
gtk_tree_path_free (path);
}
return event_processed;
}
case GDK_KEY_Down:
{
return FALSE;
}
default:
{
gint start_pos;
gint end_pos;
gtk_editable_get_selection_bounds (GTK_EDITABLE (popup->priv->keyword_entry),
&start_pos, &end_pos);
gtk_widget_grab_focus ((GTK_WIDGET (popup->priv->keyword_entry)));
gtk_editable_select_region (GTK_EDITABLE (popup->priv->keyword_entry),
start_pos, end_pos);
gtk_widget_event (GTK_WIDGET (popup->priv->keyword_entry),
(GdkEvent *) kevent);
}
}
return FALSE;
}
static void
results_list_row_activated (GtkTreeView *treeview,
GtkTreePath *path,
GtkTreeViewColumn *col,
GimpSearchPopup *popup)
{
gimp_search_popup_run_selected (popup);
}
static void
gimp_search_popup_run_selected (GimpSearchPopup *popup)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (popup->priv->results_list));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
GimpAction *action;
gtk_tree_model_get (model, &iter, COLUMN_ACTION, &action, -1);
if (gimp_action_is_sensitive (action, NULL))
{
/* Close the search popup on activation. */
GIMP_POPUP_CLASS (parent_class)->cancel (GIMP_POPUP (popup));
gimp_action_activate (action);
}
g_object_unref (action);
}
}
static void
gimp_search_popup_setup_results (GtkWidget **results_list,
GtkWidget **list_view)
{
gint wid1 = 100;
GtkListStore *store;
GtkCellRenderer *cell;
GtkTreeViewColumn *column;
*list_view = gtk_scrolled_window_new (NULL, NULL);
store = gtk_list_store_new (N_COL,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
GIMP_TYPE_ACTION,
G_TYPE_BOOLEAN,
G_TYPE_INT);
*results_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (*results_list), FALSE);
#ifdef GIMP_UNSTABLE
gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (*results_list),
COLUMN_TOOLTIP);
#endif
cell = gtk_cell_renderer_pixbuf_new ();
column = gtk_tree_view_column_new_with_attributes (NULL, cell,
"icon-name", COLUMN_ICON,
"sensitive", COLUMN_SENSITIVE,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (*results_list), column);
gtk_tree_view_column_set_min_width (column, 22);
cell = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (NULL, cell,
"markup", COLUMN_MARKUP,
"sensitive", COLUMN_SENSITIVE,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (*results_list), column);
gtk_tree_view_column_set_max_width (column, wid1);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (*list_view),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (*list_view), *results_list);
g_object_unref (G_OBJECT (store));
}
static void
gimp_search_popup_help (GimpSearchPopup *popup)
{
GtkTreeView *tree_view;
const gchar *help_id = NULL;
GimpAction *action = NULL;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
tree_view = GTK_TREE_VIEW (popup->priv->results_list);
selection = gtk_tree_view_get_selection (tree_view);
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
gtk_tree_model_get (model, &iter, COLUMN_ACTION, &action, -1);
help_id = gimp_action_get_help_id (action);
}
if (help_id == NULL)
help_id = GIMP_HELP_ACTION_SEARCH_DIALOG;
gimp_help (popup->priv->gimp, NULL, NULL, help_id);
g_clear_object (&action);
}