/* * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * This is a plug-in for PIKA. * * Copyright (C) 1999 Andy Thomas alt@picnic.demon.co.uk * * Note some portions of the UI comes from the dbbrowser plugin. * 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 . */ #include "config.h" #include #include #include #include #include #include "libpika/stdplugins-intl.h" #define PLUG_IN_PROC "plug-in-plug-in-details" #define PLUG_IN_BINARY "plugin-browser" #define PLUG_IN_ROLE "pika-plugin-browser" #define DBL_LIST_WIDTH 250 #define DBL_WIDTH (DBL_LIST_WIDTH + 400) #define DBL_HEIGHT 250 enum { LIST_COLUMN_NAME, LIST_COLUMN_DATE, LIST_COLUMN_DATE_STRING, LIST_COLUMN_PATH, LIST_COLUMN_IMAGE_TYPES, LIST_COLUMN_PINFO, N_LIST_COLUMNS }; enum { TREE_COLUMN_PATH_NAME, TREE_COLUMN_DATE, TREE_COLUMN_DATE_STRING, TREE_COLUMN_IMAGE_TYPES, TREE_COLUMN_MPATH, TREE_COLUMN_PINFO, N_TREE_OLUMNS }; typedef struct { GtkWidget *dialog; GtkWidget *browser; GtkTreeView *list_view; GtkTreeView *tree_view; } PluginBrowser; typedef struct { gchar *menu; gchar *accel; gchar *prog; gchar *procedure; gint instime; } PInfo; typedef struct _Browser Browser; typedef struct _BrowserClass BrowserClass; struct _Browser { PikaPlugIn parent_instance; }; struct _BrowserClass { PikaPlugInClass parent_class; }; /* Declare local functions. */ #define BROWSER_TYPE (browser_get_type ()) #define BROWSER (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BROWSER_TYPE, Browser)) GType browser_get_type (void) G_GNUC_CONST; static GList * browser_query_procedures (PikaPlugIn *plug_in); static PikaProcedure * browser_create_procedure (PikaPlugIn *plug_in, const gchar *name); static PikaValueArray * browser_run (PikaProcedure *procedure, const PikaValueArray *args, gpointer run_data); static GtkWidget * browser_dialog_new (void); static void browser_dialog_response (GtkWidget *widget, gint response_id, PluginBrowser *browser); static void browser_list_selection_changed (GtkTreeSelection *selection, PluginBrowser *browser); static void browser_tree_selection_changed (GtkTreeSelection *selection, PluginBrowser *browser); static gboolean find_existing_mpath (GtkTreeModel *model, const gchar *mpath, GtkTreeIter *return_iter); G_DEFINE_TYPE (Browser, browser, PIKA_TYPE_PLUG_IN) PIKA_MAIN (BROWSER_TYPE) DEFINE_STD_SET_I18N static void browser_class_init (BrowserClass *klass) { PikaPlugInClass *plug_in_class = PIKA_PLUG_IN_CLASS (klass); plug_in_class->query_procedures = browser_query_procedures; plug_in_class->create_procedure = browser_create_procedure; plug_in_class->set_i18n = STD_SET_I18N; } static void browser_init (Browser *browser) { } static GList * browser_query_procedures (PikaPlugIn *plug_in) { return g_list_append (NULL, g_strdup (PLUG_IN_PROC)); } static PikaProcedure * browser_create_procedure (PikaPlugIn *plug_in, const gchar *procedure_name) { PikaProcedure *procedure = NULL; if (! strcmp (procedure_name, PLUG_IN_PROC)) { procedure = pika_procedure_new (plug_in, procedure_name, PIKA_PDB_PROC_TYPE_PLUGIN, browser_run, NULL, NULL); pika_procedure_set_menu_label (procedure, _("_Plug-In Browser")); pika_procedure_set_icon_name (procedure, PIKA_ICON_PLUGIN); pika_procedure_add_menu_path (procedure, "/Help/[Programming]"); pika_procedure_set_documentation (procedure, _("Display information about plug-ins"), _("Allows one to browse the plug-in " "menus system. You can search for " "plug-in names, sort by name or menu " "location and you can view a tree " "representation of the plug-in menus. " "Can also be of help to find where " "new plug-ins have installed " "themselves in the menus."), PLUG_IN_PROC); pika_procedure_set_attribution (procedure, "Andy Thomas", "Andy Thomas", "1999"); PIKA_PROC_ARG_ENUM (procedure, "run-mode", "Run mode", "The run mode", PIKA_TYPE_RUN_MODE, PIKA_RUN_INTERACTIVE, G_PARAM_READWRITE); } return procedure; } static PikaValueArray * browser_run (PikaProcedure *procedure, const PikaValueArray *args, gpointer run_data) { browser_dialog_new (); gtk_main (); return pika_procedure_new_return_values (procedure, PIKA_PDB_SUCCESS, NULL); } static gboolean find_existing_mpath_helper (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path, const gchar *mpath, GtkTreeIter *return_iter) { do { GtkTreeIter child; gchar *picked_mpath; gtk_tree_model_get (model, iter, TREE_COLUMN_MPATH, &picked_mpath, -1); if (! strcmp (mpath, picked_mpath)) { *return_iter = *iter; g_free (picked_mpath); return TRUE; } if (gtk_tree_model_iter_children (model, &child, iter)) { gtk_tree_path_down (path); if (find_existing_mpath_helper (model, &child, path, mpath, return_iter)) { g_free (picked_mpath); return TRUE; } gtk_tree_path_up (path); } gtk_tree_path_next (path); g_free (picked_mpath); } while (gtk_tree_model_iter_next (model, iter)); return FALSE; } static gboolean find_existing_mpath (GtkTreeModel *model, const gchar *mpath, GtkTreeIter *return_iter) { GtkTreePath *path = gtk_tree_path_new_first (); GtkTreeIter parent; gboolean found; if (! gtk_tree_model_get_iter (model, &parent, path)) { gtk_tree_path_free (path); return FALSE; } found = find_existing_mpath_helper (model, &parent, path, mpath, return_iter); gtk_tree_path_free (path); return found; } static void get_parent (PluginBrowser *browser, const gchar *mpath, GtkTreeIter *parent) { GtkTreeIter last_parent; gchar *tmp_ptr; gchar *str_ptr; GtkTreeStore *tree_store; if (! mpath) return; tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (browser->tree_view)); /* Lookup for existing mpath */ if (find_existing_mpath (GTK_TREE_MODEL (tree_store), mpath, parent)) return; tmp_ptr = g_strdup (mpath); /* Strip off trailing ellipsis */ str_ptr = strstr (mpath, "..."); if (str_ptr && str_ptr == (mpath + strlen (mpath) - 3)) *str_ptr = '\0'; str_ptr = strrchr (tmp_ptr, '/'); if (str_ptr == NULL) { gtk_tree_store_append (tree_store, parent, NULL); gtk_tree_store_set (tree_store, parent, TREE_COLUMN_MPATH, mpath, TREE_COLUMN_PATH_NAME, mpath, -1); } else { gchar *leaf_ptr; leaf_ptr = g_strdup (str_ptr + 1); *str_ptr = '\0'; get_parent (browser, tmp_ptr, &last_parent); gtk_tree_store_append (tree_store, parent, &last_parent); gtk_tree_store_set (tree_store, parent, TREE_COLUMN_MPATH, mpath, TREE_COLUMN_PATH_NAME, leaf_ptr, -1); g_free (leaf_ptr); } } static void insert_into_tree_view (PluginBrowser *browser, const gchar *name, gint64 xtime, const gchar *xtimestr, const gchar *menu_path, const gchar *types_str, PInfo *pinfo) { GtkTreeStore *tree_store; GtkTreeIter parent, iter; get_parent (browser, menu_path, &parent); tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (browser->tree_view)); gtk_tree_store_append (tree_store, &iter, &parent); gtk_tree_store_set (tree_store, &iter, TREE_COLUMN_MPATH, menu_path, TREE_COLUMN_PATH_NAME, name, TREE_COLUMN_IMAGE_TYPES, types_str, TREE_COLUMN_DATE, xtime, TREE_COLUMN_DATE_STRING, xtimestr, TREE_COLUMN_PINFO, pinfo, -1); } static void browser_search (PikaBrowser *pika_browser, const gchar *search_text, gint search_type, PluginBrowser *browser) { PikaValueArray *return_vals; const gchar **procedure_strs; gint num_plugins = 0; gchar *str; GtkListStore *list_store; GtkTreeStore *tree_store; pika_browser_show_message (PIKA_BROWSER (browser->browser), _("Searching by name")); return_vals = pika_pdb_run_procedure (pika_get_pdb (), "pika-plug-ins-query", G_TYPE_STRING, search_text, G_TYPE_NONE); if (PIKA_VALUES_GET_ENUM (return_vals, 0) == PIKA_PDB_SUCCESS) { procedure_strs = PIKA_VALUES_GET_STRV (return_vals, 1); num_plugins = g_strv_length ((gchar **) procedure_strs); } if (! search_text || strlen (search_text) == 0) { str = g_strdup_printf (ngettext ("%d plug-in", "%d plug-ins", num_plugins), num_plugins); } else { switch (num_plugins) { case 0: str = g_strdup (_("No matches for your query")); break; default: str = g_strdup_printf (ngettext ("%d plug-in matches your query", "%d plug-ins match your query", num_plugins), num_plugins); break; } } pika_browser_set_search_summary (pika_browser, str); g_free (str); list_store = GTK_LIST_STORE (gtk_tree_view_get_model (browser->list_view)); gtk_list_store_clear (list_store); tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (browser->tree_view)); gtk_tree_store_clear (tree_store); if (num_plugins > 0) { GtkTreeSelection *sel; GtkTreeIter iter; const gchar **accel_strs; const gchar **prog_strs; const gint *time_ints; gint i; accel_strs = PIKA_VALUES_GET_STRV (return_vals, 2); prog_strs = PIKA_VALUES_GET_STRV (return_vals, 3); time_ints = PIKA_VALUES_GET_INT32_ARRAY (return_vals, 5); for (i = 0; i < num_plugins; i++) { PikaProcedure *procedure; const gchar *types; PInfo *pinfo; gchar *menu_label; gchar *tmp; GList *menu_paths; const gchar *menu_path; gchar xtimestr[50]; struct tm *x; time_t tx; gint ret; procedure = pika_pdb_lookup_procedure (pika_get_pdb (), procedure_strs[i]); types = pika_procedure_get_image_types (procedure); menu_label = g_strdup (pika_procedure_get_menu_label (procedure)); menu_paths = pika_procedure_get_menu_paths (procedure); menu_path = menu_paths->data; /* Strip off trailing ellipsis */ tmp = strstr (menu_label, "..."); if (tmp && tmp == (menu_label + strlen (menu_label) - 3)) *tmp = '\0'; tmp = pika_strip_uline (menu_label); g_free (menu_label); menu_label = tmp; tx = time_ints[i]; if (tx) { const gchar *format = "%c"; /* gcc workaround to avoid warning */ gchar *utf8; x = localtime (&tx); ret = strftime (xtimestr, sizeof (xtimestr), format, x); xtimestr[ret] = 0; if ((utf8 = g_locale_to_utf8 (xtimestr, -1, NULL, NULL, NULL))) { g_strlcpy (xtimestr, utf8, sizeof (xtimestr)); g_free (utf8); } } else { strcpy (xtimestr, ""); } pinfo = g_new0 (PInfo, 1); pinfo->menu = g_strdup (menu_path); pinfo->accel = g_strdup (accel_strs[i]); pinfo->prog = g_strdup (prog_strs[i]); pinfo->instime = time_ints[i]; pinfo->procedure = g_strdup (procedure_strs[i]); gtk_list_store_append (list_store, &iter); gtk_list_store_set (list_store, &iter, LIST_COLUMN_NAME, menu_label, LIST_COLUMN_DATE, (gint64) tx, LIST_COLUMN_DATE_STRING, xtimestr, LIST_COLUMN_PATH, menu_path, LIST_COLUMN_IMAGE_TYPES, types, LIST_COLUMN_PINFO, pinfo, -1); /* Now do the tree view.... */ insert_into_tree_view (browser, menu_label, (gint64) tx, xtimestr, menu_path, types, pinfo); g_free (menu_label); } gtk_tree_view_columns_autosize (GTK_TREE_VIEW (browser->list_view)); gtk_tree_view_columns_autosize (GTK_TREE_VIEW (browser->tree_view)); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list_store), LIST_COLUMN_NAME, GTK_SORT_ASCENDING); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (tree_store), TREE_COLUMN_PATH_NAME, GTK_SORT_ASCENDING); sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (browser->list_view)); gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter); gtk_tree_selection_select_iter (sel, &iter); } else { pika_browser_show_message (PIKA_BROWSER (browser->browser), _("No matches")); } pika_value_array_unref (return_vals); } static GtkWidget * browser_dialog_new (void) { PluginBrowser *browser; GtkWidget *label, *notebook; GtkWidget *scrolled_window; GtkListStore *list_store; GtkTreeStore *tree_store; GtkWidget *list_view; GtkWidget *tree_view; GtkWidget *parent; GtkTreeViewColumn *column; GtkCellRenderer *renderer; GtkTreeSelection *selection; GtkTreeIter iter; pika_ui_init (PLUG_IN_BINARY); browser = g_new0 (PluginBrowser, 1); browser->dialog = pika_dialog_new (_("Plug-in Browser"), PLUG_IN_ROLE, NULL, 0, pika_standard_help_func, PLUG_IN_PROC, _("_Close"), GTK_RESPONSE_CLOSE, NULL); gtk_window_set_default_size (GTK_WINDOW (browser->dialog), DBL_WIDTH, DBL_WIDTH - DBL_LIST_WIDTH); g_signal_connect (browser->dialog, "response", G_CALLBACK (browser_dialog_response), browser); browser->browser = pika_browser_new (); gtk_container_set_border_width (GTK_CONTAINER (browser->browser), 12); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (browser->dialog))), browser->browser, TRUE, TRUE, 0); gtk_widget_show (browser->browser); g_signal_connect (browser->browser, "search", G_CALLBACK (browser_search), browser); /* left = notebook */ notebook = gtk_notebook_new (); gtk_box_pack_start (GTK_BOX (pika_browser_get_left_vbox (PIKA_BROWSER (browser->browser))), notebook, TRUE, TRUE, 0); /* list : list in a scrolled_win */ list_store = gtk_list_store_new (N_LIST_COLUMNS, G_TYPE_STRING, G_TYPE_INT64, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); list_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store)); g_object_unref (list_store); browser->list_view = GTK_TREE_VIEW (list_view); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "text", LIST_COLUMN_NAME, NULL); gtk_tree_view_column_set_sort_column_id (column, LIST_COLUMN_NAME); gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Menu Path"), renderer, "text", LIST_COLUMN_PATH, NULL); gtk_tree_view_column_set_sort_column_id (column, LIST_COLUMN_PATH); gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Image Types"), renderer, "text", LIST_COLUMN_IMAGE_TYPES, NULL); gtk_tree_view_column_set_sort_column_id (column, LIST_COLUMN_IMAGE_TYPES); gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Installation Date"), renderer, "text", LIST_COLUMN_DATE_STRING, NULL); gtk_tree_view_column_set_sort_column_id (column, LIST_COLUMN_DATE); gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 2); 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_AUTOMATIC); gtk_widget_set_size_request (list_view, DBL_LIST_WIDTH, DBL_HEIGHT); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list_view)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); g_signal_connect (selection, "changed", G_CALLBACK (browser_list_selection_changed), browser); label = gtk_label_new (_("List View")); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled_window, label); gtk_container_add (GTK_CONTAINER (scrolled_window), list_view); gtk_widget_show (list_view); gtk_widget_show (scrolled_window); /* notebook->ctree */ tree_store = gtk_tree_store_new (N_LIST_COLUMNS, G_TYPE_STRING, G_TYPE_INT64, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (tree_store)); g_object_unref (tree_store); browser->tree_view = GTK_TREE_VIEW (tree_view); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Menu Path"), renderer, "text", TREE_COLUMN_PATH_NAME, NULL); gtk_tree_view_column_set_sort_column_id (column, TREE_COLUMN_PATH_NAME); gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Image Types"), renderer, "text", TREE_COLUMN_IMAGE_TYPES, NULL); gtk_tree_view_column_set_sort_column_id (column, TREE_COLUMN_IMAGE_TYPES); gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Installation Date"), renderer, "text", TREE_COLUMN_DATE_STRING, NULL); gtk_tree_view_column_set_sort_column_id (column, TREE_COLUMN_DATE); gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 2); 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_AUTOMATIC); gtk_widget_set_size_request (tree_view, DBL_LIST_WIDTH, DBL_HEIGHT); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); g_signal_connect (selection, "changed", G_CALLBACK (browser_tree_selection_changed), browser); label = gtk_label_new (_("Tree View")); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled_window, label); gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view); gtk_widget_show (tree_view); gtk_widget_show (scrolled_window); gtk_widget_show (notebook); parent = gtk_widget_get_parent (pika_browser_get_right_vbox (PIKA_BROWSER (browser->browser))); parent = gtk_widget_get_parent (parent); gtk_widget_set_size_request (parent, DBL_WIDTH - DBL_LIST_WIDTH, -1); /* now build the list */ browser_search (PIKA_BROWSER (browser->browser), "", 0, browser); gtk_widget_show (browser->dialog); if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter)) gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (list_view)), &iter); return browser->dialog; } static void browser_dialog_response (GtkWidget *widget, gint response_id, PluginBrowser *browser) { gtk_widget_destroy (browser->dialog); gtk_main_quit (); } static void browser_list_selection_changed (GtkTreeSelection *selection, PluginBrowser *browser) { PInfo *pinfo = NULL; GtkTreeIter iter; GtkTreeModel *model; gchar *mpath = NULL; g_return_if_fail (browser != NULL); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { gtk_tree_model_get (model, &iter, LIST_COLUMN_PINFO, &pinfo, LIST_COLUMN_PATH, &mpath, -1); } if (!pinfo || !mpath) return; model = gtk_tree_view_get_model (browser->tree_view); if (find_existing_mpath (model, mpath, &iter)) { GtkTreeSelection *tree_selection; GtkTreePath *tree_path; tree_path = gtk_tree_model_get_path (model, &iter); gtk_tree_view_expand_to_path (browser->tree_view, tree_path); tree_selection = gtk_tree_view_get_selection (browser->tree_view); g_signal_handlers_block_by_func (tree_selection, browser_tree_selection_changed, browser); gtk_tree_selection_select_iter (tree_selection, &iter); g_signal_handlers_unblock_by_func (tree_selection, browser_tree_selection_changed, browser); gtk_tree_view_scroll_to_cell (browser->tree_view, tree_path, NULL, TRUE, 0.5, 0.0); } else { g_warning ("Failed to find node in tree"); } g_free (mpath); pika_browser_set_widget (PIKA_BROWSER (browser->browser), pika_proc_view_new (pinfo->procedure)); } static void browser_tree_selection_changed (GtkTreeSelection *selection, PluginBrowser *browser) { PInfo *pinfo = NULL; GtkTreeIter iter; GtkTreeModel *model; gchar *mpath = NULL; gboolean valid, found; g_return_if_fail (browser != NULL); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { gtk_tree_model_get (model, &iter, TREE_COLUMN_PINFO, &pinfo, TREE_COLUMN_MPATH, &mpath, -1); } if (!pinfo || !mpath) return; /* Get the first iter in the list */ model = gtk_tree_view_get_model (browser->list_view); valid = gtk_tree_model_get_iter_first (model, &iter); found = FALSE; while (valid) { /* Walk through the list, reading each row */ gchar *picked_mpath; gtk_tree_model_get (model, &iter, LIST_COLUMN_PATH, &picked_mpath, -1); if (picked_mpath && !strcmp (mpath, picked_mpath)) { found = TRUE; break; } g_free (picked_mpath); valid = gtk_tree_model_iter_next (model, &iter); } g_free (mpath); if (found) { GtkTreeSelection *list_selection; GtkTreePath *tree_path; tree_path = gtk_tree_model_get_path (model, &iter); list_selection = gtk_tree_view_get_selection (browser->list_view); g_signal_handlers_block_by_func (list_selection, browser_list_selection_changed, browser); gtk_tree_selection_select_iter (list_selection, &iter); g_signal_handlers_unblock_by_func (list_selection, browser_list_selection_changed, browser); gtk_tree_view_scroll_to_cell (browser->list_view, tree_path, NULL, TRUE, 0.5, 0.0); } else { g_warning ("Failed to find node in list"); } pika_browser_set_widget (PIKA_BROWSER (browser->browser), pika_proc_view_new (pinfo->procedure)); }