[user@localhost ~]$./puniconf_
./home ./about ./plugins ./plugin_API ./screenshots ./download ./old_source
#!/usr/bin/perl -w
################################################
# fbconfig.pl
#   --Configuration program fro blackbox, fluxbox, etc.
#
#TODO:
#   --code add/update btns for men editor
#   --save menu file
#   --
#   --code init file editor
#   --
#   --code style file editor
#   --
#   --code status bar
#   --
#   --split this file into smaller files
##################################################

use Gtk2;
#use strict;
use Gtk2::Gdk::Keysyms;
use Data::Dumper;

init Gtk2;

use constant FALSE => 0;
use constant TRUE => 1;
use constant TEST =>1;

### Global Variables ###

my $menufile="~/.fluxbox/menu";
my $initfile="~/.fluxbox/init";
my $stylesdir="~/.fluxbox/styles";
my $stylefile="";
my $context_id;
my $current_doc_isTainted = FALSE;
my $statusText="";
##################

### GUI Elements###

my $mw = new Gtk2::Window( 'toplevel' );
    my $main_box = new Gtk2::VBox( 0, 0 );
        my $menu_box = new Gtk2::HBox( 1, 0 );
            my $menubar = new Gtk2::MenuBar();
        my $toolbar_box = new Gtk2::HBox( 0, 0 );
            my $toolbar = new Gtk2::Toolbar;
        my $notebook_box = new Gtk2::HBox( 0, 0 );
            my $notebook = new Gtk2::Notebook();
                my $menuEdit_box= new Gtk2::HPaned();
                    my $menuTree_view = new Gtk2::ScrolledWindow( 0,0 );
                        my $menuTree = new Gtk2::TreeView();
                            my $menu_selection;
                            my $menuTreeModel=Gtk2::TreeStore->new(qw/ Glib::String Glib::String Glib::String /);
                            my $selected; #current selection
                         use constant NAMECOL=>0;
                            use constant FXNCOL=>1;
                            use constant CMDCOL=>2;
                            use constant ICNCOL=>3;
                            use constant NUMCOLS=>3;
                    my $menuEditor_view=new Gtk2::Table( 10, 3, 1 );
                    my $menueditor_frame=new Gtk2::Frame( "Options" );
                my $initEdit_box= new Gtk2::HPaned();
                my $styleEdit_box= new Gtk2::HPaned();
        my $status_box = new Gtk2::HBox( 0, 0 );
            my $status = new Gtk2::Statusbar(); 
        
my $filesel = new Gtk2::FileSelection( "Select File" );


######################################
###         Editing Panes          ###
######################################

######################################
###         Menu Edit              ###


#Title column
my $renderer = Gtk2::CellRendererText->new;
$renderer->set (xalign => 0.0);

my $col_offset = $menuTree->insert_column_with_attributes 
                    (-1, "Title", $renderer,
                     text => NAMECOL);
my $column = $menuTree->get_column ($col_offset - 1);
$column->set_clickable (TRUE);

#Type  column
$renderer = Gtk2::CellRendererText->new;
$renderer->set (xalign => 0.0);

$col_offset = $menuTree->insert_column_with_attributes 
                    (-1, "Type", $renderer,
                     text => FXNCOL);
$column = $menuTree->get_column ($col_offset - 1);
$column->set_clickable (TRUE);

#Command column
$renderer = Gtk2::CellRendererText->new;
$renderer->set (xalign => 0.0);

$col_offset = $menuTree->insert_column_with_attributes 
                    (-1, "Command", $renderer,
                     text => CMDCOL);
$column = $menuTree->get_column ($col_offset - 1);
$column->set_clickable (TRUE);


$menuTree->set_rules_hint (TRUE);
#$menuTree->signal_connect( "select_cursor_row", \&select_row ); 
$menuTree->show;

my $function_entry = new Gtk2::Entry;
my $function_sel = new Gtk2::OptionMenu;
my $title_entry = new Gtk2::Entry();
my $cmd_entry = new Gtk2::Entry();

my $browse_btn = new Gtk2::Button('Browse');
my $add_btn = new Gtk2::Button('Add');
my $update_btn = new Gtk2::Button('Update');

#build popup function menu
my @Fxn_Menu=('Submenu', 
                        'Exec', 
                        'Include', 
                        'Nop', 
                        'Style',
                        'StylesDir',
                        'StylesMenu',
                        'Reconfig',
                        'Restart',
                        'Workspaces');
