# Download class implementation for Insight. # Copyright (C) 1999, 2001 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License (GPL) 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. # ---------------------------------------------------------------------- # Download window and associated procs # # ---------------------------------------------------------------------- itcl::body Download::constructor {args} { global gdb_pretty_name debug $args eval itk_initialize $args window_name "Download Status" "Download" add_hook download_progress_hook "$this update_download" label $itk_interior.dload -text "Downloading $filename to $gdb_pretty_name" label $itk_interior.stat set f [frame $itk_interior.f] set i 0 while {$i <$num_sections} { iwidgets::feedback $f.meter$i -steps $num_steps grid forget [$f.meter$i component percentage] label $f.sec$i -text [lindex $section(names) $i] -anchor w label $f.num$i -text $bytes($i) -anchor e grid $f.sec$i $f.meter$i $f.num$i -padx 4 -pady 4 -sticky news incr i } grid columnconfigure $f 1 -weight 1 button $itk_interior.cancel -text Cancel -command "$this cancel" \ -state active -width 10 pack $itk_interior.dload -padx 5 -pady 5 -side top -fill x -expand yes pack $itk_interior.stat -padx 5 -pady 5 -expand yes pack $itk_interior.f -padx 5 -pady 5 -fill x -expand yes pack $itk_interior.cancel -padx 5 -pady 5 -side bottom ::update idletasks } # ------------------------------------------------------------------ # METHOD: update_download - update the download meters # ------------------------------------------------------------------ itcl::body Download::update_download { sec num tot } { # Loop through all the sections, marking each as either done or # updating its meter. This will mark all previous sections prior to # SEC as complete. foreach s $section(names) { set i $section($s) if {$s == $sec} { # Advance feedback meter. The iwidgets meter leaves a lot to # be desired. No way to query the current setting. No way to # set the state of the meter by percentage. It only understands # steps, and we must be careful not to step the widget past the # the configured number of steps, or else the meter will be # set wrong. How lame. set steps [expr {$num / $bytes($i) * $num_steps}] if {[expr {$completed_steps($s) + $steps}] > $num_steps} { set steps [expr {$num_steps - $completed_steps($s)}] } incr completed_steps($s) $steps $itk_interior.f.meter$i step $steps break } else { # Section already loaded. Make sure meter is at 100%. if {$completed_steps($s) < $num_steps} { set steps [expr {$num_steps - $completed_steps($s)}] set completed_steps($s) $num_steps $itk_interior.f.meter$i step $steps } } } ::update } # ------------------------------------------------------------------ # METHOD: done - notification that the download is really complete # ------------------------------------------------------------------ itcl::body Download::done { {msg ""} } { bell if {$msg == ""} { # download finished set secs [expr {[clock seconds] - $::download_start_time}] if {$secs == 0} { incr secs } $itk_interior.cancel config -state disabled set bps [expr {8 * $total_bytes / $secs / 1000}] $itk_interior.stat config -text "$total_bytes bytes in $secs seconds ($bps kbps)" # set all indicators to FULL foreach sec $section(names) { set i $section($sec) if {$completed_steps($sec) < $num_steps} { set steps [expr {$num_steps - $completed_steps($sec)}] set completed_steps($sec) $num_steps $itk_interior.f.meter$i step $steps } } } else { # download failed if {$msg != "CANCEL"} { $itk_interior.stat config -text $msg } } # enable OK button $itk_interior.cancel config -state active -text OK -command "delete object $this" ::update } # ------------------------------------------------------------------ # METHOD: cancel - cancel the download # ------------------------------------------------------------------ itcl::body Download::cancel {} { debug "canceling the download" set ::download_cancel_ok 1 } # ------------------------------------------------------------------ # DESTRUCTOR - destroy window containing widget # ------------------------------------------------------------------ itcl::body Download::destructor {} { remove_hook download_progress_hook "$this update_download" } itcl::body Download::do_download_hooks {} { set ::download_timer(ok) 1 } itcl::body Download::download_hash { section num } { global download_timer debug "sec=$section num=$num tot=$total_bytes ok=$::download_cancel_ok" ::update # Only run the timer at discrete times... if {[info exists download_timer(timer)]} { after cancel $download_timer(timer) } set download_timer(timer) [after 100 Download::do_download_hooks] if {![info exists download_timer(ok)] || $download_timer(ok)} { run_hooks download_progress_hook $section $num $total_bytes ::update unset download_timer(timer) set download_timer(ok) 0 } return $::download_cancel_ok } # Download the executable. Return zero for success, and non-zero for error. itcl::body Download::download_it { } { global gdb_exe_name gdb_downloading gdb_loaded global gdb_target_name gdb_pretty_name global gdb_running global tcl_platform debug "exe=$gdb_exe_name downloading=$gdb_downloading" debug " loaded=$gdb_loaded target=$gdb_target_name running=$gdb_running" if {$gdb_downloading || $gdb_exe_name == ""} { return 0 } set gdb_downloading 1 set gdb_loaded 0 # Make sure the source window has had time to be created ::update gdbtk_busy # Only places that load files should do set_exe #set_exe switch [set_target] { ERROR { # target command failed set gdb_downloading 0 gdbtk_idle return 0 } CANCELED { # command cancelled by user set gdb_downloading 0 if {$gdb_running} { # Run the idle hooks (free the UI) gdbtk_update gdbtk_idle } else { gdbtk_idle } return 1 } } if {[string compare $tcl_platform(platform) "windows"] == 0 && [llength [info commands ide_cygwin_path]]} { set f [ide_cygwin_path to_win32 $gdb_exe_name] } else { set f $gdb_exe_name } if {! [file exists $f]} { tk_messageBox -icon error -title GDB -type ok \ -message "Request to download non-existent executable $gdb_exe_name" set gdb_downloading 0 gdbtk_idle return 0 } debug "downloading $gdb_exe_name" set target $gdb_target_name # get load info and total up number of bytes if {[catch {gdb_load_info $gdb_exe_name} val]} { set result "$gdb_exe_name: $val" tk_dialog .load_warn "" "$result" error 0 Ok return 0 } set i 0 set total_bytes 0 set section(names) {} foreach x $val { set s [lindex $x 0] lappend section(names) $s set section($s) $i set b [lindex $x 1] set bytes($i) [expr {double($b)}] incr total_bytes $b set completed_steps($s) 0 incr i } set num_sections $i set ::download_cancel_ok 0 set ::download_start_time [clock seconds] if {[pref getd gdb/load/$target-verbose] == "1"} { # open a detailed download dialog window set download_dialog [ManagedWin::open Download -transient -filename $gdb_exe_name] } else { # raise source windows foreach src [ManagedWin::find SrcWin] { $src reveal $src toolbar downloading } set download_dialog "" } set download_error "" debug "starting load" ::update idletasks if {[catch {gdb_cmd "load $gdb_exe_name"} errTxt]} { debug "load returned $errTxt" if {[regexp -nocase cancel $errTxt]} { set download_error "CANCEL" } else { set download_error $errTxt } set ::download_cancel_ok 1 } debug "Done loading" set gdb_downloading 0 if {$::download_cancel_ok} { set gdb_loaded 0 if {$download_dialog != ""} { catch {$download_dialog done $download_error} } } else { set gdb_loaded 1 if {$download_dialog != ""} { catch {$download_dialog done} } } foreach src [ManagedWin::find SrcWin] { if {$download_error == "CANCEL"} { $src download_progress CANCEL 1 1 } else { $src download_progress DONE 0 $total_bytes $download_error } } set ::download_cancel_ok 0 set download_dialog "" gdbtk_idle return 0 }