source: tags/1.3.4/gui/scripts/bugreport.tcl @ 4722

Last change on this file since 4722 was 4722, checked in by ldelgass, 9 years ago

backport ssl3/tls fix from r4652

File size: 27.0 KB
Line 
1# -*- mode: tcl; indent-tabs-mode: nil -*-
2# ----------------------------------------------------------------------
3#  UTILITY: bugreport
4#
5#  This redefines the usual Tcl bgerror command to install a nicer
6#  looking bug handler.  Bug reports can be submitted back to a
7#  HUBzero-based site as support tickets.  Additional information
8#  can be obtained by defining procedures as bugreport::instrumented
9#  proc (captures entrance/exit from proc) and by calling
10#  bugreport::remark with extra info along the way.
11# ======================================================================
12#  AUTHOR:  Michael McLennan, Purdue University
13#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
14#
15#  See the file "license.terms" for information on usage and
16#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
17# ======================================================================
18option add *BugReport*Label.font {Helvetica -12} startupFile
19option add *BugReport*banner*foreground white startupFile
20option add *BugReport*banner*background #a9a9a9 startupFile
21option add *BugReport*banner*highlightBackground #a9a9a9 startupFile
22option add *BugReport*banner.title.font {Helvetica -18 bold} startupFile
23option add *BugReport*xmit*wrapLength 3i startupFile
24option add *BugReport*expl.width 50 startupFile
25option add *BugReport*expl.font {Helvetica -12} startupFile
26option add *BugReport*expl.boldFont {Helvetica -12 bold} startupFile
27option add *BugReport*comments.l.font {Helvetica -12 italic} startupFile
28option add *BugReport*comments.info.text.font {Helvetica -12} startupFile
29option add *BugReport*details*font {Courier -12} startupFile
30
31namespace eval Rappture::bugreport {
32    # details from the current trouble report, which user may decide to submit
33    variable details
34
35    # status from bugreport::instrumented/remark in case a bug occurs
36    variable extraStack ""
37    variable extraInfo ""
38
39    # assume that if there's a problem launching a job, we should know it
40    variable reportJobFailures 1
41
42    # submit these kinds of tickets by default
43    variable settings
44    set settings(user) $::tcl_platform(user)
45    set settings(type) "automatic"
46    set settings(group) ""
47    set settings(category) "Rappture"
48}
49
50# ----------------------------------------------------------------------
51# USAGE: install
52#
53# Called once in the main program to install this bug reporting
54# facility.  Any unexpected errors after this call will be handled
55# by this mechanism.
56# ----------------------------------------------------------------------
57proc Rappture::bugreport::install {} {
58    ::proc ::bgerror {err} { ::Rappture::bugreport::activate $err }
59}
60
61# ----------------------------------------------------------------------
62# USAGE: activate <error>
63#
64# Used internally to pop up the bug handler whenver a bug is
65# encountered.  Tells the user that there is a bug and logs the
66# problem, so it can be fixed.
67# ----------------------------------------------------------------------
68proc Rappture::bugreport::activate {err} {
69    global env errorInfo
70    variable details
71    variable settings
72
73    if {"@SHOWDETAILS" == $err} {
74        pack propagate .bugreport yes
75        pack forget .bugreport.expl
76        pack forget .bugreport.xmit
77        pack forget .bugreport.done
78        pack forget .bugreport.cntls.show
79        pack .bugreport.cntls -after .bugreport.banner -side bottom -fill x
80        pack .bugreport.details -after .bugreport.banner \
81            -expand yes -fill both -padx 8 -pady 8
82        pack .bugreport.comments -after .bugreport.details \
83            -expand yes -fill both -padx 8 -pady {0 8}
84
85        update idletasks
86        set w [winfo reqwidth .bugreport]
87        set h [winfo reqheight .bugreport]
88        #gah@purdue: temporary hack to force view of dismiss button
89        incr h 300
90        set x [expr {([winfo screenwidth .bugreport]-$w)/2}]
91        if {$x < 0} {set x "+0"} else {set x "+$x"}
92        set y [expr {([winfo screenheight .bugreport]-$h)/2}]
93        if {$y < 0} {set y "-0"} else {set y "+$y"}
94
95        wm geometry .bugreport $x$y
96        raise .bugreport
97        return
98    }
99
100    # gather details so we can submit trouble reports later
101    # do this now, before we do anything with "catch" down below
102    # that might mask the errorInfo
103    register $err
104
105    pack propagate .bugreport yes
106    pack forget .bugreport.details
107    pack forget .bugreport.xmit
108    pack forget .bugreport.done
109    pack .bugreport.cntls.show -side right
110    pack .bugreport.cntls -after .bugreport.banner -side bottom -fill x
111    pack .bugreport.expl -after .bugreport.banner \
112        -expand yes -fill both -padx 8 -pady 8
113    pack .bugreport.comments -after .bugreport.expl \
114        -expand yes -fill both -padx 8 -pady {0 8}
115
116    .bugreport.expl configure -state normal
117    .bugreport.expl delete 1.0 end
118
119    set url [Rappture::Tool::resources -huburl]
120    if {"" != $url} {
121        .bugreport.expl insert end "Something went wrong with this tool.  Help us understand what happened by submitting a trouble report, so we can fix the problem.  If you continue having trouble with this tool, please close it and restart."
122        .bugreport.cntls.send configure -state normal
123        focus .bugreport.cntls.send
124    } else {
125        .bugreport.expl insert end "Something went wrong with this tool.  We would ask you to submit a trouble report about the error, but we can't tell what hub it should be submitted to.  If you continue having trouble with this tool, please close it and restart."
126        pack forget .bugreport.comments
127        .bugreport.cntls.send configure -state disabled
128        focus .bugreport.cntls.ok
129    }
130    fixTextHeight .bugreport.expl
131    .bugreport.expl configure -state disabled
132
133    .bugreport.details.info.text configure -state normal
134    .bugreport.details.info.text delete 1.0 end
135    .bugreport.details.info.text insert end "    USER: $settings(user)\n"
136    .bugreport.details.info.text insert end "HOSTNAME: $details(hostname)\n"
137    .bugreport.details.info.text insert end "PLATFORM: $details(platform)\n"
138    .bugreport.details.info.text insert end "CATEGORY: $details(category)\n"
139    .bugreport.details.info.text insert end "    TOOL: $details(referrer)\n"
140    .bugreport.details.info.text insert end " SESSION: $details(session)\n"
141    .bugreport.details.info.text insert end " SUMMARY: $details(summary)\n"
142    .bugreport.details.info.text insert end "---------\n"
143    .bugreport.details.info.text insert end $details(stackTrace)
144    .bugreport.details.info.text configure -state disabled
145
146    set w [winfo reqwidth .bugreport]
147    set h [winfo reqheight .bugreport]
148    set x [expr {([winfo screenwidth .bugreport]-$w)/2}]
149    if {$x < 0} {set x 0}
150    set y [expr {([winfo screenheight .bugreport]-$h)/2}]
151    if {$y < 0} {set y 0}
152
153    wm geometry .bugreport +$x+$y
154    wm deiconify .bugreport
155    raise .bugreport
156
157    catch {grab set .bugreport}
158    update
159}
160
161# ----------------------------------------------------------------------
162# USAGE: deactivate
163#
164# Used internally to take down the bug handler dialog.
165# ----------------------------------------------------------------------
166proc Rappture::bugreport::deactivate {} {
167    grab release .bugreport
168    wm withdraw .bugreport
169
170    # reset the grab in case it's hosed
171    Rappture::grab::reset
172}
173
174# ----------------------------------------------------------------------
175# USAGE: instrumented <what> <name> <arglist> <body>
176#
177# Used instead of the usual Tcl "proc" or itcl::body to define a
178# procedure that will automatically register information about its
179# execution in the bugreport mechanism.  The <what> parameter should
180# be either "proc" or "itcl::body" or something like that.  When the
181# procedure starts, it pushes its call information onto the stack,
182# then invokes the procedure body, then adds information about the
183# return code.
184# ----------------------------------------------------------------------
185proc Rappture::bugreport::instrumented {what name arglist body} {
186    set avals ""
187    foreach term $arglist {
188        set aname [lindex $term 0]
189        append avals "\$$aname "
190    }
191    uplevel [list $what $name $arglist [format {
192        Rappture::bugreport::remark -enter "PROC %s: %s"
193        set __status [catch {%s} __result]
194        Rappture::bugreport::remark -leave "PROC %s: code($__status) => $__result"
195        switch -- $__status {
196            0 - 2 {
197                return $__result
198            }
199            3 {
200                set __result "invoked \"break\" outside of a loop"
201            }
202            4 {
203                set __result "invoked \"continue\" outside of a loop"
204            }
205        }
206        error $__result $::errorInfo
207    } $name $avals $body $name]]
208}
209
210# ----------------------------------------------------------------------
211# USAGE: remark ?-enter|-leave? <message>
212#
213# Adds the <message> to the current "extraInfo" being kept about the
214# program.  This adds useful debugging info to the report that gets
215# sent back when an unexpected error is trapped.  The -enter and -leave
216# options are used when a bugreport::instrumented proc starts/exits to
217# change the indent level for future messages.
218# ----------------------------------------------------------------------
219proc Rappture::bugreport::remark {args} {
220    variable extraStack
221    variable extraInfo
222
223    if {[llength $args] > 1} {
224        set option [lindex $args 0]
225        set args [lrange $args 1 end]
226        switch -- $option {
227            -enter {
228                if {[llength $args] != 1} {
229                    error "wrong # args: should be \"remark -enter message\""
230                }
231                set mesg [lindex $args 0]
232                if {[llength $extraStack] == 0} {
233                    set extraInfo ""
234                }
235                append extraInfo [remark -indent ">> $mesg"]
236                set extraStack [linsert $extraStack 0 $mesg]
237                return
238            }
239            -leave {
240                if {[llength $args] != 1} {
241                    error "wrong # args: should be \"remark -leave message\""
242                }
243                set mesg [lindex $args 0]
244                set extraStack [lrange $extraStack 1 end]
245                append extraInfo [remark -indent "<< $mesg"]
246                return
247            }
248            -indent {
249                if {[llength $args] != 1} {
250                    error "wrong # args: should be \"remark -indent message\""
251                }
252            }
253            default {
254                error "bad option \"$option\": should be -enter, -leave, -indent"
255            }
256        }
257    }
258    set mesg [lindex $args 0]
259    set nlevel [llength $extraStack]
260    set indent [string repeat { } [expr {2*$nlevel}]]
261    foreach line [split $mesg \n] {
262        append extraInfo "$indent$line\n"
263        set prefix "   "
264    }
265}
266
267# ----------------------------------------------------------------------
268# USAGE: sanitize <string> ?<replacement>?
269#
270# Removes any sensitive information in the bug report.  This is useful
271# for things such as passwords that should be scrubbed out before any
272# ticket is filed.  Replaces the <string> with an optional <replacement>
273# string (or ******** by default).  This is usually called in some sort
274# of "catch" before forwarding the error on to the usual bgerror routine.
275# ----------------------------------------------------------------------
276proc Rappture::bugreport::sanitize {str {repl ********}} {
277    global errorInfo
278    variable extraInfo
279
280    set map [list $str $repl]
281    set errorInfo [string map $map $errorInfo]
282    set extraInfo [string map $map $extraInfo]
283}
284
285# ----------------------------------------------------------------------
286# USAGE: attach <name> <string>
287#
288# Removes any sensitive information in the bug report.  This is useful
289# for things such as passwords that should be scrubbed out before any
290# ticket is filed.  Replaces the <string> with an optional <replacement>
291# string (or ******** by default).  This is usually called in some sort
292# of "catch" before forwarding the error on to the usual bgerror routine.
293# ----------------------------------------------------------------------
294proc Rappture::bugreport::attach {str {repl ********}} {
295    global errorInfo
296    variable extraInfo
297
298    set map [list $str $repl]
299    set errorInfo [string map $map $errorInfo]
300    set extraInfo [string map $map $extraInfo]
301}
302
303
304# ----------------------------------------------------------------------
305# USAGE: submit
306#
307# Takes details currently stored in the panel and registers them
308# as a support ticket on the hosting hub site.  Pops up a panel
309# during the process and informs the user of the result.
310# ----------------------------------------------------------------------
311proc Rappture::bugreport::submit {} {
312    set info [.bugreport.details.info.text get 1.0 end]
313
314    pack propagate .bugreport no
315    pack forget .bugreport.details
316    pack forget .bugreport.expl
317    pack forget .bugreport.comments
318    pack forget .bugreport.cntls
319    pack .bugreport.xmit -after .bugreport.banner -padx 8 -pady 8
320    .bugreport.xmit.title configure -text "Sending trouble report to [Rappture::Tool::resources -hubname]..."
321
322    # send off the trouble report...
323    .bugreport.xmit.icon start
324    set status [catch send result]
325    .bugreport.xmit.icon stop
326
327    pack propagate .bugreport yes
328    pack forget .bugreport.xmit
329    pack .bugreport.expl -after .bugreport.banner -padx 8 -pady 8
330    .bugreport.expl configure -state normal
331    .bugreport.expl delete 1.0 end
332
333    # handle the result
334    if {$status != 0} {
335        # add error to the details field, so we can see it with magic clicks
336        .bugreport.details.info.text configure -state normal
337        .bugreport.details.info.text insert 1.0 "Ticket submission failed:\n$result\n-----\n"
338        .bugreport.details.info.text configure -state disabled
339
340        .bugreport.expl insert end "Oops! Ticket submission failed:\n$result\n\nIf you want to report the original problem, you can file your own trouble report by going to the web site and clicking on the \"Help\" or \"Support\" link on the main navigation bar.  If you continue having trouble with this tool, please close it and restart."
341    } elseif {[regexp {Ticket #([0-9]*) +\((.*?)\) +([0-9]+) +times} $result match ticket extra times]} {
342        .bugreport.expl insert end "This problem has been reported as " "" "Ticket #$ticket" bold " in our system." ""
343        if {[string is integer $times] && $times > 1} {
344            .bugreport.expl insert end "  This particular problem has been reported $times times."
345        }
346        .bugreport.expl insert end "\n\nIf you continue having trouble with this tool, please close it and restart.  Thanks for reporting the problem and helping us improve things!"
347    } else {
348        .bugreport.expl insert end "This problem has been reported.  Here is the response from the hub, which may contain information about your ticket:\n" "" $result bold "\n\nIf you continue having trouble with this tool, please close it and restart.  Thanks for reporting the problem and helping us improve things!" ""
349    }
350    fixTextHeight .bugreport.expl
351    .bugreport.expl configure -state disabled
352    pack .bugreport.done -side bottom -padx 8 -pady 8
353    focus .bugreport.done
354}
355
356# ----------------------------------------------------------------------
357# USAGE: register <err>
358#
359# Low-level function used to capture information about a bug report
360# prior to calling "send", which actually sends the ticket.  We usually
361# let the user preview the information and decide whether or not to
362# send the ticket.
363# ----------------------------------------------------------------------
364proc Rappture::bugreport::register {err} {
365    global errorInfo tcl_platform
366    variable details
367    variable settings
368    variable extraInfo
369
370    #
371    # Figure out exactly what we'll send if the bug report is
372    # submitted, so we can show the user.
373    #
374    set stackTrace "$err\n---------\n$errorInfo\n---------\n$extraInfo"
375    if {![regexp {^([^\n]+)\n} $stackTrace match summary]} {
376        if {[string length $stackTrace] == 0} {
377            set summary "Unexpected error from Rappture"
378        } else {
379            set summary $stackTrace
380        }
381    }
382    if {[string length $summary] > 200} {
383        set summary "[string range $summary 0 200]..."
384    }
385    if {[string match {Problem launching job*} $summary]} {
386        append summary " (in tool \"[Rappture::Tool::resources -appname]\")"
387        set category "Tools"
388    } else {
389        set category $settings(category)
390    }
391
392    # make sure that the stack trace isn't too long
393    set toolong 20000
394    if {[string length $stackTrace] > $toolong} {
395        #
396        # If this came from "Problem launching job", then it will have
397        # a "== RAPPTURE INPUT ==" part somewhere in the middle.  Try
398        # to show the first part, this middle part, and the very last
399        # part, cutting out whatever we have to in the middle.
400        #
401        if {[regexp -indices {\n== RAPPTURE INPUT ==\n} $stackTrace match]} {
402            foreach {smid0 smid1} $match break
403            set quarter [expr {$toolong/4}]
404            set s0 $quarter
405            set smid0 [expr {$smid0-$quarter}]
406            set smid1 [expr {$smid1+$quarter}]
407            set s1 [expr {[string length $stackTrace]-$quarter}]
408
409            if {$smid0 < $s0} {
410                # first part is short -- truncate last part
411                set stackTrace "[string range $stackTrace 0 $smid1]\n...\n[string range $stackTrace [expr {[string length $stackTrace]-($toolong-$smid1)}] end]"
412            } elseif {$smid1 > $s1} {
413                # last part is short -- truncate first part
414                set tailsize [expr {[string length $stackTrace]-$smid0}]
415                set stackTrace "[string range $stackTrace 0 [expr {$toolong-$tailsize}]]\n...\n[string range $stackTrace $smid0 end]"
416            } else {
417                # rappture input line is right about in the middle
418                set stackTrace "[string range $stackTrace 0 $s0]\n...\n[string range $stackTrace $smid0 $smid1]\n...\n[string range $stackTrace $s1 end]"
419            }
420        } else {
421            # no Rappture input -- just show first part and last part
422            set half [expr {$toolong/2}]
423            set stackTrace "[string range $stackTrace 0 $half]\n...\n[string range $stackTrace [expr {[string length $stackTrace]-$half}] end]"
424        }
425    }
426
427    set details(summary) $summary
428    set details(category) $category
429    set details(stackTrace) $stackTrace
430    set details(hostname) [info hostname]
431    set details(session) [Rappture::Tool::resources -session]
432    set details(referrer) [Rappture::Tool::resources -appname]
433    set details(platform) [array get tcl_platform]
434
435    Rappture::Logger::log oops! $summary
436}
437
438# ----------------------------------------------------------------------
439# USAGE: attachment <string>
440#
441# Low-level function used to capture information about a bug report
442# prior to calling "send", which actually sends the ticket.  We usually
443# let the user preview the information and decide whether or not to
444# send the ticket.
445# ----------------------------------------------------------------------
446proc Rappture::bugreport::attachment { string } {
447    variable details
448    set details(attachment) $string
449}
450
451# ----------------------------------------------------------------------
452# USAGE: send
453#
454# Low-level function used to send bug reports back to the hub site.
455# Error details gathered by a previous call to "register" are sent
456# along as a support ticket.  Returns a string of the following form,
457# representing details about the new or existing ticket:
458#   Ticket #XX (XXXXXX) XX times
459# ----------------------------------------------------------------------
460proc Rappture::bugreport::send {} {
461    variable details
462    variable settings
463
464    package require http
465    package require tls
466    http::register https 443 [list ::tls::socket -tls1 1]
467
468    set report $details(stackTrace)
469    set cmts [string trim [.bugreport.comments.info.text get 1.0 end]]
470    if {[string length $cmts] > 0} {
471        set report "$cmts\n\n[string repeat = 72]\n$report"
472    }
473    set toolFile ""
474    if { [info exists details(attachment)] } {
475        set toolFile "/tmp/tool[pid].xml"
476        set f [open $toolFile "w"]
477        puts $f $details(attachment)
478        close $f
479        unset details(attachment)
480    }
481    set query [http::formatQuery \
482        option com_support \
483        controller tickets \
484        upload $toolFile \
485        task create \
486        no_html 1 \
487        report $report \
488        sesstoken $details(session) \
489        hostname $details(hostname) \
490        os $details(platform) \
491        category $details(category) \
492        summary $details(summary) \
493        referrer $details(referrer) \
494        login $settings(user) \
495        group $settings(group) \
496        type $settings(type) \
497    ]
498    set url [Rappture::Tool::resources -huburl]
499    if { $url == "" } {
500        set url "http://hubzero.org"
501    }
502    if {[string index $url end] == "/"} {
503        append url "index.php"
504    } else {
505        append url "/index.php"
506    }
507
508    set token [http::geturl $url -query $query -timeout 60000]
509
510    if {[http::ncode $token] != 200} {
511        error [http::code $token]
512    }
513    upvar #0 $token rval
514    set info $rval(body)
515    http::cleanup $token
516
517    if { $toolFile != "" } {
518        file delete $toolFile
519    }
520    if {[regexp {Ticket #[0-9]* +\(.*?\) +[0-9]+ +times} $info match]} {
521        return $match
522    }
523    error "Report received, but ticket may not have been filed.  Here's the result...\n$info"
524}
525
526# ----------------------------------------------------------------------
527# USAGE: fixTextHeight <widget>
528#
529# Used internally to adjust the height of a text widget so it is just
530# tall enough to show the info within it.
531# ----------------------------------------------------------------------
532proc Rappture::bugreport::fixTextHeight {widget} {
533    #
534    # HACK ALERT!  In Tk8.5, we can count display lines directly.
535    #   But for earlier versions, we have to cook up something
536    #   similar.
537    #
538    if {[catch {$widget count -displaylines 1.0 end} h] == 0 && $h > 0} {
539        $widget configure -height $h
540    } else {
541        for {set h 1} {$h < 15} {incr h} {
542            $widget configure -height $h
543            $widget see 1.0
544            update idletasks
545            if {"" != [$widget bbox end-1char]} {
546                break
547            }
548        }
549    }
550}
551
552# ----------------------------------------------------------------------
553# USAGE: shouldReport jobfailures <boolean>
554# USAGE: shouldReport for ?oops|jobs?
555#
556# Used internally to determine whether or not this system should
557# automatically report errors back to the hosting hub.  Returns 1
558# if the tool should, and 0 otherwise.  The decision is made based
559# on whether this is a current tool in production, whether it is
560# being tested in a workspace, and whether the tool commonly generates
561# problems (by pilot error in its input deck).
562# ----------------------------------------------------------------------
563proc Rappture::bugreport::shouldReport {option value} {
564    global env
565
566    switch -- $option {
567        jobfailures {
568            variable reportJobFailures
569            if {![string is boolean $value]} {
570                error "bad value \"$value\": should be boolean"
571            }
572            set reportJobFailures $value
573        }
574        for {
575            # is it being run within a workspace?
576            set appname [Rappture::Tool::resources -appname]
577            if {[string match {[Ww]orkspace*} $appname]} {
578                return 0
579            }
580
581            # if this is a problem launching a job and the tool
582            # expects this, then don't bother with automatic reports.
583            variable reportJobFailures
584            if {"jobs" == $value && !$reportJobFailures} {
585                return 0
586            }
587
588            # this is a real problem -- report it!
589            return 1
590        }
591        default {
592            error "bad option \"$option\": should be jobfailures or for"
593        }
594    }
595}
596
597# ----------------------------------------------------------------------
598# Build the bug reporting dialog
599# ----------------------------------------------------------------------
600toplevel .bugreport -class BugReport -borderwidth 1 -relief solid
601wm overrideredirect .bugreport 1
602wm withdraw .bugreport
603
604frame .bugreport.banner -background #a9a9a9
605pack .bugreport.banner -side top -fill x
606label .bugreport.banner.icon -image [Rappture::icon alert]
607pack .bugreport.banner.icon -side left -padx 2 -pady 2
608label .bugreport.banner.title -text "Oops! Internal Error"
609pack .bugreport.banner.title -side left -padx {0 8} -pady 2
610
611# add these frustration bindings in case the "Dismiss" button is off screen
612bind .bugreport.banner.icon <Double-ButtonPress-1> \
613    Rappture::bugreport::deactivate
614bind .bugreport.banner.title <Double-ButtonPress-1> \
615    Rappture::bugreport::deactivate
616bind .bugreport <KeyPress-Escape> \
617    Rappture::bugreport::deactivate
618
619set bg [.bugreport cget -background]
620text .bugreport.expl -borderwidth 0 -highlightthickness 0 -background $bg \
621    -height 3 -wrap word
622.bugreport.expl tag configure bold \
623    -font [option get .bugreport.expl boldFont Font]
624#
625# HACK ALERT!  We have problems with fixTextHeight working correctly
626#   on Windows for Tk8.4 and earlier.  To make it work properly, we
627#   add the binding below.  At some point, we'll ditch 8.4 and we can
628#   use the new "count -displaylines" option in Tk8.5.
629#
630bind .bugreport.expl <Map> {Rappture::bugreport::fixTextHeight %W}
631
632frame .bugreport.comments
633label .bugreport.comments.l -text "What were you doing just before this error?" -anchor w
634pack .bugreport.comments.l -side top -anchor w
635Rappture::Scroller .bugreport.comments.info -xscrollmode none -yscrollmode auto
636text .bugreport.comments.info.text -width 30 -height 3 -wrap word
637.bugreport.comments.info contents .bugreport.comments.info.text
638bind .bugreport.comments.info.text <ButtonPress> {focus %W}
639pack .bugreport.comments.info -expand yes -fill both
640
641frame .bugreport.cntls
642pack .bugreport.cntls -side bottom -fill x
643button .bugreport.cntls.ok -text "Ignore" -command {
644    Rappture::bugreport::deactivate
645}
646pack .bugreport.cntls.ok -side left -padx {4 20} -pady 8
647button .bugreport.cntls.send -text "Send Trouble Report" -command {
648    Rappture::bugreport::submit
649}
650pack .bugreport.cntls.send -side right -padx 4 -pady 8
651
652button .bugreport.cntls.show -text "Show Details..." \
653    -command {Rappture::bugreport::activate @SHOWDETAILS}
654pack .bugreport.cntls.show -side right
655
656
657frame .bugreport.details
658Rappture::Scroller .bugreport.details.info -xscrollmode auto -yscrollmode auto
659text .bugreport.details.info.text -width 50 -height 15 -wrap none
660.bugreport.details.info contents .bugreport.details.info.text
661pack .bugreport.details.info -expand yes -fill both
662
663frame .bugreport.xmit
664Rappture::Animicon .bugreport.xmit.icon -images {
665    circle-ball1 circle-ball2 circle-ball3 circle-ball4
666    circle-ball5 circle-ball6 circle-ball7 circle-ball8
667}
668pack .bugreport.xmit.icon -side left
669label .bugreport.xmit.title -anchor w
670pack .bugreport.xmit.title -side left -expand yes -fill x
671
672button .bugreport.done -text "Done" \
673    -command Rappture::bugreport::deactivate
674
675# this binding keeps the bugreport window on top
676bind BugReportOnTop <ButtonPress> {
677    wm deiconify %W
678    raise %W
679}
680set btags [bindtags .bugreport]
681bindtags .bugreport [linsert $btags 0 BugReportOnTop]
682
Note: See TracBrowser for help on using the repository browser.