mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-03 09:23:24 +00:00

The dialog was still calling the old API gimp_pdb_query() everywhere, which made it fail to run when called with the new API (e.g. from the Python console or directly from an action) whereas it worked well when called from the old API (e.g. from the Script-fu console). By testing the existence of the GimpPDB singleton, we can have this dialog work in both cases.
561 lines
18 KiB
C
561 lines
18 KiB
C
/* LIBGIMP - The GIMP Library
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
*
|
|
* gimpprocbrowserdialog.c
|
|
*
|
|
* This library is free software: you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 3 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <gegl.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
#include "gimp.h"
|
|
|
|
#include "gimpuitypes.h"
|
|
#include "gimpprocbrowserdialog.h"
|
|
#include "gimpprocview.h"
|
|
|
|
#include "libgimp-intl.h"
|
|
|
|
|
|
/**
|
|
* SECTION: gimpprocbrowserdialog
|
|
* @title: GimpProcBrowserDialog
|
|
* @short_description: The dialog for the procedure and plugin browsers.
|
|
*
|
|
* The dialog for the procedure and plugin browsers.
|
|
**/
|
|
|
|
|
|
#define DBL_LIST_WIDTH 250
|
|
#define DBL_WIDTH (DBL_LIST_WIDTH + 400)
|
|
#define DBL_HEIGHT 250
|
|
|
|
|
|
enum
|
|
{
|
|
SELECTION_CHANGED,
|
|
ROW_ACTIVATED,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
typedef enum
|
|
{
|
|
SEARCH_TYPE_ALL,
|
|
SEARCH_TYPE_NAME,
|
|
SEARCH_TYPE_BLURB,
|
|
SEARCH_TYPE_HELP,
|
|
SEARCH_TYPE_AUTHOR,
|
|
SEARCH_TYPE_COPYRIGHT,
|
|
SEARCH_TYPE_DATE,
|
|
SEARCH_TYPE_PROC_TYPE
|
|
} SearchType;
|
|
|
|
enum
|
|
{
|
|
COLUMN_PROC_NAME,
|
|
N_COLUMNS
|
|
};
|
|
|
|
|
|
struct _GimpProcBrowserDialogPrivate
|
|
{
|
|
GtkWidget *browser;
|
|
|
|
GtkListStore *store;
|
|
GtkWidget *tree_view;
|
|
};
|
|
|
|
#define GET_PRIVATE(obj) (((GimpProcBrowserDialog *) (obj))->priv)
|
|
|
|
|
|
static void browser_selection_changed (GtkTreeSelection *sel,
|
|
GimpProcBrowserDialog *dialog);
|
|
static void browser_row_activated (GtkTreeView *treeview,
|
|
GtkTreePath *path,
|
|
GtkTreeViewColumn *column,
|
|
GimpProcBrowserDialog *dialog);
|
|
static void browser_search (GimpBrowser *browser,
|
|
const gchar *query_text,
|
|
gint search_type,
|
|
GimpProcBrowserDialog *dialog);
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (GimpProcBrowserDialog, gimp_proc_browser_dialog,
|
|
GIMP_TYPE_DIALOG)
|
|
|
|
#define parent_class gimp_proc_browser_dialog_parent_class
|
|
|
|
static guint dialog_signals[LAST_SIGNAL] = { 0, };
|
|
|
|
|
|
static void
|
|
gimp_proc_browser_dialog_class_init (GimpProcBrowserDialogClass *klass)
|
|
{
|
|
/**
|
|
* GimpProcBrowserDialog::selection-changed:
|
|
* @dialog: the object that received the signal
|
|
*
|
|
* Emitted when the selection in the contained #GtkTreeView changes.
|
|
*/
|
|
dialog_signals[SELECTION_CHANGED] =
|
|
g_signal_new ("selection-changed",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (GimpProcBrowserDialogClass,
|
|
selection_changed),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
|
|
/**
|
|
* GimpProcBrowserDialog::row-activated:
|
|
* @dialog: the object that received the signal
|
|
*
|
|
* Emitted when one of the rows in the contained #GtkTreeView is activated.
|
|
*/
|
|
dialog_signals[ROW_ACTIVATED] =
|
|
g_signal_new ("row-activated",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (GimpProcBrowserDialogClass,
|
|
row_activated),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
|
|
klass->selection_changed = NULL;
|
|
klass->row_activated = NULL;
|
|
}
|
|
|
|
static void
|
|
gimp_proc_browser_dialog_init (GimpProcBrowserDialog *dialog)
|
|
{
|
|
GimpProcBrowserDialogPrivate *priv;
|
|
GtkWidget *scrolled_window;
|
|
GtkCellRenderer *renderer;
|
|
GtkTreeSelection *selection;
|
|
GtkWidget *parent;
|
|
|
|
dialog->priv = gimp_proc_browser_dialog_get_instance_private (dialog);
|
|
|
|
priv = GET_PRIVATE (dialog);
|
|
|
|
priv->browser = gimp_browser_new ();
|
|
gimp_browser_add_search_types (GIMP_BROWSER (priv->browser),
|
|
_("by name"), SEARCH_TYPE_NAME,
|
|
_("by description"), SEARCH_TYPE_BLURB,
|
|
_("by help"), SEARCH_TYPE_HELP,
|
|
_("by author"), SEARCH_TYPE_AUTHOR,
|
|
_("by copyright"), SEARCH_TYPE_COPYRIGHT,
|
|
_("by date"), SEARCH_TYPE_DATE,
|
|
_("by type"), SEARCH_TYPE_PROC_TYPE,
|
|
NULL);
|
|
gtk_container_set_border_width (GTK_CONTAINER (priv->browser), 12);
|
|
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
|
priv->browser, TRUE, TRUE, 0);
|
|
gtk_widget_show (priv->browser);
|
|
|
|
g_signal_connect (priv->browser, "search",
|
|
G_CALLBACK (browser_search),
|
|
dialog);
|
|
|
|
/* list : list in a scrolled_win */
|
|
|
|
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
|
|
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_AUTOMATIC,
|
|
GTK_POLICY_ALWAYS);
|
|
gtk_box_pack_start (GTK_BOX (gimp_browser_get_left_vbox (GIMP_BROWSER (priv->browser))),
|
|
scrolled_window, TRUE, TRUE, 0);
|
|
gtk_widget_show (scrolled_window);
|
|
|
|
priv->tree_view = gtk_tree_view_new ();
|
|
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
gtk_cell_renderer_text_set_fixed_height_from_font
|
|
(GTK_CELL_RENDERER_TEXT (renderer), 1);
|
|
|
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view),
|
|
-1, NULL,
|
|
renderer,
|
|
"text", 0,
|
|
NULL);
|
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
|
|
|
|
g_signal_connect (priv->tree_view, "row_activated",
|
|
G_CALLBACK (browser_row_activated),
|
|
dialog);
|
|
|
|
gtk_widget_set_size_request (priv->tree_view, DBL_LIST_WIDTH, DBL_HEIGHT);
|
|
gtk_container_add (GTK_CONTAINER (scrolled_window), priv->tree_view);
|
|
gtk_widget_show (priv->tree_view);
|
|
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
|
|
|
|
g_signal_connect (selection, "changed",
|
|
G_CALLBACK (browser_selection_changed),
|
|
dialog);
|
|
|
|
parent = gtk_widget_get_parent (gimp_browser_get_right_vbox (GIMP_BROWSER (priv->browser)));
|
|
parent = gtk_widget_get_parent (parent);
|
|
|
|
gtk_widget_set_size_request (parent, DBL_WIDTH - DBL_LIST_WIDTH, -1);
|
|
|
|
/* first search (all procedures) */
|
|
browser_search (GIMP_BROWSER (dialog->priv->browser),
|
|
"", SEARCH_TYPE_ALL, dialog);
|
|
}
|
|
|
|
|
|
/* public functions */
|
|
|
|
/**
|
|
* gimp_proc_browser_dialog_new:
|
|
* @title: The dialog's title.
|
|
* @role: The dialog's role, see gtk_window_set_role().
|
|
* @help_func: (scope async): The function which will be called if
|
|
* the user presses "F1".
|
|
* @help_id: The help_id which will be passed to @help_func.
|
|
* @...: A %NULL-terminated list destribing the action_area buttons.
|
|
*
|
|
* Create a new #GimpProcBrowserDialog.
|
|
*
|
|
* Returns: a newly created #GimpProcBrowserDialog.
|
|
*
|
|
* Since: 2.4
|
|
**/
|
|
GtkWidget *
|
|
gimp_proc_browser_dialog_new (const gchar *title,
|
|
const gchar *role,
|
|
GimpHelpFunc help_func,
|
|
const gchar *help_id,
|
|
...)
|
|
{
|
|
GimpProcBrowserDialog *dialog;
|
|
va_list args;
|
|
gboolean use_header_bar;
|
|
|
|
va_start (args, help_id);
|
|
|
|
g_object_get (gtk_settings_get_default (),
|
|
"gtk-dialogs-use-header", &use_header_bar,
|
|
NULL);
|
|
|
|
dialog = g_object_new (GIMP_TYPE_PROC_BROWSER_DIALOG,
|
|
"title", title,
|
|
"role", role,
|
|
"help-func", help_func,
|
|
"help-id", help_id,
|
|
"use-header-bar", use_header_bar,
|
|
NULL);
|
|
|
|
gimp_dialog_add_buttons_valist (GIMP_DIALOG (dialog), args);
|
|
|
|
va_end (args);
|
|
|
|
return GTK_WIDGET (dialog);
|
|
}
|
|
|
|
/**
|
|
* gimp_proc_browser_dialog_get_selected:
|
|
* @dialog: a #GimpProcBrowserDialog
|
|
*
|
|
* Retrieves the name of the currently selected procedure.
|
|
*
|
|
* Returns: (nullable): The name of the selected procedure of %NULL if no
|
|
* procedure is selected.
|
|
*
|
|
* Since: 2.4
|
|
**/
|
|
gchar *
|
|
gimp_proc_browser_dialog_get_selected (GimpProcBrowserDialog *dialog)
|
|
{
|
|
GtkTreeSelection *sel;
|
|
GtkTreeIter iter;
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROC_BROWSER_DIALOG (dialog), NULL);
|
|
|
|
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->tree_view));
|
|
|
|
if (gtk_tree_selection_get_selected (sel, NULL, &iter))
|
|
{
|
|
gchar *proc_name;
|
|
|
|
gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->store), &iter,
|
|
COLUMN_PROC_NAME, &proc_name,
|
|
-1);
|
|
|
|
return proc_name;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* private functions */
|
|
|
|
static void
|
|
browser_selection_changed (GtkTreeSelection *sel,
|
|
GimpProcBrowserDialog *dialog)
|
|
{
|
|
GtkTreeIter iter;
|
|
|
|
if (gtk_tree_selection_get_selected (sel, NULL, &iter))
|
|
{
|
|
gchar *proc_name;
|
|
|
|
gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->store), &iter,
|
|
COLUMN_PROC_NAME, &proc_name,
|
|
-1);
|
|
|
|
gimp_browser_set_widget (GIMP_BROWSER (dialog->priv->browser),
|
|
gimp_proc_view_new (proc_name, NULL));
|
|
|
|
g_free (proc_name);
|
|
}
|
|
|
|
g_signal_emit (dialog, dialog_signals[SELECTION_CHANGED], 0);
|
|
}
|
|
|
|
static void
|
|
browser_row_activated (GtkTreeView *treeview,
|
|
GtkTreePath *path,
|
|
GtkTreeViewColumn *column,
|
|
GimpProcBrowserDialog *dialog)
|
|
{
|
|
g_signal_emit (dialog, dialog_signals[ROW_ACTIVATED], 0);
|
|
}
|
|
|
|
static void
|
|
browser_search (GimpBrowser *browser,
|
|
const gchar *query_text,
|
|
gint search_type,
|
|
GimpProcBrowserDialog *dialog)
|
|
{
|
|
GimpProcBrowserDialogPrivate *priv = GET_PRIVATE (dialog);
|
|
gchar **proc_list;
|
|
gint num_procs;
|
|
gchar *str;
|
|
GRegex *regex;
|
|
|
|
/* first check if the query is a valid regex */
|
|
regex = g_regex_new (query_text, 0, 0, NULL);
|
|
|
|
if (! regex)
|
|
{
|
|
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), NULL);
|
|
priv->store = NULL;
|
|
|
|
gimp_browser_show_message (browser, _("No matches"));
|
|
|
|
gimp_browser_set_search_summary (browser,
|
|
_("Search term invalid or incomplete"));
|
|
return;
|
|
}
|
|
|
|
g_regex_unref (regex);
|
|
|
|
switch (search_type)
|
|
{
|
|
case SEARCH_TYPE_ALL:
|
|
gimp_browser_show_message (browser, _("Searching"));
|
|
|
|
if (gimp_get_plug_in ())
|
|
proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
|
|
".*", ".*", ".*", ".*", ".*",
|
|
".*", ".*", ".*", &num_procs);
|
|
else
|
|
gimp_pdb_query (".*", ".*", ".*", ".*", ".*", ".*", ".*",
|
|
&num_procs, &proc_list);
|
|
break;
|
|
|
|
case SEARCH_TYPE_NAME:
|
|
{
|
|
GString *query = g_string_new ("");
|
|
const gchar *q = query_text;
|
|
|
|
gimp_browser_show_message (browser, _("Searching by name"));
|
|
|
|
while (*q)
|
|
{
|
|
if ((*q == '_') || (*q == '-'))
|
|
g_string_append (query, "-");
|
|
else
|
|
g_string_append_c (query, *q);
|
|
|
|
q++;
|
|
}
|
|
|
|
if (gimp_get_plug_in ())
|
|
proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
|
|
query->str, ".*", ".*", ".*", ".*",
|
|
".*", ".*", ".*", &num_procs);
|
|
else
|
|
gimp_pdb_query (query->str,
|
|
".*", ".*", ".*", ".*", ".*", ".*",
|
|
&num_procs, &proc_list);
|
|
|
|
g_string_free (query, TRUE);
|
|
}
|
|
break;
|
|
|
|
case SEARCH_TYPE_BLURB:
|
|
gimp_browser_show_message (browser, _("Searching by description"));
|
|
|
|
if (gimp_get_plug_in ())
|
|
proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
|
|
".*", query_text, ".*", ".*", ".*",
|
|
".*", ".*", ".*", &num_procs);
|
|
else
|
|
gimp_pdb_query (".*", query_text, ".*", ".*", ".*", ".*", ".*",
|
|
&num_procs, &proc_list);
|
|
break;
|
|
|
|
case SEARCH_TYPE_HELP:
|
|
gimp_browser_show_message (browser, _("Searching by help"));
|
|
|
|
if (gimp_get_plug_in ())
|
|
proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
|
|
".*", ".*", query_text, ".*", ".*",
|
|
".*", ".*", ".*", &num_procs);
|
|
else
|
|
gimp_pdb_query (".*", ".*", query_text, ".*", ".*", ".*", ".*",
|
|
&num_procs, &proc_list);
|
|
break;
|
|
|
|
case SEARCH_TYPE_AUTHOR:
|
|
gimp_browser_show_message (browser, _("Searching by author"));
|
|
|
|
if (gimp_get_plug_in ())
|
|
proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
|
|
".*", ".*", ".*", ".*", query_text,
|
|
".*", ".*", ".*", &num_procs);
|
|
else
|
|
gimp_pdb_query (".*", ".*", ".*", query_text, ".*", ".*", ".*",
|
|
&num_procs, &proc_list);
|
|
break;
|
|
|
|
case SEARCH_TYPE_COPYRIGHT:
|
|
gimp_browser_show_message (browser, _("Searching by copyright"));
|
|
|
|
if (gimp_get_plug_in ())
|
|
proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
|
|
".*", ".*", ".*", ".*", ".*",
|
|
query_text, ".*", ".*", &num_procs);
|
|
else
|
|
gimp_pdb_query (".*", ".*", ".*", ".*", query_text, ".*", ".*",
|
|
&num_procs, &proc_list);
|
|
break;
|
|
|
|
case SEARCH_TYPE_DATE:
|
|
gimp_browser_show_message (browser, _("Searching by date"));
|
|
|
|
if (gimp_get_plug_in ())
|
|
proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
|
|
".*", ".*", ".*", ".*", ".*",
|
|
".*", query_text, ".*", &num_procs);
|
|
else
|
|
gimp_pdb_query (".*", ".*", ".*", ".*", ".*", query_text, ".*",
|
|
&num_procs, &proc_list);
|
|
break;
|
|
|
|
case SEARCH_TYPE_PROC_TYPE:
|
|
gimp_browser_show_message (browser, _("Searching by type"));
|
|
|
|
if (gimp_get_plug_in ())
|
|
proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
|
|
".*", ".*", ".*", ".*", ".*",
|
|
".*", ".*", query_text, &num_procs);
|
|
else
|
|
gimp_pdb_query (".*", ".*", ".*", ".*", ".*", ".*", query_text,
|
|
&num_procs, &proc_list);
|
|
break;
|
|
}
|
|
|
|
if (! query_text || strlen (query_text) == 0)
|
|
{
|
|
str = g_strdup_printf (dngettext (GETTEXT_PACKAGE "-libgimp",
|
|
"%d procedure",
|
|
"%d procedures",
|
|
num_procs), num_procs);
|
|
}
|
|
else
|
|
{
|
|
switch (num_procs)
|
|
{
|
|
case 0:
|
|
str = g_strdup (_("No matches for your query"));
|
|
break;
|
|
default:
|
|
str = g_strdup_printf (dngettext (GETTEXT_PACKAGE "-libgimp",
|
|
"%d procedure matches your query",
|
|
"%d procedures match your query",
|
|
num_procs), num_procs);
|
|
break;
|
|
}
|
|
}
|
|
|
|
gimp_browser_set_search_summary (browser, str);
|
|
g_free (str);
|
|
|
|
if (num_procs > 0)
|
|
{
|
|
GtkTreeSelection *selection;
|
|
GtkTreeIter iter;
|
|
gint i;
|
|
|
|
priv->store = gtk_list_store_new (N_COLUMNS,
|
|
G_TYPE_STRING);
|
|
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view),
|
|
GTK_TREE_MODEL (priv->store));
|
|
g_object_unref (priv->store);
|
|
|
|
for (i = 0; i < num_procs; i++)
|
|
{
|
|
gtk_list_store_append (priv->store, &iter);
|
|
gtk_list_store_set (priv->store, &iter,
|
|
COLUMN_PROC_NAME, proc_list[i],
|
|
-1);
|
|
}
|
|
|
|
g_strfreev (proc_list);
|
|
|
|
gtk_tree_view_columns_autosize (GTK_TREE_VIEW (priv->tree_view));
|
|
|
|
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store),
|
|
COLUMN_PROC_NAME,
|
|
GTK_SORT_ASCENDING);
|
|
|
|
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->store), &iter);
|
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
|
|
gtk_tree_selection_select_iter (selection, &iter);
|
|
}
|
|
else
|
|
{
|
|
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), NULL);
|
|
priv->store = NULL;
|
|
|
|
gimp_browser_show_message (browser, _("No matches"));
|
|
}
|
|
}
|