881 lines
29 KiB
C
881 lines
29 KiB
C
/*
|
|
* 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <libpika/pika.h>
|
|
#include <libpika/pikaui.h>
|
|
|
|
#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,
|
|
PikaProcedureConfig *config,
|
|
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, "<Image>/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,
|
|
PikaProcedureConfig *config,
|
|
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)
|
|
{
|
|
PikaProcedure *procedure;
|
|
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"));
|
|
|
|
procedure = pika_pdb_lookup_procedure (pika_get_pdb (),
|
|
"pika-plug-ins-query");
|
|
return_vals = pika_procedure_run (procedure,
|
|
"search-string", search_text,
|
|
NULL);
|
|
|
|
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));
|
|
}
|