Version 1 of Tickmassfiler

Updated 2004-05-25 01:04:13 by GPS

GPS: I wanted a file manager that would ease the burden of working with hundreds of videos. I looked around at a few and decided that I didn't like any of them. I normally use a few xterm with pdksh, but that doesn't cut it sometimes.

The file manager should organize the files alphabetically, but only display the files with a specific prefix or * for all. The file manager updates the view of files if the directory I'm in changes (from removal or addition). The "Do this:" entry is the command to run when a file is clicked. This is not a conventional file manager, but I find it useful. It isn't a "do everything for you" file manager.


 #Tickmassfiler-3
 #By George Peter Staplin

 option add *Scrollbar.relief raised
 option add *Scrollbar.borderWidth 1
 option add *Scrollbar.elementBorderWidth 0
 option add *Scrollbar.troughColor royalblue3

 set ::directory_time_stamp [file mtime [pwd]]

 proc change.directory {} {
  set dir [.fdirs.l get [.fdirs.l curselection]]
  cd $dir
  fill.with [glob -nocomplain .* *] 
  set.title.directory [pwd]
 }

 proc create.gui {} {
  frame .fdirs 
  scrollbar .fdirs.yscroll -command {.fdirs.l yview}
  scrollbar .fdirs.xscroll -orient horizontal \
   -command {.fdirs.l xview}
  listbox .fdirs.l \
   -xscrollcommand {.fdirs.xscroll set} \
   -yscrollcommand {.fdirs.yscroll set}

  frame .fprefix
  scrollbar .fprefix.yscroll -command {.fprefix.l yview}
  listbox .fprefix.l -width 4 \
   -yscrollcommand {.fprefix.yscroll set}

  frame .ffiles
  scrollbar .ffiles.yscroll -command {.ffiles.l yview}
  scrollbar .ffiles.xscroll -orient horizontal \
   -command {.ffiles.l xview}
  listbox .ffiles.l \
   -xscrollcommand {.ffiles.xscroll set} \
   -yscrollcommand {.ffiles.yscroll set}

  frame .fdo
  label .fdo.l -text "Do this:" -anchor w
  entry .fdo.e -text ::cmd
  button .fdo.kill -text Kill -command {catch {exec kill -9 $::last_pid}}
 }

 proc do.file {} {
  if {[catch {.ffiles.l get [.ffiles.l curselection]} f]} {
   #We probably had no files in our listbox, and the user clicked a button.
   return
  }
  if {[catch {eval exec -- $::cmd \$f &} pid]} {
   tk_messageBox -title Error -message $pid
   return
  }
  set ::last_pid $pid
 }

 proc every {n body} {
  uplevel #0 $body
  after $n [list every $n $body]
 }

 proc fill.prefix.with files {
  .fprefix.l delete 0 end
  .fprefix.l insert end *
  array set prefix_ar {}
  foreach f $::cur_files {
   set c [string toupper [string index $f 0]]
   if {[info exists prefix_ar($c)]} continue
   .fprefix.l insert end $c
   set prefix_ar($c) {}
  }
 }

 proc fill.with files {
  .fdirs.l delete 0 end
  .ffiles.l delete 0 end
  .fdirs.l insert end . ..
  set ::cur_files [list]
  foreach f [lsort -dictionary -unique $files] {
   if {"." == $f || ".." == $f} {
    continue
   } elseif {[file isdirectory $f]} {
    .fdirs.l insert end $f
    continue
   } 
   #We could do the fill.prefix.with code here ...
   lappend ::cur_files $f
  } 
  fill.prefix.with $::cur_files
 }

 proc insert.all.files {} {
  foreach f $::cur_files {
   .ffiles.l insert end $f
  }
 }

 proc insert.files.with.prefix prefix {
  foreach f $::cur_files {
   if {[string equal -nocase [string index $f 0] $prefix]} {
    .ffiles.l insert end $f
   }
  }
 }

 proc load.files {} {
  .ffiles.l delete 0 end
  set c [.fprefix.l get [.fprefix.l curselection]]
  if {[string equal $c "*"]} {
   insert.all.files
   return
  }
  insert.files.with.prefix $c
 }

 proc manage.gui {} {
  grid .fdirs.yscroll -row 0 -column 0 -sticky ns
  grid .fdirs.l -row 0 -column 1 -sticky news
  grid .fdirs.xscroll -row 1 -column 1 -sticky we
  grid rowconfigure .fdirs 0 -weight 100
  grid columnconfigure .fdirs 1 -weight 100

  bind .fdirs.l <<ListboxSelect>> change.directory

  grid .fprefix.yscroll -row 0 -column 0 -sticky ns
  grid .fprefix.l -row 0 -column 1 -sticky news
  grid rowconfigure .fprefix 0 -weight 100

  bind .fprefix.l <<ListboxSelect>> load.files

  grid .ffiles.yscroll -row 0 -column 0 -sticky ns
  grid .ffiles.l -row 0 -column 1 -sticky news
  grid .ffiles.xscroll -row 1 -column 1 -sticky we
  grid rowconfigure .ffiles 0 -weight 100
  grid columnconfigure .ffiles 1 -weight 100

  bind .ffiles.l <<ListboxSelect>> do.file

  grid .fdo.l -row 0 -column 0 -sticky w
  grid .fdo.e -row 0 -column 1 -sticky we
  grid .fdo.kill -row 0 -column 2
  grid columnconfigure .fdo 1 -weight 100


  grid .fdirs -row 0 -column 0 -sticky news
  grid .fprefix -row 0 -column 1 -sticky news
  grid .ffiles -row 0 -column 2 -sticky news
  grid .fdo -row 1 -column 0 -columnspan 3 -sticky we
  grid rowconfigure . 0 -weight 100
  grid columnconfigure . 0 -weight 80
  grid columnconfigure . 2 -weight 100
 }

 proc refill.if.needed {} {
  if {[file mtime [pwd]] == $::directory_time_stamp} {
   #There were no changes to our directory.
   return 
  }
  #save our existing state
  set pxview [lindex [.fprefix.l xview] 0]
  set pyview [lindex [.fprefix.l yview] 0]
  set fxview [lindex [.ffiles.l xview] 0]
  set fyview [lindex [.ffiles.l yview] 0]

  set cursel [.fprefix.l curselection]
  if {"" == $cursel} {
   set c *
  } else {
   set c [.fprefix.l get $cursel]
  }

  fill.with [glob -nocomplain .* *]
  set ::directory_time_stamp [file mtime [pwd]]

  #restore our old state (as much as possible)
  set prefix_list [.fprefix.l get 0 end]
  set i [lsearch $prefix_list $c]
  if {$i < 0} {
   #The change to the directory removed the old prefix.
   return
  } 
  .fprefix.l selection clear 0 end
  .fprefix.l selection set $i $i
  load.files
  .fprefix.l xview moveto $pxview
  .fprefix.l yview moveto $pyview
  .ffiles.l xview moveto $fxview
  .ffiles.l yview moveto $fyview
 }

 proc set.title.directory dir {
  wm title . "Tickmassfiler viewing: $dir"
 }

 proc main {} {
  wm geometry . 400x600
  create.gui
  manage.gui
  fill.with [glob -nocomplain .* *]
  set.title.directory [pwd]
  every 2000 refill.if.needed
 }
 main

Category Application