$function_sel->set_menu(&getMenu(@Fxn_Menu));
$function_sel->signal_connect( "changed",  sub {$function_entry->set_text( $Fxn_Menu[$function_sel->get_history])}); 
$function_sel->show;
$function_entry->show;
$add_btn->signal_connect( "clicked", sub{update_tree("add");});
$update_btn->signal_connect( "clicked", sub{update_tree("update");});

$menuEditor_view->attach( (new Gtk2::Label("Function:")), 0, 1, 1, 2, [], [],  0, 0 );
$menuEditor_view->attach( $function_entry, 1, 3, 1, 2, ['fill','expand','shrink'], [], 0, 0 );
$menuEditor_view->attach( $function_sel, 3, 4, 1, 2, ['fill','expand','shrink'], [], 0, 0 );

$menuEditor_view->attach( (new Gtk2::Label("Menu Title:")), 0, 1, 2, 3, [], [],  0, 0 );
$menuEditor_view->attach_defaults( $title_entry, 1, 4, 2, 3);

$menuEditor_view->attach( (new Gtk2::Label("Command:")), 0, 1, 3, 4, [], [],  0, 0 );
$menuEditor_view->attach( $cmd_entry, 1, 3, 3, 4, ['fill','expand','shrink'], [], 0, 0 );
$menuEditor_view->attach( $browse_btn, 3, 4, 3, 4, [], [], 0, 0 );

$menuEditor_view->attach( $add_btn, 2, 3, 5, 6, [], [], 0, 0 );
$menuEditor_view->attach( $update_btn, 3, 4, 5, 6, [], [], 0, 0 );

$menuEditor_view->show_all();


$menuTree_view->add_with_viewport($menuTree);
$menuTree_view->show_all();

$menueditor_frame->add($menuEditor_view);
$menueditor_frame->set_label_align(.5,0);
$menueditor_frame->set_shadow_type('etched_out');
$menueditor_frame->show;

$menuEdit_box->pack1( $menuTree_view, 1, 1 );
$menuEdit_box->pack2( $menueditor_frame, 1, 1 );

$menuEdit_box->show;

###        Menu Edit               ###
######################################

######################################
###        Init  Edit              ###


$initEdit_box->show();
###        Init Edit               ###
######################################
######################################
###        Style Edit              ###


$styleEdit_box->show();
###        Style Edit              ###
######################################




######################################
###            Widows              ###
######################################

######################################
###         Main Window            ###

#set window props
$mw->set_title( "FBConfig" );
$mw->set_default_size (600, 400);
$mw->signal_connect( "destroy"=> \&exit_app );
$mw->realize();

###############
### menubar ###

my $file_mnu_root = new Gtk2::MenuItem( "File" );
my $file_mnu = new Gtk2::Menu();
    my $open_item = new Gtk2::MenuItem( "Open" );
        $file_mnu->append( $open_item );
        $open_item->signal_connect( 'activate', sub{$filesel->show();} );
        $open_item->show();
    my $save_item = new Gtk2::MenuItem( "Save" );
        $file_mnu->append( $save_item );
        $save_item->signal_connect( 'activate', \&file_save );
        $save_item->show();
    my $quit_item = new Gtk2::MenuItem( "Quit" );
        $file_mnu->append( $quit_item );
        $quit_item->signal_connect( 'activate', \&exit_app );
        $quit_item->show();
$file_mnu_root->set_submenu( $file_mnu );
$file_mnu_root->show();
my $help_mnu_root = new Gtk2::MenuItem( "Help" );
my $help_mnu = new Gtk2::Menu();
    my $help_item = new Gtk2::MenuItem( "Help" );
        $help_mnu->append( $help_item );
        $help_item->signal_connect( 'activate', \&show_help );
        $help_item->show();
    my $about_item = new Gtk2::MenuItem( "About" );
        $help_mnu->append( $about_item );
        $about_item->signal_connect( 'activate', \&show_about );
        $about_item->show();

$help_mnu_root->set_submenu( $help_mnu );
$help_mnu_root->show();

$menubar->append( $file_mnu_root );
$menubar->append( $help_mnu_root );

$menubar->show();

$menu_box->pack_start( $menubar, 1, 1, 0 ); 

$menu_box->show();

### menubar ###
###############

