1999-02-04 09:31:33 +08:00
/*
* Copyright ( C ) 1995 Spencer Kimball and Peter Mattis
*
* This is a plug - in for the GIMP .
*
* Copyright ( C ) 1999 Andy Thomas alt @ picnic . demon . co . uk
*
* Note some portions of th 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 2 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 , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <time.h>
# include "gtk/gtk.h"
# include "libgimp/gimp.h"
# define DBL_LIST_WIDTH 250
# define DBL_WIDTH DBL_LIST_WIDTH+450
# define DBL_HEIGHT 200
static char * proc_type_str [ ] =
{
" Internal GIMP procedure " ,
" GIMP Plug-In " ,
" GIMP Extension " ,
" Temporary Procedure "
} ;
/* Declare some local functions.
*/
static void query ( void ) ;
static void run ( char * name ,
int nparams ,
GParam * param ,
int * nreturn_vals ,
GParam * * return_vals ) ;
static GtkWidget * gimp_plugin_desc ( ) ;
static gint procedure_clist_select_callback ( GtkWidget * widget ,
gint row ,
gint column ,
GdkEventButton * bevent ,
gpointer data ) ;
static gint procedure_ctree_select_callback ( GtkWidget * widget ,
GtkWidget * row ,
gint column ,
gpointer data ) ;
GPlugInInfo PLUG_IN_INFO =
{
NULL , /* init_proc */
NULL , /* quit_proc */
query , /* query_proc */
run , /* run_proc */
} ;
MAIN ( )
static void
query ( )
{
static GParamDef args [ ] =
{
{ PARAM_INT32 , " run_mode " , " Interactive, [non-interactive] " }
} ;
static int nargs = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
gimp_install_procedure ( " plug_in_details " ,
" Displays plugin details " ,
" Helps browse the plugin menus system. You can search for plugin names, sort by name or menu location and you can view a tree representation of the plugin menus. Can also be of help to find where new plugins have installed themselves in the menuing system " ,
" Andy Thomas " ,
" Andy Thomas " ,
" 1999 " ,
" <Toolbox>/Xtns/Plugin Details " ,
" " ,
PROC_EXTENSION ,
nargs , 0 ,
args , NULL ) ;
}
static void
run ( char * name ,
int nparams ,
GParam * param ,
int * nreturn_vals ,
GParam * * return_vals )
{
static GParam values [ 2 ] ;
GRunModeType run_mode ;
GtkWidget * plugin_dialog ;
run_mode = param [ 0 ] . data . d_int32 ;
* nreturn_vals = 1 ;
* return_vals = values ;
values [ 0 ] . type = PARAM_STATUS ;
values [ 0 ] . data . d_status = STATUS_CALLING_ERROR ;
if ( strcmp ( name , " plug_in_details " ) = = 0 )
{
* nreturn_vals = 1 ;
values [ 0 ] . data . d_status = STATUS_SUCCESS ;
plugin_dialog = gimp_plugin_desc ( ) ;
gtk_main ( ) ;
gdk_flush ( ) ;
}
}
typedef struct
{
GtkWidget * dlg ;
GtkWidget * clist ;
GtkWidget * ctree ;
GtkWidget * search_entry ;
GtkWidget * descr_scroll ;
GtkWidget * name_button ;
GtkWidget * blurb_button ;
GtkWidget * scrolled_win ;
GtkWidget * ctree_scrolled_win ;
GtkWidget * info_table ;
1999-02-07 00:34:16 +08:00
GtkWidget * paned ;
GtkWidget * left_paned ;
1999-02-04 09:31:33 +08:00
GtkWidget * info_align ;
gint num_plugins ;
gint ctree_row ;
gint clist_row ;
1999-02-07 00:34:16 +08:00
gint c1size ;
1999-02-04 09:31:33 +08:00
gboolean details_showing ;
} PLUGINDESC , * PLUGINDESCP ;
PLUGINDESCP plugindesc = NULL ;
typedef struct
{
gchar * menu ;
gchar * accel ;
gchar * prog ;
gchar * types ;
gchar * realname ;
gint instime ;
} PINFO , * PINFOP ;
static void
dialog_close_callback ( GtkWidget * widget ,
gpointer data )
/* end of the dialog */
{
PLUGINDESCP pdesc = data ;
gtk_widget_destroy ( pdesc - > dlg ) ;
gtk_main_quit ( ) ;
}
1999-02-07 00:34:16 +08:00
/* Bit of a fiddle but sorta has the effect I want... */
1999-02-04 09:31:33 +08:00
static void
details_callback ( GtkWidget * widget ,
gpointer data )
{
/* Show or hide the details window */
PLUGINDESCP pdesc = data ;
GtkLabel * lab = GTK_LABEL ( GTK_BIN ( widget ) - > child ) ;
if ( pdesc - > details_showing = = FALSE )
{
1999-02-07 00:34:16 +08:00
GTK_PANED ( pdesc - > paned ) - > child1_resize = FALSE ;
gtk_paned_set_handle_size ( GTK_PANED ( pdesc - > paned ) , 10 ) ;
gtk_paned_set_gutter_size ( GTK_PANED ( pdesc - > paned ) , 6 ) ;
1999-02-04 09:31:33 +08:00
gtk_label_set_text ( lab , " Details <<< " ) ;
gtk_widget_show ( pdesc - > descr_scroll ) ;
pdesc - > details_showing = TRUE ;
}
else
{
1999-02-07 00:34:16 +08:00
GtkWidget * p = GTK_WIDGET ( pdesc - > paned ) - > parent ;
GTK_PANED ( pdesc - > paned ) - > child1_resize = TRUE ;
GTK_PANED ( pdesc - > paned ) - > child2_resize = TRUE ;
gtk_paned_set_handle_size ( GTK_PANED ( pdesc - > paned ) , 0 ) ;
gtk_paned_set_gutter_size ( GTK_PANED ( pdesc - > paned ) , 0 ) ;
1999-02-04 09:31:33 +08:00
gtk_label_set_text ( lab , " Details >>> " ) ;
gtk_widget_hide ( pdesc - > descr_scroll ) ;
1999-02-07 00:34:16 +08:00
gtk_paned_set_position ( GTK_PANED ( pdesc - > paned ) , p - > allocation . width ) ; /*plugindesc->c1size);*/
1999-02-04 09:31:33 +08:00
pdesc - > details_showing = FALSE ;
}
}
static gchar *
format_menu_path ( gchar * s )
{
gchar * * str_array ;
gchar * newstr = NULL ;
if ( ! s )
return s ;
str_array = g_strsplit ( s , " / " , 0 ) ;
newstr = g_strjoinv ( " -> " , str_array ) ;
g_strfreev ( str_array ) ;
return newstr ;
}
static gint
procedure_general_select_callback ( PLUGINDESCP pdesc ,
PINFOP pinfo )
{
gchar * selected_proc_blurb ;
gchar * selected_proc_help ;
gchar * selected_proc_author ;
gchar * selected_proc_copyright ;
gchar * selected_proc_date ;
gint selected_proc_type ;
gint selected_nparams ;
gint selected_nreturn_vals ;
GParamDef * selected_params ;
GParamDef * selected_return_vals ;
GtkWidget * label ;
GtkWidget * help ;
GtkWidget * text ;
GtkWidget * vscrollbar ;
GtkWidget * old_table ;
GtkWidget * old_align ;
gint table_row = 0 ;
g_return_val_if_fail ( pdesc ! = NULL , FALSE ) ;
g_return_val_if_fail ( pinfo ! = NULL , FALSE ) ;
selected_proc_blurb = NULL ;
selected_proc_help = NULL ;
selected_proc_author = NULL ;
selected_proc_copyright = NULL ;
selected_proc_date = NULL ;
selected_proc_type = 0 ;
selected_nparams = 0 ;
selected_nreturn_vals = 0 ;
selected_params = NULL ;
selected_return_vals = NULL ;
gimp_query_procedure ( pinfo - > realname ,
& selected_proc_blurb ,
& selected_proc_help ,
& selected_proc_author ,
& selected_proc_copyright ,
& selected_proc_date ,
& selected_proc_type ,
& selected_nparams ,
& selected_nreturn_vals ,
& selected_params ,
& selected_return_vals ) ;
old_table = pdesc - > info_table ;
old_align = pdesc - > info_align ;
pdesc - > info_table = gtk_table_new ( 10 , 5 , FALSE ) ;
pdesc - > info_align = gtk_alignment_new ( 0.5 , 0.5 , 0 , 0 ) ;
gtk_table_set_col_spacings ( GTK_TABLE ( pdesc - > info_table ) , 3 ) ;
/* Number of plugins */
label = gtk_label_new ( g_strdup_printf ( " Number of plugin interfaces :%d " , pdesc - > num_plugins ) ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 0.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 0 , 0 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
label = gtk_hseparator_new ( ) ; /* ok, not really a label ... :) */
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 6 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
/* menu path */
label = gtk_label_new ( " Menu path : " ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 1.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 1 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 0 ) ;
gtk_widget_show ( label ) ;
label = gtk_label_new ( format_menu_path ( pinfo - > menu ) ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 0.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
1 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 0 , 0 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
label = gtk_hseparator_new ( ) ; /* ok, not really a label ... :) */
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 6 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
/* show the name */
label = gtk_label_new ( " Name : " ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 1.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 1 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 6 ) ;
gtk_widget_show ( label ) ;
label = gtk_entry_new ( ) ;
gtk_entry_set_text ( GTK_ENTRY ( label ) , pinfo - > realname ) ;
gtk_entry_set_editable ( GTK_ENTRY ( label ) , FALSE ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
1 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 0 , 0 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
label = gtk_hseparator_new ( ) ; /* ok, not really a label ... :) */
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 6 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
/* show the description */
label = gtk_label_new ( " Blurb : " ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 1.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 1 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 0 ) ;
gtk_widget_show ( label ) ;
label = gtk_label_new ( selected_proc_blurb ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 0.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
1 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 0 , 0 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
label = gtk_hseparator_new ( ) ; /* ok, not really a label ... :) */
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 6 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
/* show the help */
if ( ( selected_proc_help ) & & ( strlen ( selected_proc_help ) > 1 ) )
{
label = gtk_label_new ( " Help : " ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 1.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 1 , table_row , table_row + 1 ,
GTK_FILL , GTK_FILL , 3 , 0 ) ;
gtk_widget_show ( label ) ;
help = gtk_table_new ( 2 , 2 , FALSE ) ;
gtk_table_set_row_spacing ( GTK_TABLE ( help ) , 0 , 2 ) ;
gtk_table_set_col_spacing ( GTK_TABLE ( help ) , 0 , 2 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , help ,
1 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 0 ) ;
gtk_widget_show ( help ) ;
table_row + + ;
text = gtk_text_new ( NULL , NULL ) ;
gtk_text_set_editable ( GTK_TEXT ( text ) , FALSE ) ;
gtk_text_set_word_wrap ( GTK_TEXT ( text ) , TRUE ) ;
gtk_widget_set_usize ( text , - 1 , 60 ) ;
gtk_table_attach ( GTK_TABLE ( help ) , text , 0 , 1 , 0 , 1 ,
GTK_EXPAND | GTK_SHRINK | GTK_FILL ,
GTK_EXPAND | GTK_SHRINK | GTK_FILL , 0 , 0 ) ;
gtk_widget_show ( text ) ;
vscrollbar = gtk_vscrollbar_new ( GTK_TEXT ( text ) - > vadj ) ;
gtk_table_attach ( GTK_TABLE ( help ) , vscrollbar , 1 , 2 , 0 , 1 ,
GTK_FILL , GTK_EXPAND | GTK_SHRINK | GTK_FILL , 0 , 0 ) ;
gtk_widget_show ( vscrollbar ) ;
label = gtk_hseparator_new ( ) ; /* ok, not really a label ... :) */
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 6 ) ;
gtk_widget_show ( label ) ;
gtk_text_freeze ( GTK_TEXT ( text ) ) ;
gtk_text_insert ( GTK_TEXT ( text ) , NULL , NULL , NULL ,
selected_proc_help , - 1 ) ;
gtk_text_thaw ( GTK_TEXT ( text ) ) ;
table_row + + ;
}
/* show the type */
label = gtk_label_new ( " Type : " ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 1.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 1 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 6 ) ;
gtk_widget_show ( label ) ;
label = gtk_label_new ( proc_type_str [ selected_proc_type ] ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 0.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
1 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 0 , 0 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
label = gtk_hseparator_new ( ) ; /* ok, not really a label ... :) */
gtk_table_attach ( GTK_TABLE ( pdesc - > info_table ) , label ,
0 , 4 , table_row , table_row + 1 , GTK_FILL , GTK_FILL , 3 , 6 ) ;
gtk_widget_show ( label ) ;
table_row + + ;
/* Remove old and replace with new */
if ( old_table )
gtk_widget_destroy ( old_table ) ;
if ( old_align )
gtk_widget_destroy ( old_align ) ;
gtk_container_add ( GTK_CONTAINER ( pdesc - > info_align ) , pdesc - > info_table ) ;
gtk_scrolled_window_add_with_viewport ( GTK_SCROLLED_WINDOW ( pdesc - > descr_scroll ) ,
pdesc - > info_align ) ;
gtk_widget_show ( pdesc - > info_table ) ;
gtk_widget_show ( pdesc - > info_align ) ;
if ( selected_proc_blurb )
g_free ( selected_proc_blurb ) ;
if ( selected_proc_help )
g_free ( selected_proc_help ) ;
if ( selected_proc_author )
g_free ( selected_proc_author ) ;
if ( selected_proc_copyright )
g_free ( selected_proc_copyright ) ;
if ( selected_proc_date )
g_free ( selected_proc_date ) ;
if ( selected_params )
g_free ( selected_params ) ;
if ( selected_return_vals )
g_free ( selected_return_vals ) ;
return FALSE ;
}
static void
expand_to ( PLUGINDESCP pdesc , GtkCTreeNode * parent )
{
if ( parent )
{
expand_to ( pdesc , ( GTK_CTREE_ROW ( parent ) ) - > parent ) ;
gtk_ctree_expand ( GTK_CTREE ( pdesc - > ctree ) , parent ) ;
}
}
static gint
procedure_clist_select_callback ( GtkWidget * widget ,
gint row ,
gint column ,
GdkEventButton * bevent ,
gpointer data )
{
PINFOP pinfo ;
GtkCTreeNode * found_node ;
PLUGINDESCP pdesc = data ;
g_return_val_if_fail ( pdesc ! = NULL , FALSE ) ;
pinfo = ( PINFOP ) gtk_clist_get_row_data ( GTK_CLIST ( widget ) , row ) ;
if ( ! pinfo )
return FALSE ;
/* Must select the correct one in the ctree structure */
found_node = gtk_ctree_find_by_row_data ( GTK_CTREE ( pdesc - > ctree ) , NULL , pinfo ) ;
if ( found_node )
{
GtkCTreeRow * ctr ;
GtkCTreeNode * parent ;
int sel_row ;
/* Make sure this is expanded */
ctr = GTK_CTREE_ROW ( found_node ) ;
parent = GTK_CTREE_NODE ( ctr - > parent ) ;
expand_to ( pdesc , parent ) ;
sel_row = gtk_clist_find_row_from_data ( GTK_CLIST ( pdesc - > ctree ) , pinfo ) ;
gtk_widget_hide ( pdesc - > ctree ) ;
gtk_widget_show ( pdesc - > ctree ) ;
gtk_signal_handler_block_by_func ( GTK_OBJECT ( pdesc - > ctree ) , ( GtkSignalFunc ) procedure_ctree_select_callback , pdesc ) ;
gtk_clist_select_row ( GTK_CLIST ( pdesc - > ctree ) , sel_row , - 1 ) ;
gtk_ctree_select ( GTK_CTREE ( pdesc - > ctree ) , found_node ) ;
gtk_clist_moveto ( GTK_CLIST ( pdesc - > ctree ) ,
sel_row ,
0 ,
0.5 , 0.5 ) ;
gtk_signal_handler_unblock_by_func ( GTK_OBJECT ( pdesc - > ctree ) , ( GtkSignalFunc ) procedure_ctree_select_callback , pdesc ) ;
pdesc - > ctree_row = sel_row ;
}
else
{
g_warning ( " Failed to find node in ctree " ) ;
}
return procedure_general_select_callback ( pdesc , pinfo ) ;
}
/* This was an attempt to get around a problem in gtk
* where the scroll windows that contain ctree and clist
* refuse to respond to the moveto funcions unless the
* widgets are visible .
* Still did not work 100 % even after this .
* Note the scrollbars are in the correct position but the
* widget needs to be redrawn at the correct location .
*/
static gint
page_select_callback ( GtkNotebook * notebook ,
GtkNotebookPage * page ,
guint page_num ,
gpointer data )
{
PLUGINDESCP pdesc = data ;
if ( page_num = = 0 )
{
gtk_clist_select_row ( GTK_CLIST ( pdesc - > clist ) , pdesc - > clist_row , - 1 ) ;
gtk_clist_moveto ( GTK_CLIST ( pdesc - > clist ) ,
pdesc - > clist_row ,
0 ,
0.5 , 0.5 ) ;
}
else
{
gtk_clist_select_row ( GTK_CLIST ( pdesc - > ctree ) , pdesc - > ctree_row , - 1 ) ;
gtk_clist_moveto ( GTK_CLIST ( pdesc - > ctree ) ,
pdesc - > ctree_row ,
0 ,
0.5 , 0.5 ) ;
}
return FALSE ;
}
static gint
procedure_ctree_select_callback ( GtkWidget * widget ,
GtkWidget * row ,
gint column ,
gpointer data )
{
PINFOP pinfo ;
PLUGINDESCP pdesc ;
gboolean is_leaf ;
gint sel_row ;
/* row is not a leaf the we have no interest in it */
gtk_ctree_get_node_info ( GTK_CTREE ( widget ) ,
GTK_CTREE_NODE ( row ) ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
& is_leaf ,
NULL ) ;
if ( ! is_leaf )
{
return FALSE ;
}
pdesc = data ;
pinfo = ( PINFOP ) gtk_ctree_node_get_row_data ( GTK_CTREE ( widget ) , GTK_CTREE_NODE ( row ) ) ;
/* Must set clist to this one */
/* Block signals */
gtk_signal_handler_block_by_func ( GTK_OBJECT ( pdesc - > clist ) , ( GtkSignalFunc ) procedure_clist_select_callback , pdesc ) ;
sel_row = gtk_clist_find_row_from_data ( GTK_CLIST ( pdesc - > clist ) , pinfo ) ;
gtk_clist_select_row ( GTK_CLIST ( pdesc - > clist ) , sel_row , - 1 ) ;
gtk_clist_moveto ( GTK_CLIST ( pdesc - > clist ) ,
sel_row ,
0 ,
0.5 , 0.5 ) ;
gtk_signal_handler_unblock_by_func ( GTK_OBJECT ( pdesc - > clist ) , ( GtkSignalFunc ) procedure_clist_select_callback , pdesc ) ;
pdesc - > clist_row = sel_row ;
return procedure_general_select_callback ( pdesc , pinfo ) ;
}
static void
pinfo_free ( gpointer p )
{
PINFOP pinfo = p ;
g_free ( pinfo - > menu ) ;
g_free ( pinfo - > accel ) ;
g_free ( pinfo - > prog ) ;
g_free ( pinfo - > types ) ;
g_free ( pinfo - > realname ) ;
g_free ( pinfo ) ;
}
static GtkCTreeNode *
get_parent ( PLUGINDESCP pdesc , GHashTable * ghash , gchar * mpath )
{
GtkCTreeNode * parent ;
GtkCTreeNode * last_parent ;
gchar * tmp_ptr ;
gchar * str_ptr ;
gchar * leaf_ptr ;
gchar * labels [ 3 ] ;
if ( mpath = = NULL )
return NULL ; /* Parent is root */
parent = g_hash_table_lookup ( ghash , mpath ) ;
if ( parent )
{
/* found node */
return ( parent ) ;
}
/* Next one up */
tmp_ptr = g_strdup ( mpath ) ;
str_ptr = strrchr ( tmp_ptr , ' / ' ) ;
if ( str_ptr = = NULL )
{
/* printf("Root node for %s\n",mpath); */
leaf_ptr = mpath ;
tmp_ptr = " <root> " ;
last_parent = NULL ;
}
else
{
leaf_ptr = g_strdup ( str_ptr + 1 ) ;
* str_ptr = ' \000 ' ;
last_parent = get_parent ( pdesc , ghash , tmp_ptr ) ;
}
labels [ 0 ] = g_strdup ( leaf_ptr ) ;
labels [ 1 ] = g_strdup ( " " ) ;
labels [ 2 ] = g_strdup ( " " ) ;
/* printf("get_parent::creating node %s under %s\n",leaf_ptr,tmp_ptr); */
parent = gtk_ctree_insert_node ( GTK_CTREE ( pdesc - > ctree ) ,
last_parent ,
NULL ,
labels ,
4 ,
NULL ,
NULL ,
NULL ,
NULL ,
FALSE ,
FALSE ) ;
g_hash_table_insert ( ghash , mpath , parent ) ;
return parent ;
}
static void
insert_into_ctree ( PLUGINDESCP pdesc , gchar * name ,
gchar * xtimestr ,
gchar * menu_str ,
gchar * types_str ,
GHashTable * ghash ,
PINFOP pinfo )
{
gchar * labels [ 3 ] ;
gchar * str_ptr ;
gchar * tmp_ptr ;
gchar * leaf_ptr ;
GtkCTreeNode * parent = NULL ;
GtkCTreeNode * leaf_node = NULL ;
/* Find all nodes */
/* Last one is the leaf part */
tmp_ptr = g_strdup ( menu_str ) ;
str_ptr = strrchr ( tmp_ptr , ' / ' ) ;
if ( str_ptr = = NULL )
return ; /* No node */
leaf_ptr = g_strdup ( str_ptr + 1 ) ;
* str_ptr = ' \000 ' ;
/* printf("inserting %s...\n",menu_str); */
parent = get_parent ( pdesc , ghash , tmp_ptr ) ;
/* Last was a leaf */
/* printf("found leaf %s parent = %p\n",leaf_ptr,parent); */
labels [ 0 ] = g_strdup ( name ) ;
labels [ 1 ] = g_strdup ( xtimestr ) ;
labels [ 2 ] = g_strdup ( types_str ) ;
leaf_node = gtk_ctree_insert_node ( GTK_CTREE ( pdesc - > ctree ) ,
parent ,
NULL ,
labels ,
4 ,
NULL ,
NULL ,
NULL ,
NULL ,
TRUE ,
FALSE ) ;
gtk_ctree_node_set_row_data ( GTK_CTREE ( pdesc - > ctree ) , leaf_node , pinfo ) ;
}
static void
get_plugin_info ( PLUGINDESCP pdesc , gchar * search_text )
{
GParam * return_vals ;
int nreturn_vals ;
gint row_count = 0 ;
gchar * * menu_strs ;
gchar * * accel_strs ;
gchar * * prog_strs ;
gchar * * types_strs ;
gchar * * realname_strs ;
gint * time_ints ;
GHashTable * ghash = g_hash_table_new ( g_str_hash , g_str_equal ) ;
if ( ! search_text )
search_text = " " ;
return_vals = gimp_run_procedure ( " gimp_plugins_query " ,
& nreturn_vals ,
PARAM_STRING , search_text ,
PARAM_END ) ;
if ( return_vals [ 0 ] . data . d_status = = STATUS_SUCCESS )
{
int loop ;
pdesc - > num_plugins = return_vals [ 1 ] . data . d_int32 ;
menu_strs = return_vals [ 2 ] . data . d_stringarray ;
accel_strs = return_vals [ 4 ] . data . d_stringarray ;
prog_strs = return_vals [ 6 ] . data . d_stringarray ;
types_strs = return_vals [ 8 ] . data . d_stringarray ;
time_ints = return_vals [ 10 ] . data . d_int32array ;
realname_strs = return_vals [ 12 ] . data . d_stringarray ;
for ( loop = 0 ; loop < return_vals [ 1 ] . data . d_int32 ; loop + + )
{
PINFOP pinfo ;
gchar * labels [ 4 ] ;
gchar * name ;
gchar xtimestr [ 50 ] ;
struct tm * x ;
time_t tx ;
int ret ;
name = strrchr ( menu_strs [ loop ] , ' / ' ) ;
if ( name )
name = name + 1 ;
else
name = menu_strs [ loop ] ;
pinfo = g_new0 ( PINFO , 1 ) ;
tx = time_ints [ loop ] ;
if ( tx )
{
x = localtime ( & tx ) ;
ret = strftime ( xtimestr , sizeof ( xtimestr ) , " %c " , x ) ;
xtimestr [ ret ] = 0 ;
}
else
strcpy ( xtimestr , " " ) ;
pinfo - > menu = g_strdup ( menu_strs [ loop ] ) ;
pinfo - > accel = g_strdup ( accel_strs [ loop ] ) ;
pinfo - > prog = g_strdup ( prog_strs [ loop ] ) ;
pinfo - > types = g_strdup ( types_strs [ loop ] ) ;
pinfo - > instime = time_ints [ loop ] ;
pinfo - > realname = g_strdup ( realname_strs [ loop ] ) ;
labels [ 0 ] = g_strdup ( name ) ;
labels [ 1 ] = g_strdup ( xtimestr ) ;
labels [ 2 ] = g_strdup ( menu_strs [ loop ] ) ;
labels [ 3 ] = g_strdup ( types_strs [ loop ] ) ;
gtk_clist_insert ( GTK_CLIST ( GTK_CLIST ( pdesc - > clist ) ) , row_count ,
labels ) ;
gtk_clist_set_row_data_full ( GTK_CLIST ( pdesc - > clist ) , row_count ,
pinfo , pinfo_free ) ;
row_count + + ;
/* Now do the tree view.... */
insert_into_ctree ( pdesc ,
name ,
xtimestr ,
menu_strs [ loop ] ,
types_strs [ loop ] ,
ghash ,
pinfo ) ;
}
}
gimp_destroy_params ( return_vals , nreturn_vals ) ;
}
static void
dialog_search_callback ( GtkWidget * widget ,
gpointer data )
{
PLUGINDESCP pdesc = data ;
gchar * search_text = NULL ;
if ( widget ! = NULL )
{
/* The result of a button press... read entry data */
search_text = gtk_entry_get_text ( GTK_ENTRY ( plugindesc - > search_entry ) ) ;
}
gtk_clist_freeze ( GTK_CLIST ( pdesc - > ctree ) ) ;
gtk_clist_clear ( GTK_CLIST ( pdesc - > ctree ) ) ;
gtk_clist_freeze ( GTK_CLIST ( pdesc - > clist ) ) ;
gtk_clist_clear ( GTK_CLIST ( pdesc - > clist ) ) ;
get_plugin_info ( pdesc , search_text ) ;
gtk_clist_columns_autosize ( GTK_CLIST ( plugindesc - > clist ) ) ;
gtk_clist_sort ( GTK_CLIST ( pdesc - > clist ) ) ;
gtk_clist_thaw ( GTK_CLIST ( pdesc - > clist ) ) ;
gtk_ctree_sort_recursive ( GTK_CTREE ( pdesc - > ctree ) , NULL ) ;
gtk_clist_thaw ( GTK_CLIST ( pdesc - > ctree ) ) ;
}
static gint
date_sort ( GtkCList * clist ,
gconstpointer ptr1 ,
gconstpointer ptr2 )
{
GtkCListRow * row1 = ( GtkCListRow * ) ptr1 ;
GtkCListRow * row2 = ( GtkCListRow * ) ptr2 ;
/* Get the data for the row */
PINFOP row1_pinfo = row1 - > data ;
PINFOP row2_pinfo = row2 - > data ;
/* Want to sort on the date field */
if ( row2_pinfo - > instime < row1_pinfo - > instime )
{
return ( - 1 ) ;
}
if ( row2_pinfo - > instime > row1_pinfo - > instime )
{
return ( 1 ) ;
}
return ( 0 ) ;
}
static void
clist_click_column ( GtkCList * clist , gint column , gpointer data )
{
if ( column = = 1 )
{
gtk_clist_set_compare_func ( clist , date_sort ) ;
}
else
{
gtk_clist_set_compare_func ( clist , NULL ) ; /* Set back to default */
}
if ( column = = clist - > sort_column )
{
if ( clist - > sort_type = = GTK_SORT_ASCENDING )
clist - > sort_type = GTK_SORT_DESCENDING ;
else
clist - > sort_type = GTK_SORT_ASCENDING ;
}
else
gtk_clist_set_sort_column ( clist , column ) ;
gtk_clist_sort ( clist ) ;
}
static GtkWidget *
gimp_plugin_desc ( )
{
GtkWidget * button ;
GtkWidget * hbox , * searchhbox , * vbox ;
GtkWidget * label , * notebook , * swindow ;
gchar * * argv ;
gint argc ;
gchar * clabels [ 4 ] ;
argc = 1 ;
argv = g_new ( gchar * , 1 ) ;
argv [ 0 ] = g_strdup ( " plugin_desc " ) ;
gtk_init ( & argc , & argv ) ;
gtk_rc_parse ( gimp_gtkrc ( ) ) ;
plugindesc = g_new0 ( PLUGINDESC , 1 ) ;
/* the dialog box */
plugindesc - > dlg = gtk_dialog_new ( ) ;
plugindesc - > details_showing = FALSE ;
gtk_window_set_title ( GTK_WINDOW ( plugindesc - > dlg ) , " Plugin Descriptions " ) ;
gtk_window_position ( GTK_WINDOW ( plugindesc - > dlg ) , GTK_WIN_POS_MOUSE ) ;
gtk_signal_connect ( GTK_OBJECT ( plugindesc - > dlg ) , " destroy " ,
( GtkSignalFunc ) dialog_close_callback ,
plugindesc ) ;
gtk_window_set_policy ( GTK_WINDOW ( plugindesc - > dlg ) , TRUE , TRUE , TRUE ) ;
/* hbox : left=notebook ; right=description */
1999-02-07 00:34:16 +08:00
plugindesc - > paned = hbox = gtk_hpaned_new ( ) ;
1999-02-04 09:31:33 +08:00
gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( plugindesc - > dlg ) - > vbox ) ,
hbox , TRUE , TRUE , 0 ) ;
gtk_widget_show ( hbox ) ;
1999-02-07 00:34:16 +08:00
gtk_paned_set_handle_size ( GTK_PANED ( hbox ) , 0 ) ;
gtk_paned_set_gutter_size ( GTK_PANED ( hbox ) , 0 ) ;
1999-02-04 09:31:33 +08:00
/* left = vbox : the list and the search entry */
1999-02-07 00:34:16 +08:00
plugindesc - > left_paned = vbox = gtk_vbox_new ( FALSE , 0 ) ;
1999-02-04 09:31:33 +08:00
gtk_container_border_width ( GTK_CONTAINER ( vbox ) , 3 ) ;
gtk_paned_add1 ( GTK_PANED ( hbox ) , vbox ) ;
gtk_widget_show ( vbox ) ;
/* left = notebook */
notebook = gtk_notebook_new ( ) ;
gtk_box_pack_start ( GTK_BOX ( vbox ) , notebook , TRUE , TRUE , 0 ) ;
/* list : list in a scrolled_win */
clabels [ 0 ] = g_strdup ( " Name " ) ;
clabels [ 1 ] = g_strdup ( " Ins Date " ) ;
clabels [ 2 ] = g_strdup ( " Menu Path " ) ;
clabels [ 3 ] = g_strdup ( " Image Types " ) ;
plugindesc - > clist = gtk_clist_new_with_titles ( 4 , clabels ) ;
gtk_signal_connect ( GTK_OBJECT ( plugindesc - > clist ) , " click_column " ,
( GtkSignalFunc ) clist_click_column , NULL ) ;
gtk_clist_column_titles_show ( GTK_CLIST ( plugindesc - > clist ) ) ;
swindow = gtk_scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( swindow ) ,
GTK_POLICY_AUTOMATIC , GTK_POLICY_AUTOMATIC ) ;
gtk_clist_set_selection_mode ( GTK_CLIST ( plugindesc - > clist ) ,
GTK_SELECTION_BROWSE ) ;
gtk_widget_set_usize ( plugindesc - > clist , DBL_LIST_WIDTH , DBL_HEIGHT ) ;
gtk_signal_connect ( GTK_OBJECT ( plugindesc - > clist ) , " select_row " ,
( GtkSignalFunc ) procedure_clist_select_callback ,
plugindesc ) ;
label = gtk_label_new ( " List view " ) ;
gtk_notebook_append_page ( GTK_NOTEBOOK ( notebook ) , swindow , label ) ;
gtk_container_add ( GTK_CONTAINER ( swindow ) , plugindesc - > clist ) ;
gtk_widget_show ( plugindesc - > clist ) ;
gtk_widget_show ( swindow ) ;
/* notebook->ctree */
clabels [ 0 ] = g_strdup ( " Menu Path/Name " ) ;
clabels [ 1 ] = g_strdup ( " Ins Date " ) ;
clabels [ 2 ] = g_strdup ( " Image Types " ) ;
plugindesc - > ctree = gtk_ctree_new_with_titles ( 3 , 0 , clabels ) ;
plugindesc - > ctree_scrolled_win =
swindow = gtk_scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( swindow ) ,
GTK_POLICY_AUTOMATIC , GTK_POLICY_AUTOMATIC ) ;
gtk_widget_set_usize ( plugindesc - > ctree , DBL_LIST_WIDTH , DBL_HEIGHT ) ;
gtk_signal_connect ( GTK_OBJECT ( plugindesc - > ctree ) , " tree_select_row " ,
( GtkSignalFunc ) procedure_ctree_select_callback ,
plugindesc ) ;
label = gtk_label_new ( " Tree view " ) ;
gtk_clist_set_column_auto_resize ( GTK_CLIST ( plugindesc - > ctree ) , 0 , TRUE ) ;
gtk_clist_set_column_auto_resize ( GTK_CLIST ( plugindesc - > ctree ) , 1 , TRUE ) ;
gtk_clist_set_column_auto_resize ( GTK_CLIST ( plugindesc - > ctree ) , 2 , TRUE ) ;
gtk_notebook_append_page ( GTK_NOTEBOOK ( notebook ) , swindow , label ) ;
gtk_container_add ( GTK_CONTAINER ( swindow ) , plugindesc - > ctree ) ;
gtk_widget_show ( plugindesc - > ctree ) ;
gtk_widget_show ( swindow ) ;
gtk_signal_connect_after ( GTK_OBJECT ( notebook ) , " switch_page " ,
( GtkSignalFunc ) page_select_callback ,
plugindesc ) ;
gtk_widget_show ( notebook ) ;
/* search entry & details button */
searchhbox = gtk_hbox_new ( FALSE , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( vbox ) ,
searchhbox , FALSE , TRUE , 0 ) ;
gtk_widget_show ( searchhbox ) ;
label = gtk_label_new ( " Search : " ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 0.0 , 0.5 ) ;
gtk_box_pack_start ( GTK_BOX ( searchhbox ) ,
label , TRUE , TRUE , 0 ) ;
gtk_widget_show ( label ) ;
plugindesc - > search_entry = gtk_entry_new ( ) ;
gtk_box_pack_start ( GTK_BOX ( searchhbox ) ,
plugindesc - > search_entry , TRUE , TRUE , 0 ) ;
gtk_widget_show ( plugindesc - > search_entry ) ;
button = gtk_button_new_with_label ( " Details >>> " ) ;
gtk_widget_show ( button ) ;
gtk_signal_connect ( GTK_OBJECT ( button ) , " clicked " ,
( GtkSignalFunc ) details_callback , plugindesc ) ;
gtk_box_pack_start ( GTK_BOX ( searchhbox ) ,
button , TRUE , TRUE , 0 ) ;
/* right = description */
plugindesc - > descr_scroll = gtk_scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( plugindesc - > descr_scroll ) ,
GTK_POLICY_ALWAYS ,
GTK_POLICY_ALWAYS
) ;
gtk_paned_add2 ( GTK_PANED ( hbox ) , plugindesc - > descr_scroll ) ;
gtk_widget_set_usize ( plugindesc - > descr_scroll , DBL_WIDTH - DBL_LIST_WIDTH , 0 ) ;
/* buttons in dlg->action_area */
gtk_container_border_width ( GTK_CONTAINER ( GTK_DIALOG ( plugindesc - > dlg ) - > action_area ) , 0 ) ;
plugindesc - > name_button = gtk_button_new_with_label ( " Search by name " ) ;
GTK_WIDGET_SET_FLAGS ( plugindesc - > name_button , GTK_CAN_DEFAULT ) ;
gtk_signal_connect ( GTK_OBJECT ( plugindesc - > name_button ) , " clicked " ,
( GtkSignalFunc ) dialog_search_callback , plugindesc ) ;
gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( plugindesc - > dlg ) - > action_area ) ,
plugindesc - > name_button , TRUE , TRUE , 0 ) ;
gtk_widget_show ( plugindesc - > name_button ) ;
button = gtk_button_new_with_label ( " Close " ) ;
GTK_WIDGET_SET_FLAGS ( button , GTK_CAN_DEFAULT ) ;
gtk_signal_connect ( GTK_OBJECT ( button ) , " clicked " ,
( GtkSignalFunc ) dialog_close_callback , plugindesc ) ;
gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( plugindesc - > dlg ) - > action_area ) ,
button , TRUE , TRUE , 0 ) ;
gtk_widget_show ( button ) ;
/* now build the list */
dialog_search_callback ( NULL , ( gpointer ) plugindesc ) ;
gtk_widget_show ( plugindesc - > clist ) ;
gtk_widget_show ( plugindesc - > dlg ) ;
1999-02-07 00:34:16 +08:00
plugindesc - > c1size = GTK_PANED ( plugindesc - > paned ) - > child1_size ;
GTK_PANED ( plugindesc - > paned ) - > child1_resize = TRUE ;
1999-02-04 09:31:33 +08:00
return plugindesc - > dlg ;
}