Search code examples
treeviewtcl

Invalid Command and files not populating using treeview in TCL


In my endeavour to create a simple treeview GUI I have come across tree.tcl which is available in the active tcl 8.6 installation.

I've managed to adapt the code to fit my purpose (hardy changed anything) and when I run the code in the same way as the demos for Active TCL 8.6 (via widget) are run the code is running as expected (though I've not tried making any selection of node within tree).

However that is not the case once I copy the code over into my gui application.

The structure is as expected but when I try to expand the nodes I get:

  1. I get invalid command error ERROR: invalid command name "populateTree" command bound to event: "populateTree .fc.tv.tree [.fc.tv.tree focus]"

  2. Now for some reason none of the files within the folders are read i.e. all file types are recognised as Directories hence everything under nodes shown as "dummy"

  3. I'd also like to add filter to only read a specific file type, i.e. *.txt, if I do so then even folders are not read. i.e foreach f [lsort -dictionary [glob -nocomplain -dir $path *]] to foreach f [lsort -dictionary [glob -nocomplain -dir $path *.txt]]

I'd be obliged if someone could help.

GUI IMAGE

    # temp dir to mimic Network dir
    set ::dir "C:/Dev"
    
    proc populateRoots {tree} {
    populateTree $tree [$tree insert {} end -text "Network File" \
    -values [list $::dir directory]]
    }
    
    ## Code to populate a node of the tree
    proc populateTree {tree node} {
    if {[$tree set $node type] ne "directory"} {
    return
    }
    set path [$tree set $node fullpath]
    $tree delete [$tree children $node]
    foreach f [lsort -dictionary [glob -nocomplain -dir $path *]] {
    set type [file type $f]
    set id [$tree insert $node end -text [file tail $f] \
    -values [list $f $type]]
    if {$type eq "directory"} {
    ## Make it so that this node is openable
    $tree insert $id 0 -text dummy ;# a dummy
    $tree item $id -text [file tail $f]/
    } elseif {$type eq "file"} {
    set size [file size $f]
    set ttime [file mtime $f]
    ## Format the file size nicely
    if {$size >= 1024*1024*1024} {
    set size [format %.1f\ GB [expr {$size/1024/1024/1024.}]]
    } elseif {$size >= 1024*1024} {
    set size [format %.1f\ MB [expr {$size/1024/1024.}]]
    } elseif {$size >= 1024} {
    set size [format %.1f\ kB [expr {$size/1024.}]]
    } else {
    append size " bytes"
    }
    $tree set $id size $size
    }
    }
    
    # Stop this code from rerunning on the current node
    $tree set $node type processedDirectory
    }
    
    # ## Create the tree and set it up
    
    
    ttk::treeview $tw.tree -columns {fullpath type size date time} -displaycolumns {size date time} \
    -yscroll "$tw.vsb set" -xscroll "$tw.hsb set"
    ttk::scrollbar $tw.vsb -orient vertical -command "$tw.tree yview"
    ttk::scrollbar $tw.hsb -orient horizontal -command "$tw.tree xview"
    $tw.tree heading \#0 -text "Directory Structure"
    $tw.tree heading size -text "File Size"
    $tw.tree column size -stretch 0 -width 70
    populateRoots $tw.tree
    bind $tw.tree <<TreeviewOpen>> {populateTree %W [%W focus]}
    
    # ## Arrange the tree and its scrollbars in the toplevel
    lower [ttk::frame $tw.dummy]
    pack $tw.dummy -fill both -expand 1
    grid $tw.tree $tw.vsb -sticky nsew -in $tw.dummy
    grid $tw.hsb -sticky nsew -in $tw.dummy
    grid columnconfigure $tw.dummy 0 -weight 1
    grid rowconfigure $tw.dummy 0 -weight 1

Thanks in advance, George


Solution

  • The issue was that the procedure populateTree needed to be ::populateTree so it could be found within the namespace.

    PS: I still can't print selection to console...