###############
### toolbar ###
 $toolbar->insert_stock ('gtk-open',
                              "Opens File for editing.",
                              undef,
                              sub{$filesel->show();},
                              $mw, # user data for callback
                              -1);  # -1 means "append"

    $toolbar->insert_stock ('gtk-quit',
                              "Quits",
                              undef,
                              \&exit_app,
                              $mw, # user data for callback
                              -1);  # -1 means "append"

    $toolbar->append_space;


#$toolbar->border_width( 0 );
#$toolbar->set_space_size( 0 );

#my $open_button = $toolbar->append_item( "Open",
#                      "Open a file",
#                      "Private",
#                      &getImage("open") );
#   $open_button->signal_connect( "clicked", sub{$filesel->show();} );
#my $close_button = $toolbar->append_item( "Close",
#                      "Close this app",
#                      "Private",
#                      &getImage("exit") );
#   $close_button->signal_connect( "clicked", \&exit_app );

$toolbar->show();
$toolbar_box->pack_start( $toolbar, 1, 1, 0 ); 
$toolbar_box->show();

### toolbar ###
############


##############
### NoteBook ###


$notebook->set_tab_pos( 'top' );
$notebook->append_page($menuEdit_box, (new Gtk2::Label( "Menu" )));
$notebook->append_page($initEdit_box, (new Gtk2::Label( "Init" )));
$notebook->append_page($styleEdit_box, (new Gtk2::Label( "Style" )) );

$notebook->show();
$notebook_box->pack_start( $notebook, 1, 1, 1 ); 
$notebook_box->show();

### NoteBook ###
##############


##############
### Status Bar ###

my @context_id;
showStatus("Welcome to $0");
$status->show();

$status_box->pack_start( $status, 1, 1, 0 ); 
$status_box->show();

### Status Bar ###
##############





$main_box->pack_start($menu_box , 0, 0, 0);
$main_box->pack_start( $toolbar_box , 0, 0, 0);
$main_box->pack_start( $notebook_box , 1, 1, 0);
$main_box->pack_start( $status_box , 0, 0, 0);
$main_box->show;
$mw->add( $main_box );


###          Main Window           ###
######################################





######################################
###     File Selection Dialog      ###

# Connect the ok_button to file_ok_sel function
$filesel->ok_button->signal_connect( "clicked",
                     \&file_ok_sel,
                     $filesel );

# Connect the cancel_button to destroy the widget
$filesel->cancel_button->signal_connect( "clicked",
                         sub { $filesel->destroy; } );

# Set the filename, 
$filesel->set_filename( $menufile );

###    File Selection Dialog       ###
######################################


#$mw->add( $mainlayout );

$mw->show;

Gtk2->main;
#Gtk2->main_quit;
exit 0 ;

######################################
###       Global Routines          ###
######################################

sub file_ok_sel
{
   my ( $widget, $file_selection ) = @_;
   $menufile = $file_selection->get_filename();

   #print( "$menufile\n" );
   &makemodel();
   $file_selection->destroy;
}


#this just manipulates the status ba. Pass in the string to display as a parameter.
sub showStatus{
    my ( $statusText) = @_;
    if ($context_id[0]){
        pop @context_id;
    }
    push (@context_id , $status->get_context_id( "$statusText" ) );

    $status->push( $context_id[-1], $statusText );
}

#
# getImage() is used to display the toolbar images.
# The parameter is the name of the file in pixmaps/, without the .xpm extension.
#
sub getImage {
    my $file = "pixmaps/".$_[0].".xpm";
    
    if (-e $file){
        my ( $icon, $mask ) = Gtk2::Gdk::Pixmap->create_from_xpm( $mw->window,
                            $mw->style->white,
                            $file );
    
        return ( new Gtk2::Pixmap( $icon, $mask ) );
    } else {
        return undef;
    }
}

#
# Place all closing code here.
# If a doc hasn't been saved, then ask to save it.
sub exit_app {
    if ($current_doc_isTainted) {
        #prompt user to save
 }
    #$mw->destroy;
 Gtk2->main_quit;
    exit 0;
}


