PageRenderTime 26ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/libgui/library/sendpr.tcl

https://gitlab.com/OpenSourceMirror/sourcenav
TCL | 348 lines | 315 code | 7 blank | 26 comment | 15 complexity | a04e8a913994bab5b23975d5b4ee3977 MD5 | raw file
  1. # sendpr.tcl - GUI to send-pr.
  2. # Copyright (C) 1997 Cygnus Solutions.
  3. # Written by Tom Tromey <tromey@cygnus.com>.
  4. # FIXME:
  5. # * consider adding ability to set various options from outside,
  6. # eg via the configure method.
  7. # * Have explanatory text at the top
  8. # * if synopsis not set, don't allow PR to be sent
  9. # * at least one text field must have text in it before PR can be sent
  10. # * see other fixme comments in text.
  11. # FIXME: shouldn't have global variable.
  12. defarray SENDPR_state
  13. itcl_class Sendpr {
  14. inherit Ide_window
  15. # This array holds information about this site. It is a private
  16. # common array. Once initialized it is never changed.
  17. common _site
  18. # Initialize the _site array.
  19. global Paths tcl_platform
  20. # On Windows, there is no `send-pr' program. For now, we just
  21. # hard-code things there to work in the most important case.
  22. if {$tcl_platform(platform) == "windows"} then {
  23. set _site(header) ""
  24. set _site(to) bugs@cygnus.com
  25. set _site(field,Submitter-Id) cygnus
  26. set _site(field,Originator) Nobody
  27. set _site(field,Release) "Internal"
  28. set _site(field,Organization) "Red Hat, Inc."
  29. set _site(field,Environment) ""
  30. foreach item {byteOrder machine os osVersion platform} {
  31. append _site(field,Environment) "$item = $tcl_platform($item)\n"
  32. }
  33. set _site(categories) foundry
  34. } else {
  35. set _site(sendpr) [file join $Paths(bindir) send-pr]
  36. # If it doesn't exist, try the user's path. This is a hack for
  37. # developers.
  38. if {! [file exists $_site(sendpr)]} then {
  39. set _site(sendpr) send-pr
  40. }
  41. set _site(header) {}
  42. set outList [split [exec $_site(sendpr) -P] \n]
  43. set lastField {}
  44. foreach line $outList {
  45. if {[string match SEND-PR* $line]} then {
  46. # Nothing.
  47. } elseif {[regexp {^$} $line] || [regexp "^\[ \t\]" $line]} then {
  48. # Empty lines and lines starting with a blank are skipped.
  49. } elseif {$lastField == "" &&
  50. [regexp [format {^[^>]([^:]+):[ %s]+(.+)$} \t] \
  51. $line dummy field value]} then {
  52. # A non-empty mail header line. This can only occur when there
  53. # is no last field.
  54. if {[string tolower $field] == "to"} then {
  55. set _site(to) $value
  56. }
  57. } elseif {[regexp {^>([^:]*):(.*)$} $line dummy field value]} then {
  58. # Found a field. Set it.
  59. set lastField $field
  60. if {$value != "" && ![string match <*> [string trim $value]]} then {
  61. set _site(field,$lastField) $value
  62. }
  63. } elseif {$lastField == ""} then {
  64. # No last field.
  65. } else {
  66. # Stuff into last field.
  67. if {[info exists _site(field,$lastField)]} then {
  68. append _site(field,$lastField) \n
  69. }
  70. append _site(field,$lastField) $line
  71. }
  72. }
  73. # Now find the categories.
  74. regsub -all -- {[()\"]} [exec $_site(sendpr) -CL] \
  75. "" _site(categories)
  76. set _site(categories) [lrmdups [concat foundry $_site(categories)]]
  77. }
  78. # Internationalize some text. We have to do this because of how
  79. # Tk's optionmenu works. Indices here are the names that GNATS
  80. # wants; this is important.
  81. set _site(sw-bug) [gettext "Software bug"]
  82. set _site(doc-bug) [gettext "Documentation bug"]
  83. set _site(change-request) [gettext "Change request"]
  84. set _site(support) [gettext "Support"]
  85. set _site(non-critical) [gettext "Non-critical"]
  86. set _site(serious) [gettext "Serious"]
  87. set _site(critical) [gettext "Critical"]
  88. set _site(low) [gettext "Low"]
  89. set _site(medium) [gettext "Medium"]
  90. set _site(high) [gettext "High"]
  91. # Any text passed to constructor is saved and put into Description
  92. # section of output.
  93. constructor {{text ""}} {
  94. Ide_window::constructor [gettext "Report Bug"]
  95. } {
  96. global SENDPR_state
  97. # The standard widget-making trick.
  98. set class [$this info class]
  99. set hull [namespace tail $this]
  100. set old_name $this
  101. ::rename $this $this-tmp-
  102. # For now always make a toplevel. Number 7 comes from Windows
  103. ::rename $hull $old_name-win-
  104. ::rename $this $old_name
  105. ::rename $this $this-win-
  106. ::rename $this-tmp- $this
  107. wm withdraw [namespace tail $this]
  108. ###FIXME - this constructor callout will cause the parent constructor to be called twice
  109. ::set SENDPR_state($this,desc) $text
  110. #
  111. # The Classification frame.
  112. #
  113. Labelledframe [namespace tail $this].cframe -text [gettext "Classification"]
  114. set parent [[namespace tail $this].cframe get_frame]
  115. tixComboBox $parent.category -dropdown 1 -editable 0 \
  116. -label [gettext "Category"] -variable SENDPR_state($this,category)
  117. foreach item $_site(categories) {
  118. $parent.category insert end $item
  119. }
  120. # FIXME: allow user of this class to set default category.
  121. ::set SENDPR_state($this,category) foundry
  122. ::set SENDPR_state($this,secret) no
  123. checkbutton $parent.secret -text [gettext "Confidential"] \
  124. -variable SENDPR_state($this,secret) -onvalue yes -offvalue no \
  125. -anchor w
  126. # FIXME: put labels on these?
  127. set m1 [_make_omenu $parent.class class 0 \
  128. sw-bug doc-bug change-request support]
  129. set m2 [_make_omenu $parent.severity severity 1 \
  130. non-critical serious critical]
  131. set m3 [_make_omenu $parent.priority priority 1 \
  132. low medium high]
  133. if {$m1 > $m2} then {
  134. set m2 $m1
  135. }
  136. if {$m2 > $m3} then {
  137. set m3 $m2
  138. }
  139. $parent.class configure -width $m3
  140. $parent.severity configure -width $m3
  141. $parent.priority configure -width $m3
  142. grid $parent.category $parent.severity -sticky nw -padx 2
  143. grid $parent.secret $parent.class -sticky nw -padx 2
  144. grid x $parent.priority -sticky nw -padx 2
  145. #
  146. # The text and entry frames.
  147. #
  148. Labelledframe [namespace tail $this].synopsis -text [gettext "Synopsis"]
  149. set parent [[namespace tail $this].synopsis get_frame]
  150. entry $parent.synopsis -textvariable SENDPR_state($this,synopsis)
  151. pack $parent.synopsis -expand 1 -fill both
  152. # Text fields. Each is wrapped in its own label frame.
  153. # We decided to eliminate all the frames but one; the others are
  154. # just confusing.
  155. ::set SENDPR_state($this,repeat) [_make_text [namespace tail $this].desc \
  156. [gettext "Description"]]
  157. # Some buttons.
  158. frame [namespace tail $this].buttons -borderwidth 0 -relief flat
  159. button [namespace tail $this].buttons.send -text [gettext "Send"] \
  160. -command [list $this _send]
  161. button [namespace tail $this].buttons.cancel -text [gettext "Cancel"] \
  162. -command [list destroy $this]
  163. button [namespace tail $this].buttons.help -text [gettext "Help"] -state disabled
  164. standard_button_box [namespace tail $this].buttons
  165. # FIXME: we'd really like to have sashes between the text widgets.
  166. # iwidgets or tix will provide that for us.
  167. grid [namespace tail $this].cframe -sticky ew -padx 4 -pady 4
  168. grid [namespace tail $this].synopsis -sticky ew -padx 4 -pady 4
  169. grid [namespace tail $this].desc -sticky news -padx 4 -pady 4
  170. grid [namespace tail $this].buttons -sticky ew -padx 4
  171. grid rowconfigure [namespace tail $this] 0 -weight 0
  172. grid rowconfigure [namespace tail $this] 1 -weight 0
  173. grid rowconfigure [namespace tail $this] 2 -weight 1
  174. grid rowconfigure [namespace tail $this] 3 -weight 1
  175. grid columnconfigure [namespace tail $this] 0 -weight 1
  176. bind [namespace tail $this].buttons <Destroy> [list $this delete]
  177. wm deiconify [namespace tail $this]
  178. }
  179. destructor {
  180. global SENDPR_state
  181. foreach item [array names SENDPR_state $this,*] {
  182. ::unset SENDPR_state($item)
  183. }
  184. catch {destroy $this}
  185. }
  186. method configure {config} {}
  187. # Create an optionmenu and fill it. Also, go through all the items
  188. # and find the one that makes the menubutton the widest. Return the
  189. # max width. Private method.
  190. method _make_omenu {name index def_index args} {
  191. global SENDPR_state
  192. set max 0
  193. set values {}
  194. # FIXME: we can't actually examine which one makes the menubutton
  195. # widest. Why not? Because the menubutton's -width option is in
  196. # characters, but we can only look at the width in pixels.
  197. foreach item $args {
  198. lappend values $_site($item)
  199. if {[string length $_site($item)] > $max} then {
  200. set max [string length $_site($item)]
  201. }
  202. }
  203. eval tk_optionMenu $name SENDPR_state($this,$index) $values
  204. ::set SENDPR_state($this,$index) $_site([lindex $args $def_index])
  205. return $max
  206. }
  207. # Create a labelled frame and put a text widget in it. Private
  208. # method.
  209. method _make_text {name text} {
  210. Labelledframe $name -text $text
  211. set parent [$name get_frame]
  212. text $parent.text -width 80 -height 15 -wrap word \
  213. -yscrollcommand [list $parent.vb set]
  214. scrollbar $parent.vb -orient vertical -command [list $parent.text yview]
  215. grid $parent.text -sticky news
  216. grid $parent.vb -row 0 -column 1 -sticky ns
  217. grid rowconfigure $parent 0 -weight 1
  218. grid columnconfigure $parent 0 -weight 1
  219. grid columnconfigure $parent 1 -weight 0
  220. return $parent.text
  221. }
  222. # This takes a text string and finds the element of site which has
  223. # the same value. It returns the corresponding key. Private
  224. # method.
  225. method _invert {text values} {
  226. foreach item $values {
  227. if {$_site($item) == $text} then {
  228. return $item
  229. }
  230. }
  231. error "couldn't find \"$text\""
  232. }
  233. # Send the PR. Private method.
  234. method _send {} {
  235. global SENDPR_state
  236. set email {}
  237. if {[info exists _site(field,Submitter-Id)]} then {
  238. set _site(field,Customer-Id) $_site(field,Submitter-Id)
  239. unset _site(field,Submitter-Id)
  240. }
  241. foreach field {Customer-Id Originator Release} {
  242. append email ">$field: $_site(field,$field)\n"
  243. }
  244. foreach field {Organization Environment} {
  245. append email ">$field:\n$_site(field,$field)\n"
  246. }
  247. append email ">Confidential: "
  248. if {$SENDPR_state($this,secret)} then {
  249. append email yes\n
  250. } else {
  251. append email no\n
  252. }
  253. append email ">Synopsis: $SENDPR_state($this,synopsis)\n"
  254. foreach field {Severity Priority Class} \
  255. values {{non-critical serious critical} {low medium high}
  256. {sw-bug doc-bug change-request support}} {
  257. set name [string tolower $field]
  258. set value [_invert $SENDPR_state($this,$name) $values]
  259. append email ">$field: $value\n"
  260. }
  261. append email ">Category: $SENDPR_state($this,category)\n"
  262. # Now big things.
  263. append email ">How-To-Repeat:\n"
  264. append email "[$SENDPR_state($this,repeat) get 1.0 end]\n"
  265. # This isn't displayed to the user, but can be set by the caller.
  266. append email ">Description:\n$SENDPR_state($this,desc)\n"
  267. send_mail $_site(to) $SENDPR_state($this,synopsis) $email
  268. destroy $this
  269. }
  270. # Override from Ide_window.
  271. method idew_save {} {
  272. global SENDPR_state
  273. foreach name {category secret severity priority class synopsis} {
  274. set result($name) $SENDPR_state($this,$name)
  275. }
  276. # Stop just before `end'; otherwise we add a newline each time.
  277. set result(repeat) [$SENDPR_state($this,repeat) get 1.0 {end - 1c}]
  278. set result(desc) $SENDPR_state($this,desc)
  279. return [list Sendpr :: _restore [array get result]]
  280. }
  281. # This is used to restore a bug report window. Private proc.
  282. proc _restore {alist x y width height visibility} {
  283. global SENDPR_state
  284. array set values $alist
  285. set name .[gensym]
  286. Sendpr $name $values(desc)
  287. foreach name {category secret severity priority class synopsis} {
  288. ::set $SENDPR_state($this,$name) $values($name)
  289. }
  290. $SENDPR_state($name,repeat) insert end $desc
  291. $name idew_set_geometry $x $y $width $height
  292. $name idew_set_visibility $visibility
  293. }
  294. }