# this function actually creates the menu tree. 
sub makemodel {
    my @nodes;
    
    open (MENUFILE, $menufile) || return;
    
    foreach $thistr (<MENUFILE>){
        #chomp;
     #my $thistr=$_;
             
        if ($thistr=~m/^\s*#/){
         #do nothing
     } elsif ($thistr=~m/\[(\s*)begin(\s*)\]/){              #begins menu
         $thistr=~m/\(.*\)/;                                 #matches name of menu
         $thistr=$&;                                         #thistr= name of menu
         $thistr=~s/\(//;$thistr=~s/\)//;                    #delete parens
         push(@nodes, $menuTreeModel->append(undef) );       #add to tree as node
         $menuTreeModel->set($nodes[-1],NAMECOL,"$thistr" ); #fill in vals in row
     } elsif ($thistr=~m/\[(\s)*submenu(\s)*\]/){
            $thistr=~m/\(.*\)/;
            $thistr=$&;
            $thistr=~s/\(//;$thistr=~s/\)//;
            push(@nodes, $menuTreeModel->append( $nodes[-1] ) ) ;
            $menuTreeModel->set($nodes[-1],NAMECOL,"$thistr" );
        } elsif ($thistr=~m/\[(\s)*end(\s)*\]/){
            pop (@nodes);
        } else {
            my $temp=$thistr;
            $temp=~m/\[.*\]/;
            my $fxn=$&;$fxn=~s/\[//;$fxn=~s/\]//;
            
            $temp=$thistr;$temp=~m/\(.*\)/;
            my $title=$&;$title=~s/\(//;$title=~s/\)//;
            
            $temp=$thistr;$temp=~m/\{.*\}/;
            my $cmd=$&;
            $cmd=~s/\{//;$cmd=~s/\}//;
            #showStatus( "Number of Iters in \@parentIters is $nodes[-1] \n");
         if($title){
                my $childIter=$menuTreeModel-> append($nodes[-1]);
                $menuTreeModel-> set( $childIter, NAMECOL,"$title", FXNCOL,"$fxn",CMDCOL,"$cmd" );
            }
        }
    }
    close (MENUFILE);
    $menuTree->set_model($menuTreeModel);
    $menuTree->set_expander_column (NAMECOL);
    $menu_selection = $menuTree->get_selection;
    $menu_selection->set_mode ('browse');
    $menu_selection->signal_connect (changed => \&select_row, $menuTreeModel);
    #$menuTree->signal_connect (row_activated => \&row_activated, $menuTreeModel);
}

#this is just here so select_row can work. don't ask me why, but it needs to be here.
sub row_activated {

}
#
# Callback when a row is selected
#
sub select_row   {
    my ($selection, $model) = @_;
    $selected = $selection->get_selected;
    showStatus("Could not get selection.\n") if !($selected);
    return unless $selected;
    
    my $title = $model->get ($selected, NAMECOL);
    my $fxn = $model->get ($selected, FXNCOL);
    my $cmd = $model->get ($selected, CMDCOL);
    #my $icn = $model->get ($selected, ICNCOL);
 
    $title_entry->set_text( $title ) if $title; 
    $cmd_entry->set_text( $cmd ) if $cmd;$cmd_entry->set_text("") if !($cmd);
    $function_entry->set_text( $fxn ) if $fxn;$function_entry->set_text("") if !($fxn);
    $fxn="Submenu" if !($fxn);
    $function_sel->set_history( &which_index($fxn,@Fxn_Menu) );
}

#which_index takes a string and an array and returns the index of that string in the array
#   For my purposes, it is only used to change the value of the option menu for the
#       menu editor when a row is selected.
sub which_index{
    local ($str,@ompare)=@_;
    local ($cnt,$ret)=0;
    
    foreach $i (@ompare){ 
        $ret=$cnt if ( lc($str) eq lc($i) );
        $cnt++;
    }
    return $ret;
}




#getMenu() returns a menu widget based on an array. Used for the menueditor->popupmenu
sub getMenu {
    my @list = @_;
    my $menu =  Gtk2::Menu->new;
    my $menuitem;
    #$menu->set_title($list[0]);
 my $i;
    foreach $i (@list){ 
        $menuitem = Gtk2::MenuItem->new_with_label ($i);
        $menu->append($menuitem);
        $menuitem->show;        
    }
    return $menu;

}

#updates item to menutree
#to update:
#   $menuTreeModel->set_value($iter, $column,$value)
#   $menuTreeModel->set($iter, COL1, $value1, COL2, $value2, ... ,-1)
#to add:
#   $iter=$menu_selection->get_selection()
#   $menuTreeModel->insert_after($iter)
sub update_tree {
    my ($type)=@_;
    local $iter;
    $menu_selection = $menuTree->get_selection;
    $iter = $menu_selection->get_selected;
    $path=$menuTreeModel->get_path($iter)->to_string;
    if ($type eq 'add'){
        $iter=$menuTreeModel->insert_after('',$iter);
        $path=$menuTreeModel->get_path($iter)->to_string;
        showStatus("Added to $path.");
    }
    
    if ($type eq 'update'){
        showStatus("Updated $path.");
    }
        $menuTreeModel-> set( $iter, 
                                NAMECOL,$title_entry->get_text, 
                                CMDCOL,$cmd_entry->get_text,
                                FXNCOL,lc($function_entry->get_text) );
}


#
#this function saves the file
#
sub file_save {
    my $out="#this file generated by fbConfig by Skaman Sam . Copyleft 2003.\n";
 my @spaceholder;
    #$menuTreeModel->foreach(\&printrow,\$out);
 
    #my $iter=$menuTreeModel->get_iter_first;
 $path=new_first Gtk2::TreePath;
    get_child($menuTreeModel,$path,\$out);
    warn ($out);
    
}


sub get_child{

    local ($model,$path,$out)=@_;
    
    local $iter=$model->get_iter($path);
    
    #warn "iter has ".$model->iter_n_children($iter)." children.\n";
 for (my $cnt=0; $cnt<$model->iter_n_children($iter);$cnt++){
        #local $parent=$model->get_iter($path);
     #$model->iter_parent($parent);
     
        $iter=$model->iter_nth_child($model->iter_parent($parent),$cnt);
        
        local $name=$model->get ($iter, NAMECOL) if ($model->get ($iter, NAMECOL));
        local $fxn=$model->get ($iter, FXNCOL) if ($model->get ($iter, FXNCOL));
        local $cmd=$model->get ($iter, CMDCOL) if ($model->get ($iter, CMDCOL));

        #$$out.=join(@spaceholder,"  ");
     $$out.="[".$fxn."] " if $fxn;
        $$out.="(".$name.") " if $name;
        $$out.="{".$cmd."}" if $cmd;
        $$out.="\n";
        warn $$out;
        
        #$model->iter_next($iter);
     
        if ($model->iter_has_child($iter)){
            $path->down;
            get_child($model,$path,$out);
        } else {
        }
    }
        $$out.="[end]\n";

}


#
#this function is used to traverse a Gtk2::TreeModel and output all data in the tree to a variable
#printrow() takes a few variables
#   $treeStore   => the Gtk2::Treestore you want to read from (passed in auto. by foreach())
#   $TreePath   => the Gtk2::TreePath you want to read from (passed in auto. by foreach())
#   $CurIter      => the Gtk2::TreeModel->get_iter you want to read from (passed in auto. by foreach())
#   \$in                 => the data you want to add to
#
sub printrow{
    local ($model,$treePath,$iter,$out) = @_;
    
    #if no iter, then return and end traversal
 return TRUE if (!$iter);
    
    #prints the path of the current iter
 #$$out.=$treePath->to_string if TEST;
 
    #adds the submenu and begin parts to the output
 if($model->iter_has_child($iter)){
        if ($treePath->to_string eq '0'){
            $$out.="[begin] " ;
        }  else {
            $$out.="[submenu] ";
        }
        push(@spaceholder,"  ");
    }
    
    
    local $name=$model->get ($iter, NAMECOL) if ($model->get ($iter, NAMECOL));
    local $fxn=$model->get ($iter, FXNCOL) if ($model->get ($iter, FXNCOL));
    local $cmd=$model->get ($iter, CMDCOL) if ($model->get ($iter, CMDCOL));

    $$out.=join(@spaceholder,"  ");
    $$out.="[".$fxn."] " if $fxn;
    $$out.="(".$name.") " if $name;
    $$out.="{".$cmd."}" if $cmd;
    $$out.="\n";
    
    #adds the '[end]' to the end of the submenu
 #local $tmpPath= new Gtk2::TreePath;
 $tmpIter=$model->get_iter_first;
    $tmpIter=$iter;
    
    if (! $model->iter_next($tmpIter)){
        if ($treePath->to_string eq '0'){
        
        }  else {
            $$out.=join(@spaceholder,"  ");
            $$out.="[end]\n";
            pop(@spaceholder);
            return FALSE;
        }
    }
    $model->iter_prev($iter);
    
    #$in.=$out;
 #warn $out;
 return FALSE;
    
}


SourceForge.net Logo Support This Project


This site created, maintained and operated by "Skaman" Sam Tyler, using SaMS content management software. If you like any of the ideas on these pages, feel free to help out, by e-mailing him at SkamanSam@punks.net