cosmos 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (912) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +48 -48
  4. data/.travis.yml +7 -7
  5. data/CONTRIBUTING.txt +50 -50
  6. data/Gemfile +6 -6
  7. data/Guardfile +27 -27
  8. data/LICENSE.txt +879 -879
  9. data/Manifest.txt +1116 -1114
  10. data/README.md +109 -107
  11. data/Rakefile +214 -214
  12. data/autohotkey/config/data/diamond.STL +57 -57
  13. data/autohotkey/config/system/system.txt +34 -34
  14. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  15. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  16. data/autohotkey/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  17. data/autohotkey/config/targets/COSMOS/target.txt +5 -5
  18. data/autohotkey/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  19. data/autohotkey/config/targets/INST/cmd_tlm/inst_tlm.txt +247 -247
  20. data/autohotkey/config/targets/INST/cmd_tlm_server.txt +5 -5
  21. data/autohotkey/config/targets/INST/lib/example_limits_response.rb +30 -30
  22. data/autohotkey/config/targets/INST/lib/sim_inst.rb +305 -294
  23. data/autohotkey/config/targets/INST/screens/adcs.txt +46 -46
  24. data/autohotkey/config/targets/INST/screens/array.txt +7 -7
  25. data/autohotkey/config/targets/INST/screens/block.txt +8 -8
  26. data/autohotkey/config/targets/INST/screens/commanding.txt +30 -30
  27. data/autohotkey/config/targets/INST/screens/graphs.txt +14 -14
  28. data/autohotkey/config/targets/INST/screens/ground.txt +25 -25
  29. data/autohotkey/config/targets/INST/screens/health_status.txt +33 -33
  30. data/autohotkey/config/targets/INST/screens/hs.txt +49 -49
  31. data/autohotkey/config/targets/INST/screens/image.txt +21 -21
  32. data/autohotkey/config/targets/INST/screens/latest.txt +23 -23
  33. data/autohotkey/config/targets/INST/screens/mech.txt +25 -25
  34. data/autohotkey/config/targets/INST/screens/other.txt +25 -25
  35. data/autohotkey/config/targets/INST/screens/params.txt +25 -25
  36. data/autohotkey/config/targets/INST/screens/tabs.txt +68 -68
  37. data/autohotkey/config/targets/INST/target.txt +26 -26
  38. data/autohotkey/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  39. data/autohotkey/config/targets/META/cmd_tlm/meta_tlm.txt +9 -9
  40. data/autohotkey/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  41. data/autohotkey/config/targets/SYSTEM/screens/error.txt +11 -11
  42. data/autohotkey/config/tools/cmd_tlm_server/cmd_tlm_server.txt +22 -22
  43. data/autohotkey/config/tools/data_viewer/data_viewer.txt +11 -11
  44. data/autohotkey/config/tools/handbook_creator/handbook_creator.txt +49 -49
  45. data/autohotkey/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  46. data/autohotkey/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  47. data/autohotkey/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  48. data/autohotkey/config/tools/handbook_creator/templates/header.html.erb +25 -25
  49. data/autohotkey/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  50. data/autohotkey/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  51. data/autohotkey/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  52. data/autohotkey/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  53. data/autohotkey/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  54. data/autohotkey/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  55. data/autohotkey/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  56. data/autohotkey/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  57. data/autohotkey/config/tools/handbook_creator/templates/title.html.erb +1 -1
  58. data/autohotkey/config/tools/launcher/launcher.txt +38 -38
  59. data/autohotkey/config/tools/script_runner/script_runner.txt +3 -3
  60. data/autohotkey/config/tools/table_manager/ConfigTables_def.txt +8 -8
  61. data/autohotkey/config/tools/table_manager/OneDimensionalTable_def.txt +19 -19
  62. data/autohotkey/config/tools/table_manager/TwoDimensionalTable_def.txt +248 -248
  63. data/autohotkey/config/tools/test_runner/test_runner.txt +8 -8
  64. data/autohotkey/config/tools/test_runner/test_runner2.txt +11 -11
  65. data/autohotkey/config/tools/test_runner/test_runner3.txt +6 -6
  66. data/autohotkey/config/tools/test_runner/test_runner4.txt +1 -1
  67. data/autohotkey/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  68. data/autohotkey/config/tools/tlm_extractor/tlm_extractor2.txt +9 -9
  69. data/autohotkey/config/tools/tlm_grapher/bad.txt +50 -50
  70. data/autohotkey/config/tools/tlm_grapher/temp1-4.txt +51 -51
  71. data/autohotkey/config/tools/tlm_grapher/test2.txt +111 -111
  72. data/autohotkey/config/tools/tlm_viewer/tlm_viewer.txt +24 -24
  73. data/autohotkey/config/tools/tlm_viewer/tlm_viewer2.txt +4 -4
  74. data/autohotkey/config/tools/tlm_viewer/tlm_viewer3.txt +3 -3
  75. data/autohotkey/lib/example_background_task.rb +42 -42
  76. data/autohotkey/lib/user_version.rb +3 -3
  77. data/autohotkey/procedures/clear_util.rb +7 -7
  78. data/autohotkey/procedures/collect.rb +18 -18
  79. data/autohotkey/procedures/collect_util.rb +14 -14
  80. data/autohotkey/procedures/example_test.rb +67 -67
  81. data/autohotkey/procedures/example_test2.rb +74 -74
  82. data/autohotkey/procedures/script_test.rb +17 -17
  83. data/autohotkey/procedures/syntax_error.rb +18 -18
  84. data/autohotkey/tools/CmdExtractorAHK +16 -16
  85. data/autohotkey/tools/CmdSender +14 -14
  86. data/autohotkey/tools/CmdSenderAHK +18 -18
  87. data/autohotkey/tools/CmdTlmServer +14 -14
  88. data/autohotkey/tools/CmdTlmServerAHK +28 -28
  89. data/autohotkey/tools/CmdTlmServerAHK2 +17 -17
  90. data/autohotkey/tools/DataViewer +14 -14
  91. data/autohotkey/tools/DataViewerAHK +17 -17
  92. data/autohotkey/tools/HandbookCreatorAHK +20 -20
  93. data/autohotkey/tools/LauncherAHK +17 -17
  94. data/autohotkey/tools/LimitsMonitorAHK +20 -20
  95. data/autohotkey/tools/OpenGLBuilderAHK +20 -20
  96. data/autohotkey/tools/PacketViewer +14 -14
  97. data/autohotkey/tools/PacketViewerAHK +18 -18
  98. data/autohotkey/tools/PacketViewerAHK2 +17 -17
  99. data/autohotkey/tools/Replay +14 -14
  100. data/autohotkey/tools/Replay.bat +59 -59
  101. data/autohotkey/tools/ReplayAHK +17 -17
  102. data/autohotkey/tools/ScriptRunner +14 -14
  103. data/autohotkey/tools/ScriptRunnerAHK +20 -20
  104. data/autohotkey/tools/ScriptRunnerAHK2 +17 -17
  105. data/autohotkey/tools/TableManager +14 -14
  106. data/autohotkey/tools/TableManagerAHK +30 -30
  107. data/autohotkey/tools/TestRunner +15 -15
  108. data/autohotkey/tools/TestRunnerAHK +17 -17
  109. data/autohotkey/tools/TestRunnerAHK2 +17 -17
  110. data/autohotkey/tools/TestRunnerAHK3 +17 -17
  111. data/autohotkey/tools/TestRunnerAHK4 +17 -17
  112. data/autohotkey/tools/TlmExtractor +15 -15
  113. data/autohotkey/tools/TlmExtractorAHK +19 -19
  114. data/autohotkey/tools/TlmExtractorAHK2 +16 -16
  115. data/autohotkey/tools/TlmExtractorAHK3 +16 -16
  116. data/autohotkey/tools/TlmGrapher +14 -14
  117. data/autohotkey/tools/TlmGrapherAHK +19 -19
  118. data/autohotkey/tools/TlmGrapherAHK2 +23 -23
  119. data/autohotkey/tools/TlmGrapherAHK3 +17 -17
  120. data/autohotkey/tools/TlmGrapherAHK4 +17 -17
  121. data/autohotkey/tools/TlmViewer +14 -14
  122. data/autohotkey/tools/TlmViewerAHK +28 -28
  123. data/autohotkey/tools/TlmViewerAHK2 +18 -18
  124. data/autohotkey/tools/TlmViewerAHK3 +18 -18
  125. data/autohotkey/tools/TlmViewerAHK4 +18 -18
  126. data/autohotkey/tools/TlmViewerAHK5 +18 -18
  127. data/autohotkey/tools/autohotkey.rb +37 -37
  128. data/autohotkey/tools/cmd_extractor.ahk +27 -27
  129. data/autohotkey/tools/cmd_sender.ahk +182 -162
  130. data/autohotkey/tools/cmd_tlm_server.ahk +89 -89
  131. data/autohotkey/tools/cmd_tlm_server2.ahk +45 -45
  132. data/autohotkey/tools/data_viewer.ahk +135 -135
  133. data/autohotkey/tools/handbook_creator.ahk +23 -23
  134. data/autohotkey/tools/launcher.ahk +41 -41
  135. data/autohotkey/tools/limits_monitor.ahk +70 -70
  136. data/autohotkey/tools/open_gl_builder.ahk +134 -134
  137. data/autohotkey/tools/packet_viewer.ahk +143 -143
  138. data/autohotkey/tools/packet_viewer2.ahk +9 -9
  139. data/autohotkey/tools/replay.ahk +98 -98
  140. data/autohotkey/tools/script_runner.ahk +589 -589
  141. data/autohotkey/tools/script_runner2.ahk +34 -31
  142. data/autohotkey/tools/table_manager.ahk +220 -220
  143. data/autohotkey/tools/test_runner.ahk +262 -259
  144. data/autohotkey/tools/test_runner2.ahk +52 -52
  145. data/autohotkey/tools/test_runner3.ahk +13 -13
  146. data/autohotkey/tools/tlm_extractor.ahk +272 -272
  147. data/autohotkey/tools/tlm_grapher.ahk +642 -642
  148. data/autohotkey/tools/tlm_grapher2.ahk +115 -115
  149. data/autohotkey/tools/tlm_grapher3.ahk +24 -24
  150. data/autohotkey/tools/tlm_viewer.ahk +133 -133
  151. data/autohotkey/tools/tlm_viewer2.ahk +50 -49
  152. data/autohotkey/tools/tlm_viewer4.ahk +4 -4
  153. data/autohotkey/tools/tlm_viewer5.ahk +20 -20
  154. data/bin/cosmos +96 -96
  155. data/bin/cstol_converter +1166 -1166
  156. data/bin/rubysloc +85 -85
  157. data/cosmos.gemspec +98 -97
  158. data/data/about.txt +4 -4
  159. data/data/crc.txt +306 -305
  160. data/data/diamond.STL +57 -57
  161. data/data/legal.txt +9 -9
  162. data/demo/Gemfile +6 -6
  163. data/demo/Launcher +15 -15
  164. data/demo/Launcher.bat +59 -59
  165. data/demo/Rakefile +61 -61
  166. data/demo/config/data/crc.txt +222 -206
  167. data/demo/config/data/diamond.STL +57 -57
  168. data/demo/config/data/meta_init.txt +4 -4
  169. data/demo/config/system/system.txt +34 -34
  170. data/demo/config/system/system2.txt +33 -33
  171. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  172. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  173. data/demo/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  174. data/demo/config/targets/COSMOS/screens/limits_change.txt +20 -20
  175. data/demo/config/targets/COSMOS/screens/version.txt +19 -19
  176. data/demo/config/targets/COSMOS/target.txt +11 -11
  177. data/demo/config/targets/EXAMPLE/cmd_tlm/example_cmds.txt +2 -2
  178. data/demo/config/targets/EXAMPLE/cmd_tlm/example_tlm.txt +3 -3
  179. data/demo/config/targets/EXAMPLE/cmd_tlm_server.txt +6 -6
  180. data/demo/config/targets/EXAMPLE/lib/example_interface.rb +22 -22
  181. data/demo/config/targets/EXAMPLE/target.txt +6 -6
  182. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  183. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +247 -247
  184. data/demo/config/targets/INST/cmd_tlm_server.txt +5 -5
  185. data/demo/config/targets/INST/lib/example_limits_response.rb +30 -30
  186. data/demo/config/targets/INST/lib/sim_inst.rb +305 -294
  187. data/demo/config/targets/INST/screens/adcs.txt +46 -46
  188. data/demo/config/targets/INST/screens/array.txt +15 -15
  189. data/demo/config/targets/INST/screens/block.txt +8 -8
  190. data/demo/config/targets/INST/screens/commanding.txt +30 -30
  191. data/demo/config/targets/INST/screens/graphs.txt +14 -14
  192. data/demo/config/targets/INST/screens/ground.txt +25 -25
  193. data/demo/config/targets/INST/screens/hs.txt +44 -44
  194. data/demo/config/targets/INST/screens/latest.txt +23 -23
  195. data/demo/config/targets/INST/screens/other.txt +29 -29
  196. data/demo/config/targets/INST/screens/tabs.txt +70 -70
  197. data/demo/config/targets/INST/target.txt +33 -33
  198. data/demo/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  199. data/demo/config/targets/META/cmd_tlm/meta_tlm.txt +13 -13
  200. data/demo/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  201. data/demo/config/targets/SYSTEM/cmd_tlm/override.txt +29 -29
  202. data/demo/config/targets/SYSTEM/screens/status.txt +12 -12
  203. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_cmds.txt +13 -12
  204. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_tlm.txt +3 -3
  205. data/demo/config/targets/TEMPLATED/cmd_tlm_server.txt +6 -6
  206. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +54 -48
  207. data/demo/config/targets/TEMPLATED/target.txt +6 -6
  208. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +33 -33
  209. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +29 -29
  210. data/demo/config/tools/data_viewer/data_viewer.txt +11 -11
  211. data/demo/config/tools/handbook_creator/handbook_creator.txt +66 -66
  212. data/demo/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  213. data/demo/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  214. data/demo/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  215. data/demo/config/tools/handbook_creator/templates/header.html.erb +25 -25
  216. data/demo/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  217. data/demo/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  218. data/demo/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  219. data/demo/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  220. data/demo/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  221. data/demo/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  222. data/demo/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  223. data/demo/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  224. data/demo/config/tools/handbook_creator/templates/title.html.erb +1 -1
  225. data/demo/config/tools/launcher/launcher.txt +45 -45
  226. data/demo/config/tools/launcher/launcher2.txt +45 -45
  227. data/demo/config/tools/script_runner/script_runner.txt +3 -3
  228. data/demo/config/tools/table_manager/ConfigTables_def.txt +8 -8
  229. data/demo/config/tools/table_manager/ExampleTableDefinition.txt +24 -24
  230. data/demo/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +25 -25
  231. data/demo/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +25 -25
  232. data/demo/config/tools/table_manager/PPSSelectionTable_def.txt +8 -8
  233. data/demo/config/tools/table_manager/TLMMonitoringTable_def.txt +248 -248
  234. data/demo/config/tools/test_runner/test_runner.txt +17 -17
  235. data/demo/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  236. data/demo/config/tools/tlm_extractor/tlm_extractor2.txt +2 -2
  237. data/demo/config/tools/tlm_extractor/tlm_extractor3.txt +2 -2
  238. data/demo/config/tools/tlm_extractor/tlm_extractor4.txt +2 -2
  239. data/demo/config/tools/tlm_viewer/tlm_viewer.txt +41 -41
  240. data/demo/lib/example_background_task.rb +57 -52
  241. data/demo/lib/example_target.rb +113 -108
  242. data/demo/lib/scpi_target.rb +74 -74
  243. data/demo/lib/user_version.rb +3 -3
  244. data/demo/procedures/checks.rb +11 -11
  245. data/demo/procedures/clear_util.rb +7 -7
  246. data/demo/procedures/collect.rb +18 -18
  247. data/demo/procedures/collect_util.rb +14 -14
  248. data/demo/procedures/cosmos_api_test.rb +293 -293
  249. data/demo/procedures/disconnect.rb +29 -29
  250. data/demo/procedures/example_test.rb +182 -182
  251. data/demo/procedures/plot_test.rb +8 -8
  252. data/demo/procedures/run_example_test.rb +3 -3
  253. data/demo/procedures/test.rb +51 -51
  254. data/demo/tools/CmdExtractor +15 -15
  255. data/demo/tools/CmdExtractor.bat +59 -59
  256. data/demo/tools/CmdSender +15 -15
  257. data/demo/tools/CmdSender.bat +59 -59
  258. data/demo/tools/CmdTlmServer +15 -15
  259. data/demo/tools/CmdTlmServer.bat +59 -59
  260. data/demo/tools/DataViewer +15 -15
  261. data/demo/tools/DataViewer.bat +59 -59
  262. data/demo/tools/ExampleTarget +15 -15
  263. data/demo/tools/ExampleTarget.bat +59 -59
  264. data/demo/tools/HandbookCreator +15 -15
  265. data/demo/tools/HandbookCreator.bat +61 -61
  266. data/demo/tools/Launcher +15 -15
  267. data/demo/tools/Launcher.bat +59 -59
  268. data/demo/tools/LimitsMonitor +15 -15
  269. data/demo/tools/LimitsMonitor.bat +59 -59
  270. data/demo/tools/OpenGLBuilder +15 -15
  271. data/demo/tools/OpenGLBuilder.bat +59 -59
  272. data/demo/tools/PacketViewer +15 -15
  273. data/demo/tools/PacketViewer.bat +59 -59
  274. data/demo/tools/Replay +15 -15
  275. data/demo/tools/Replay.bat +59 -59
  276. data/demo/tools/ScpiTarget +15 -15
  277. data/demo/tools/ScpiTarget.bat +59 -59
  278. data/demo/tools/ScriptRunner +15 -15
  279. data/demo/tools/ScriptRunner.bat +59 -59
  280. data/demo/tools/TableManager +15 -15
  281. data/demo/tools/TableManager.bat +59 -59
  282. data/demo/tools/TestRunner +15 -15
  283. data/demo/tools/TestRunner.bat +59 -59
  284. data/demo/tools/TlmExtractor +15 -15
  285. data/demo/tools/TlmExtractor.bat +59 -59
  286. data/demo/tools/TlmGrapher +15 -15
  287. data/demo/tools/TlmGrapher.bat +59 -59
  288. data/demo/tools/TlmViewer +15 -15
  289. data/demo/tools/TlmViewer.bat +59 -59
  290. data/demo/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  291. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +15 -15
  292. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +6 -6
  293. data/demo/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  294. data/demo/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +15 -15
  295. data/demo/tools/mac/CmdSender.app/Contents/MacOS/main.sh +6 -6
  296. data/demo/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  297. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +15 -15
  298. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +6 -6
  299. data/demo/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  300. data/demo/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +15 -15
  301. data/demo/tools/mac/DataViewer.app/Contents/MacOS/main.sh +6 -6
  302. data/demo/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  303. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +15 -15
  304. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +6 -6
  305. data/demo/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  306. data/demo/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +15 -15
  307. data/demo/tools/mac/Launcher.app/Contents/MacOS/main.sh +6 -6
  308. data/demo/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  309. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +15 -15
  310. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +6 -6
  311. data/demo/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  312. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +15 -15
  313. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +6 -6
  314. data/demo/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  315. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +15 -15
  316. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +6 -6
  317. data/demo/tools/mac/Replay.app/Contents/Info.plist +38 -38
  318. data/demo/tools/mac/Replay.app/Contents/MacOS/Replay.rb +15 -15
  319. data/demo/tools/mac/Replay.app/Contents/MacOS/main.sh +6 -6
  320. data/demo/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  321. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +15 -15
  322. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +6 -6
  323. data/demo/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  324. data/demo/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +15 -15
  325. data/demo/tools/mac/TableManager.app/Contents/MacOS/main.sh +6 -6
  326. data/demo/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  327. data/demo/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +15 -15
  328. data/demo/tools/mac/TestRunner.app/Contents/MacOS/main.sh +6 -6
  329. data/demo/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  330. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +15 -15
  331. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +6 -6
  332. data/demo/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  333. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +15 -15
  334. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +6 -6
  335. data/demo/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  336. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +15 -15
  337. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +6 -6
  338. data/ext/cosmos/ext/array/array.c +111 -111
  339. data/ext/cosmos/ext/array/extconf.rb +13 -13
  340. data/ext/cosmos/ext/buffered_file/buffered_file.c +167 -167
  341. data/ext/cosmos/ext/buffered_file/extconf.rb +13 -13
  342. data/ext/cosmos/ext/config_parser/config_parser.c +237 -237
  343. data/ext/cosmos/ext/config_parser/extconf.rb +13 -13
  344. data/ext/cosmos/ext/cosmos_io/cosmos_io.c +117 -117
  345. data/ext/cosmos/ext/cosmos_io/extconf.rb +13 -13
  346. data/ext/cosmos/ext/crc/crc.c +341 -341
  347. data/ext/cosmos/ext/crc/extconf.rb +12 -12
  348. data/ext/cosmos/ext/line_graph/extconf.rb +13 -13
  349. data/ext/cosmos/ext/line_graph/line_graph.c +501 -501
  350. data/ext/cosmos/ext/low_fragmentation_array/extconf.rb +12 -12
  351. data/ext/cosmos/ext/low_fragmentation_array/low_fragmentation_array.c +261 -261
  352. data/ext/cosmos/ext/packet/extconf.rb +13 -13
  353. data/ext/cosmos/ext/packet/packet.c +339 -339
  354. data/ext/cosmos/ext/platform/extconf.rb +13 -13
  355. data/ext/cosmos/ext/platform/platform.c +81 -81
  356. data/ext/cosmos/ext/polynomial_conversion/extconf.rb +13 -13
  357. data/ext/cosmos/ext/polynomial_conversion/polynomial_conversion.c +73 -73
  358. data/ext/cosmos/ext/string/extconf.rb +13 -13
  359. data/ext/cosmos/ext/string/string.c +49 -49
  360. data/ext/cosmos/ext/structure/structure.c +894 -894
  361. data/ext/cosmos/ext/tabbed_plots_config/extconf.rb +13 -13
  362. data/ext/cosmos/ext/tabbed_plots_config/tabbed_plots_config.c +51 -51
  363. data/ext/cosmos/ext/telemetry/extconf.rb +13 -13
  364. data/ext/cosmos/ext/telemetry/telemetry.c +306 -306
  365. data/ext/mkrf_conf.rb +40 -40
  366. data/install/Gemfile +6 -6
  367. data/install/Launcher +14 -14
  368. data/install/Launcher.bat +59 -59
  369. data/install/Rakefile +61 -61
  370. data/install/config/data/crc.txt +134 -133
  371. data/install/config/system/system.txt +29 -29
  372. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  373. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  374. data/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  375. data/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  376. data/install/config/targets/COSMOS/screens/version.txt +19 -19
  377. data/install/config/targets/COSMOS/target.txt +8 -8
  378. data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +2 -2
  379. data/install/config/tools/data_viewer/data_viewer.txt +3 -3
  380. data/install/config/tools/handbook_creator/handbook_creator.txt +49 -49
  381. data/install/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  382. data/install/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  383. data/install/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  384. data/install/config/tools/handbook_creator/templates/header.html.erb +25 -25
  385. data/install/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  386. data/install/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  387. data/install/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  388. data/install/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  389. data/install/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  390. data/install/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  391. data/install/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  392. data/install/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  393. data/install/config/tools/handbook_creator/templates/title.html.erb +1 -1
  394. data/install/config/tools/launcher/launcher.txt +39 -39
  395. data/install/config/tools/script_runner/script_runner.txt +3 -3
  396. data/install/config/tools/test_runner/test_runner.txt +8 -8
  397. data/install/config/tools/tlm_viewer/tlm_viewer.txt +5 -5
  398. data/install/lib/user_version.rb +3 -3
  399. data/install/tools/CmdExtractor +15 -15
  400. data/install/tools/CmdExtractor.bat +59 -59
  401. data/install/tools/CmdSender +15 -15
  402. data/install/tools/CmdSender.bat +59 -59
  403. data/install/tools/CmdTlmServer +15 -15
  404. data/install/tools/CmdTlmServer.bat +59 -59
  405. data/install/tools/DataViewer +15 -15
  406. data/install/tools/DataViewer.bat +59 -59
  407. data/install/tools/HandbookCreator +15 -15
  408. data/install/tools/HandbookCreator.bat +61 -61
  409. data/install/tools/Launcher +15 -15
  410. data/install/tools/Launcher.bat +59 -59
  411. data/install/tools/LimitsMonitor +15 -15
  412. data/install/tools/LimitsMonitor.bat +59 -59
  413. data/install/tools/OpenGLBuilder +15 -15
  414. data/install/tools/OpenGLBuilder.bat +59 -59
  415. data/install/tools/PacketViewer +15 -15
  416. data/install/tools/PacketViewer.bat +59 -59
  417. data/install/tools/Replay +15 -15
  418. data/install/tools/Replay.bat +59 -59
  419. data/install/tools/ScriptRunner +15 -15
  420. data/install/tools/ScriptRunner.bat +59 -59
  421. data/install/tools/TableManager +15 -15
  422. data/install/tools/TableManager.bat +59 -59
  423. data/install/tools/TestRunner +15 -15
  424. data/install/tools/TestRunner.bat +59 -59
  425. data/install/tools/TlmExtractor +15 -15
  426. data/install/tools/TlmExtractor.bat +59 -59
  427. data/install/tools/TlmGrapher +15 -15
  428. data/install/tools/TlmGrapher.bat +59 -59
  429. data/install/tools/TlmViewer +15 -15
  430. data/install/tools/TlmViewer.bat +59 -59
  431. data/install/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  432. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +15 -15
  433. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +6 -6
  434. data/install/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  435. data/install/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +15 -15
  436. data/install/tools/mac/CmdSender.app/Contents/MacOS/main.sh +6 -6
  437. data/install/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  438. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +15 -15
  439. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +6 -6
  440. data/install/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  441. data/install/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +15 -15
  442. data/install/tools/mac/DataViewer.app/Contents/MacOS/main.sh +6 -6
  443. data/install/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  444. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +15 -15
  445. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +6 -6
  446. data/install/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  447. data/install/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +15 -15
  448. data/install/tools/mac/Launcher.app/Contents/MacOS/main.sh +6 -6
  449. data/install/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  450. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +15 -15
  451. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +6 -6
  452. data/install/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  453. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +15 -15
  454. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +6 -6
  455. data/install/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  456. data/install/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +15 -15
  457. data/install/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +6 -6
  458. data/install/tools/mac/Replay.app/Contents/Info.plist +38 -38
  459. data/install/tools/mac/Replay.app/Contents/MacOS/Replay.rb +15 -15
  460. data/install/tools/mac/Replay.app/Contents/MacOS/main.sh +6 -6
  461. data/install/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  462. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +15 -15
  463. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +6 -6
  464. data/install/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  465. data/install/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +15 -15
  466. data/install/tools/mac/TableManager.app/Contents/MacOS/main.sh +6 -6
  467. data/install/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  468. data/install/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +15 -15
  469. data/install/tools/mac/TestRunner.app/Contents/MacOS/main.sh +6 -6
  470. data/install/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  471. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +15 -15
  472. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +6 -6
  473. data/install/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  474. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +15 -15
  475. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +6 -6
  476. data/install/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  477. data/install/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +15 -15
  478. data/install/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +6 -6
  479. data/lib/cosmos.rb +63 -63
  480. data/lib/cosmos/ccsds/ccsds_packet.rb +63 -63
  481. data/lib/cosmos/ccsds/ccsds_parser.rb +143 -143
  482. data/lib/cosmos/config/config_parser.rb +324 -324
  483. data/lib/cosmos/conversions.rb +13 -13
  484. data/lib/cosmos/conversions/conversion.rb +47 -47
  485. data/lib/cosmos/conversions/generic_conversion.rb +55 -55
  486. data/lib/cosmos/conversions/new_packet_log_conversion.rb +45 -45
  487. data/lib/cosmos/conversions/polynomial_conversion.rb +57 -57
  488. data/lib/cosmos/conversions/processor_conversion.rb +46 -46
  489. data/lib/cosmos/conversions/received_count_conversion.rb +33 -33
  490. data/lib/cosmos/conversions/received_time_formatted_conversion.rb +37 -37
  491. data/lib/cosmos/conversions/received_time_seconds_conversion.rb +37 -37
  492. data/lib/cosmos/conversions/segmented_polynomial_conversion.rb +128 -128
  493. data/lib/cosmos/conversions/unix_time_conversion.rb +50 -50
  494. data/lib/cosmos/conversions/unix_time_formatted_conversion.rb +44 -44
  495. data/lib/cosmos/conversions/unix_time_seconds_conversion.rb +44 -44
  496. data/lib/cosmos/core_ext.rb +18 -18
  497. data/lib/cosmos/core_ext/array.rb +354 -354
  498. data/lib/cosmos/core_ext/class.rb +51 -51
  499. data/lib/cosmos/core_ext/cosmos_io.rb +29 -29
  500. data/lib/cosmos/core_ext/exception.rb +52 -52
  501. data/lib/cosmos/core_ext/file.rb +75 -75
  502. data/lib/cosmos/core_ext/hash.rb +28 -28
  503. data/lib/cosmos/core_ext/io.rb +75 -75
  504. data/lib/cosmos/core_ext/kernel.rb +38 -38
  505. data/lib/cosmos/core_ext/math.rb +119 -119
  506. data/lib/cosmos/core_ext/matrix.rb +146 -146
  507. data/lib/cosmos/core_ext/objectspace.rb +29 -29
  508. data/lib/cosmos/core_ext/range.rb +22 -22
  509. data/lib/cosmos/core_ext/socket.rb +32 -32
  510. data/lib/cosmos/core_ext/string.rb +310 -310
  511. data/lib/cosmos/core_ext/stringio.rb +24 -24
  512. data/lib/cosmos/core_ext/time.rb +446 -446
  513. data/lib/cosmos/gui/choosers/combobox_chooser.rb +130 -130
  514. data/lib/cosmos/gui/choosers/file_chooser.rb +68 -68
  515. data/lib/cosmos/gui/choosers/float_chooser.rb +82 -82
  516. data/lib/cosmos/gui/choosers/integer_chooser.rb +80 -80
  517. data/lib/cosmos/gui/choosers/string_chooser.rb +53 -53
  518. data/lib/cosmos/gui/choosers/telemetry_chooser.rb +317 -317
  519. data/lib/cosmos/gui/dialogs/about_dialog.rb +128 -128
  520. data/lib/cosmos/gui/dialogs/calendar_dialog.rb +136 -136
  521. data/lib/cosmos/gui/dialogs/cmd_details_dialog.rb +52 -52
  522. data/lib/cosmos/gui/dialogs/cmd_tlm_raw_dialog.rb +149 -149
  523. data/lib/cosmos/gui/dialogs/details_dialog.rb +174 -174
  524. data/lib/cosmos/gui/dialogs/exception_dialog.rb +97 -97
  525. data/lib/cosmos/gui/dialogs/exception_list_dialog.rb +59 -59
  526. data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +196 -196
  527. data/lib/cosmos/gui/dialogs/legal_dialog.rb +169 -168
  528. data/lib/cosmos/gui/dialogs/packet_log_dialog.rb +118 -118
  529. data/lib/cosmos/gui/dialogs/progress_dialog.rb +270 -262
  530. data/lib/cosmos/gui/dialogs/pry_dialog.rb +165 -161
  531. data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +37 -37
  532. data/lib/cosmos/gui/dialogs/select_dialog.rb +54 -54
  533. data/lib/cosmos/gui/dialogs/set_tlm_dialog.rb +131 -131
  534. data/lib/cosmos/gui/dialogs/splash.rb +113 -113
  535. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +206 -206
  536. data/lib/cosmos/gui/dialogs/tlm_edit_dialog.rb +81 -81
  537. data/lib/cosmos/gui/line_graph/line_graph.rb +456 -456
  538. data/lib/cosmos/gui/line_graph/line_graph_dialog.rb +34 -34
  539. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +494 -494
  540. data/lib/cosmos/gui/line_graph/line_graph_popups.rb +116 -116
  541. data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +460 -460
  542. data/lib/cosmos/gui/line_graph/line_graph_script.rb +26 -26
  543. data/lib/cosmos/gui/line_graph/lines.rb +290 -290
  544. data/lib/cosmos/gui/line_graph/overview_graph.rb +459 -459
  545. data/lib/cosmos/gui/opengl/earth_model.rb +22 -22
  546. data/lib/cosmos/gui/opengl/gl_bounds.rb +67 -67
  547. data/lib/cosmos/gui/opengl/gl_light.rb +39 -39
  548. data/lib/cosmos/gui/opengl/gl_material.rb +29 -29
  549. data/lib/cosmos/gui/opengl/gl_scene.rb +72 -72
  550. data/lib/cosmos/gui/opengl/gl_shape.rb +146 -146
  551. data/lib/cosmos/gui/opengl/gl_viewer.rb +724 -712
  552. data/lib/cosmos/gui/opengl/gl_viewport.rb +35 -35
  553. data/lib/cosmos/gui/opengl/moon_model.rb +22 -22
  554. data/lib/cosmos/gui/opengl/opengl.rb +8 -8
  555. data/lib/cosmos/gui/opengl/stl_reader.rb +211 -211
  556. data/lib/cosmos/gui/opengl/stl_shape.rb +124 -124
  557. data/lib/cosmos/gui/opengl/texture_mapped_sphere.rb +202 -202
  558. data/lib/cosmos/gui/qt.rb +813 -786
  559. data/lib/cosmos/gui/qt_tool.rb +378 -373
  560. data/lib/cosmos/gui/text/completion.rb +381 -381
  561. data/lib/cosmos/gui/text/completion_line_edit.rb +30 -30
  562. data/lib/cosmos/gui/text/completion_text_edit.rb +179 -179
  563. data/lib/cosmos/gui/text/ruby_editor.rb +395 -395
  564. data/lib/cosmos/gui/utilities/screenshot.rb +25 -25
  565. data/lib/cosmos/gui/utilities/script_module_gui.rb +203 -203
  566. data/lib/cosmos/gui/widgets/full_text_search_line_edit.rb +161 -161
  567. data/lib/cosmos/gui/widgets/packet_log_frame.rb +305 -305
  568. data/lib/cosmos/gui/widgets/realtime_button_bar.rb +98 -98
  569. data/lib/cosmos/interfaces.rb +11 -11
  570. data/lib/cosmos/interfaces/cmd_tlm_server_interface.rb +153 -149
  571. data/lib/cosmos/interfaces/interface.rb +213 -213
  572. data/lib/cosmos/interfaces/linc_interface.rb +360 -360
  573. data/lib/cosmos/interfaces/serial_interface.rb +76 -76
  574. data/lib/cosmos/interfaces/simulated_target_interface.rb +129 -128
  575. data/lib/cosmos/interfaces/stream_interface.rb +156 -156
  576. data/lib/cosmos/interfaces/tcpip_client_interface.rb +60 -60
  577. data/lib/cosmos/interfaces/tcpip_server_interface.rb +154 -154
  578. data/lib/cosmos/interfaces/udp_interface.rb +173 -173
  579. data/lib/cosmos/io/buffered_file.rb +11 -11
  580. data/lib/cosmos/io/cosmos_snmp.rb +50 -50
  581. data/lib/cosmos/io/io_multiplexer.rb +89 -89
  582. data/lib/cosmos/io/json_drb.rb +344 -320
  583. data/lib/cosmos/io/json_drb_object.rb +137 -137
  584. data/lib/cosmos/io/json_rpc.rb +365 -365
  585. data/lib/cosmos/io/posix_serial_driver.rb +145 -145
  586. data/lib/cosmos/io/raw_logger.rb +174 -174
  587. data/lib/cosmos/io/raw_logger_pair.rb +71 -71
  588. data/lib/cosmos/io/serial_driver.rb +85 -85
  589. data/lib/cosmos/io/stderr.rb +36 -36
  590. data/lib/cosmos/io/stdout.rb +36 -36
  591. data/lib/cosmos/io/tcpip_server.rb +583 -532
  592. data/lib/cosmos/io/udp_sockets.rb +152 -152
  593. data/lib/cosmos/io/win32_serial_driver.rb +147 -147
  594. data/lib/cosmos/packet_logs.rb +6 -6
  595. data/lib/cosmos/packet_logs/meta_packet_log_writer.rb +107 -107
  596. data/lib/cosmos/packet_logs/packet_log_reader.rb +441 -439
  597. data/lib/cosmos/packet_logs/packet_log_writer.rb +321 -309
  598. data/lib/cosmos/packet_logs/packet_log_writer_pair.rb +30 -30
  599. data/lib/cosmos/packets/binary_accessor.rb +921 -921
  600. data/lib/cosmos/packets/commands.rb +291 -291
  601. data/lib/cosmos/packets/limits.rb +263 -263
  602. data/lib/cosmos/packets/limits_response.rb +38 -38
  603. data/lib/cosmos/packets/packet.rb +714 -699
  604. data/lib/cosmos/packets/packet_config.rb +1034 -1034
  605. data/lib/cosmos/packets/packet_item.rb +317 -317
  606. data/lib/cosmos/packets/packet_item_limits.rb +128 -128
  607. data/lib/cosmos/packets/structure.rb +421 -386
  608. data/lib/cosmos/packets/structure_item.rb +233 -233
  609. data/lib/cosmos/packets/telemetry.rb +317 -317
  610. data/lib/cosmos/processors.rb +6 -6
  611. data/lib/cosmos/processors/new_packet_log_processor.rb +34 -34
  612. data/lib/cosmos/processors/processor.rb +71 -71
  613. data/lib/cosmos/processors/statistics_processor.rb +65 -65
  614. data/lib/cosmos/processors/watermark_processor.rb +44 -44
  615. data/lib/cosmos/script.rb +9 -9
  616. data/lib/cosmos/script/extract.rb +115 -115
  617. data/lib/cosmos/script/script.rb +1513 -1493
  618. data/lib/cosmos/streams/burst_stream_protocol.rb +25 -25
  619. data/lib/cosmos/streams/fixed_stream_protocol.rb +111 -111
  620. data/lib/cosmos/streams/length_stream_protocol.rb +140 -140
  621. data/lib/cosmos/streams/preidentified_stream_protocol.rb +118 -118
  622. data/lib/cosmos/streams/serial_stream.rb +152 -143
  623. data/lib/cosmos/streams/stream.rb +57 -57
  624. data/lib/cosmos/streams/stream_protocol.rb +369 -369
  625. data/lib/cosmos/streams/tcpip_client_stream.rb +77 -77
  626. data/lib/cosmos/streams/tcpip_socket_stream.rb +139 -139
  627. data/lib/cosmos/streams/template_stream_protocol.rb +140 -140
  628. data/lib/cosmos/streams/terminated_stream_protocol.rb +81 -81
  629. data/lib/cosmos/system.rb +4 -4
  630. data/lib/cosmos/system/system.rb +558 -558
  631. data/lib/cosmos/system/target.rb +178 -178
  632. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +254 -253
  633. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +716 -716
  634. data/lib/cosmos/tools/cmd_sender/cmd_sender_item_delegate.rb +77 -77
  635. data/lib/cosmos/tools/cmd_sender/cmd_sender_text_edit.rb +70 -70
  636. data/lib/cosmos/tools/cmd_tlm_server/api.rb +936 -940
  637. data/lib/cosmos/tools/cmd_tlm_server/background_task.rb +46 -46
  638. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +67 -63
  639. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +511 -497
  640. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +241 -241
  641. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +1033 -1008
  642. data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +112 -112
  643. data/lib/cosmos/tools/cmd_tlm_server/connections.rb +176 -176
  644. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +241 -221
  645. data/lib/cosmos/tools/cmd_tlm_server/interfaces.rb +127 -127
  646. data/lib/cosmos/tools/cmd_tlm_server/packet_logging.rb +132 -132
  647. data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +66 -66
  648. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +97 -97
  649. data/lib/cosmos/tools/data_viewer/data_viewer.rb +628 -600
  650. data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +167 -167
  651. data/lib/cosmos/tools/data_viewer/dump_component.rb +40 -40
  652. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +149 -149
  653. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +360 -360
  654. data/lib/cosmos/tools/launcher/launcher.rb +184 -184
  655. data/lib/cosmos/tools/launcher/launcher_config.rb +175 -167
  656. data/lib/cosmos/tools/launcher/launcher_multitool.rb +40 -41
  657. data/lib/cosmos/tools/launcher/launcher_tool.rb +104 -104
  658. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +796 -768
  659. data/lib/cosmos/tools/opengl_builder/opengl_builder.rb +416 -416
  660. data/lib/cosmos/tools/opengl_builder/scene_config.rb +118 -118
  661. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +525 -525
  662. data/lib/cosmos/tools/replay/replay.rb +495 -488
  663. data/lib/cosmos/tools/replay/replay_server.rb +91 -91
  664. data/lib/cosmos/tools/script_runner/script_audit.rb +147 -139
  665. data/lib/cosmos/tools/script_runner/script_runner.rb +914 -914
  666. data/lib/cosmos/tools/script_runner/script_runner_config.rb +40 -40
  667. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +1892 -1859
  668. data/lib/cosmos/tools/table_manager/table.rb +70 -70
  669. data/lib/cosmos/tools/table_manager/table_config.rb +764 -764
  670. data/lib/cosmos/tools/table_manager/table_item.rb +74 -74
  671. data/lib/cosmos/tools/table_manager/table_manager.rb +1065 -1065
  672. data/lib/cosmos/tools/table_manager/table_manager_core.rb +539 -539
  673. data/lib/cosmos/tools/test_runner/results_writer.rb +283 -283
  674. data/lib/cosmos/tools/test_runner/test.rb +480 -480
  675. data/lib/cosmos/tools/test_runner/test_runner.rb +1157 -1157
  676. data/lib/cosmos/tools/test_runner/test_runner_chooser.rb +338 -338
  677. data/lib/cosmos/tools/tlm_extractor/text_item_chooser.rb +60 -60
  678. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +1008 -1008
  679. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +371 -371
  680. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +60 -60
  681. data/lib/cosmos/tools/tlm_grapher/data_object_adders/housekeeping_data_object_adder.rb +75 -75
  682. data/lib/cosmos/tools/tlm_grapher/data_object_adders/singlexy_data_object_adder.rb +44 -44
  683. data/lib/cosmos/tools/tlm_grapher/data_object_adders/xy_data_object_adder.rb +94 -94
  684. data/lib/cosmos/tools/tlm_grapher/data_object_editors/data_object_editor.rb +61 -61
  685. data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +180 -180
  686. data/lib/cosmos/tools/tlm_grapher/data_object_editors/linegraph_data_object_editor.rb +141 -141
  687. data/lib/cosmos/tools/tlm_grapher/data_object_editors/singlexy_data_object_editor.rb +30 -30
  688. data/lib/cosmos/tools/tlm_grapher/data_object_editors/xy_data_object_editor.rb +173 -173
  689. data/lib/cosmos/tools/tlm_grapher/data_objects/data_object.rb +177 -177
  690. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +412 -409
  691. data/lib/cosmos/tools/tlm_grapher/data_objects/linegraph_data_object.rb +176 -176
  692. data/lib/cosmos/tools/tlm_grapher/data_objects/singlexy_data_object.rb +25 -25
  693. data/lib/cosmos/tools/tlm_grapher/data_objects/xy_data_object.rb +323 -320
  694. data/lib/cosmos/tools/tlm_grapher/plot_editors/linegraph_plot_editor.rb +181 -181
  695. data/lib/cosmos/tools/tlm_grapher/plot_editors/plot_editor.rb +28 -28
  696. data/lib/cosmos/tools/tlm_grapher/plot_editors/singlexy_plot_editor.rb +30 -30
  697. data/lib/cosmos/tools/tlm_grapher/plot_editors/xy_plot_editor.rb +59 -59
  698. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/linegraph_plot_gui_object.rb +172 -172
  699. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/singlexy_plot_gui_object.rb +27 -27
  700. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/xy_plot_gui_object.rb +74 -74
  701. data/lib/cosmos/tools/tlm_grapher/plots/linegraph_plot.rb +201 -201
  702. data/lib/cosmos/tools/tlm_grapher/plots/plot.rb +69 -69
  703. data/lib/cosmos/tools/tlm_grapher/plots/singlexy_plot.rb +20 -20
  704. data/lib/cosmos/tools/tlm_grapher/plots/xy_plot.rb +61 -61
  705. data/lib/cosmos/tools/tlm_grapher/tabbed_plots/overview_tabbed_plots.rb +1278 -1278
  706. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +430 -430
  707. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_data_object_editor.rb +107 -107
  708. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_logfile_thread.rb +111 -95
  709. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_plot_editor.rb +101 -101
  710. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +72 -66
  711. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tab.rb +57 -57
  712. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +1004 -1004
  713. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +87 -87
  714. data/lib/cosmos/tools/tlm_viewer/screen.rb +486 -458
  715. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +563 -544
  716. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +287 -287
  717. data/lib/cosmos/tools/tlm_viewer/widgets.rb +53 -53
  718. data/lib/cosmos/tools/tlm_viewer/widgets/aging_widget.rb +110 -110
  719. data/lib/cosmos/tools/tlm_viewer/widgets/array_widget.rb +70 -70
  720. data/lib/cosmos/tools/tlm_viewer/widgets/block_widget.rb +61 -61
  721. data/lib/cosmos/tools/tlm_viewer/widgets/button_widget.rb +39 -39
  722. data/lib/cosmos/tools/tlm_viewer/widgets/canvas_widget.rb +62 -62
  723. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimage_widget.rb +41 -41
  724. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimagevalue_widget.rb +57 -57
  725. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabel_widget.rb +37 -37
  726. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabelvalue_widget.rb +56 -56
  727. data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +55 -55
  728. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +66 -66
  729. data/lib/cosmos/tools/tlm_viewer/widgets/canvasvalue_widget.rb +124 -124
  730. data/lib/cosmos/tools/tlm_viewer/widgets/checkbutton_widget.rb +31 -31
  731. data/lib/cosmos/tools/tlm_viewer/widgets/combobox_widget.rb +30 -30
  732. data/lib/cosmos/tools/tlm_viewer/widgets/formatfontvalue_widget.rb +36 -36
  733. data/lib/cosmos/tools/tlm_viewer/widgets/formatvalue_widget.rb +35 -35
  734. data/lib/cosmos/tools/tlm_viewer/widgets/horizontal_widget.rb +27 -27
  735. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalbox_widget.rb +31 -31
  736. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalline_widget.rb +26 -26
  737. data/lib/cosmos/tools/tlm_viewer/widgets/label_widget.rb +29 -29
  738. data/lib/cosmos/tools/tlm_viewer/widgets/labelformatvalue_widget.rb +39 -39
  739. data/lib/cosmos/tools/tlm_viewer/widgets/labelprogressbar_widget.rb +38 -38
  740. data/lib/cosmos/tools/tlm_viewer/widgets/labeltrendlimitsbar_widget.rb +38 -38
  741. data/lib/cosmos/tools/tlm_viewer/widgets/labelvalue_widget.rb +39 -39
  742. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluedesc_widget.rb +42 -42
  743. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluelimitsbar_widget.rb +37 -37
  744. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluerangebar_widget.rb +37 -37
  745. data/lib/cosmos/tools/tlm_viewer/widgets/layout_widget.rb +34 -34
  746. data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +178 -178
  747. data/lib/cosmos/tools/tlm_viewer/widgets/linegraph_widget.rb +54 -54
  748. data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +47 -47
  749. data/lib/cosmos/tools/tlm_viewer/widgets/multi_widget.rb +116 -116
  750. data/lib/cosmos/tools/tlm_viewer/widgets/progressbar_widget.rb +34 -34
  751. data/lib/cosmos/tools/tlm_viewer/widgets/radiobutton_widget.rb +30 -30
  752. data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +57 -57
  753. data/lib/cosmos/tools/tlm_viewer/widgets/screenshotbutton_widget.rb +34 -34
  754. data/lib/cosmos/tools/tlm_viewer/widgets/scrollwindow_widget.rb +35 -35
  755. data/lib/cosmos/tools/tlm_viewer/widgets/sectionheader_widget.rb +33 -33
  756. data/lib/cosmos/tools/tlm_viewer/widgets/tabbook_widget.rb +26 -26
  757. data/lib/cosmos/tools/tlm_viewer/widgets/tabitem_widget.rb +28 -28
  758. data/lib/cosmos/tools/tlm_viewer/widgets/textbox_widget.rb +47 -47
  759. data/lib/cosmos/tools/tlm_viewer/widgets/textfield_widget.rb +26 -26
  760. data/lib/cosmos/tools/tlm_viewer/widgets/timegraph_widget.rb +88 -88
  761. data/lib/cosmos/tools/tlm_viewer/widgets/title_widget.rb +27 -27
  762. data/lib/cosmos/tools/tlm_viewer/widgets/trendbar_widget.rb +130 -130
  763. data/lib/cosmos/tools/tlm_viewer/widgets/trendlimitsbar_widget.rb +46 -46
  764. data/lib/cosmos/tools/tlm_viewer/widgets/value_widget.rb +43 -43
  765. data/lib/cosmos/tools/tlm_viewer/widgets/valuelimitsbar_widget.rb +37 -37
  766. data/lib/cosmos/tools/tlm_viewer/widgets/valuerangebar_widget.rb +37 -37
  767. data/lib/cosmos/tools/tlm_viewer/widgets/vertical_widget.rb +35 -35
  768. data/lib/cosmos/tools/tlm_viewer/widgets/verticalbox_widget.rb +37 -37
  769. data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +257 -257
  770. data/lib/cosmos/top_level.rb +647 -596
  771. data/lib/cosmos/utilities.rb +11 -10
  772. data/lib/cosmos/utilities/crc.rb +166 -166
  773. data/lib/cosmos/utilities/csv.rb +83 -83
  774. data/lib/cosmos/utilities/logger.rb +137 -137
  775. data/lib/cosmos/utilities/low_fragmentation_array.rb +11 -11
  776. data/lib/cosmos/utilities/message_log.rb +74 -74
  777. data/lib/cosmos/utilities/quaternion.rb +258 -258
  778. data/lib/cosmos/utilities/ruby_lex_utils.rb +313 -313
  779. data/lib/cosmos/utilities/simulated_target.rb +99 -99
  780. data/lib/cosmos/utilities/sleeper.rb +44 -0
  781. data/lib/cosmos/version.rb +12 -12
  782. data/lib/cosmos/win32/excel.rb +66 -66
  783. data/lib/cosmos/win32/win32.rb +387 -387
  784. data/lib/cosmos/win32/win32_main.rb +311 -311
  785. data/roodi.yml +24 -24
  786. data/run_gui_tests.bat +32 -32
  787. data/spec/ccsds/ccsds_packet_spec.rb +67 -67
  788. data/spec/ccsds/ccsds_parser_spec.rb +148 -148
  789. data/spec/config/config_parser_spec.rb +322 -322
  790. data/spec/conversions/conversion_spec.rb +31 -31
  791. data/spec/conversions/generic_conversion_spec.rb +45 -45
  792. data/spec/conversions/new_packet_log_conversion_spec.rb +39 -39
  793. data/spec/conversions/polynomial_conversion_spec.rb +40 -40
  794. data/spec/conversions/processor_conversion_spec.rb +45 -45
  795. data/spec/conversions/received_count_conversion_spec.rb +43 -43
  796. data/spec/conversions/received_time_formatted_conversion_spec.rb +49 -49
  797. data/spec/conversions/received_time_seconds_conversion_spec.rb +50 -50
  798. data/spec/conversions/segmented_polynomial_conversion_spec.rb +51 -51
  799. data/spec/conversions/unix_time_formatted_conversion_spec.rb +74 -74
  800. data/spec/conversions/unix_time_seconds_conversion_spec.rb +76 -76
  801. data/spec/core_ext/array_spec.rb +186 -186
  802. data/spec/core_ext/class_spec.rb +36 -36
  803. data/spec/core_ext/cosmos_io_spec.rb +77 -77
  804. data/spec/core_ext/exception_spec.rb +91 -91
  805. data/spec/core_ext/file_spec.rb +72 -72
  806. data/spec/core_ext/hash_spec.rb +24 -24
  807. data/spec/core_ext/io_spec.rb +46 -46
  808. data/spec/core_ext/kernel_spec.rb +54 -54
  809. data/spec/core_ext/math_spec.rb +116 -116
  810. data/spec/core_ext/matrix_spec.rb +66 -66
  811. data/spec/core_ext/objectspace_spec.rb +29 -29
  812. data/spec/core_ext/range_spec.rb +21 -21
  813. data/spec/core_ext/socket_spec.rb +32 -32
  814. data/spec/core_ext/string_spec.rb +223 -223
  815. data/spec/core_ext/stringio_spec.rb +21 -21
  816. data/spec/core_ext/time_spec.rb +151 -151
  817. data/spec/gui/line_graph/line_clip_spec.rb +322 -322
  818. data/spec/install/config/system/system.txt +33 -33
  819. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  820. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  821. data/spec/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  822. data/spec/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  823. data/spec/install/config/targets/COSMOS/screens/version.txt +19 -19
  824. data/spec/install/config/targets/COSMOS/target.txt +5 -5
  825. data/spec/install/config/targets/INST/cmd_tlm/inst_cmd_linc.txt +30 -30
  826. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +111 -111
  827. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm.txt +236 -236
  828. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm_linc.txt +25 -25
  829. data/spec/install/config/targets/INST/cmd_tlm_server.txt +5 -5
  830. data/spec/install/config/targets/INST/lib/sim_inst.rb +305 -294
  831. data/spec/install/config/targets/INST/target.txt +10 -10
  832. data/spec/install/config/targets/META/cmd_tlm/meta_cmd.txt +4 -4
  833. data/spec/install/config/targets/META/cmd_tlm/meta_tlm.txt +4 -4
  834. data/spec/install/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  835. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +150 -150
  836. data/spec/interfaces/interface_spec.rb +130 -131
  837. data/spec/interfaces/linc_interface_spec.rb +199 -199
  838. data/spec/interfaces/serial_interface_spec.rb +56 -56
  839. data/spec/interfaces/simulated_target_interface_spec.rb +128 -128
  840. data/spec/interfaces/stream_interface_spec.rb +157 -157
  841. data/spec/interfaces/tcpip_client_interface_spec.rb +54 -54
  842. data/spec/interfaces/tcpip_server_interface_spec.rb +151 -151
  843. data/spec/interfaces/udp_interface_spec.rb +175 -177
  844. data/spec/io/buffered_file_spec.rb +113 -113
  845. data/spec/io/io_multiplexer_spec.rb +94 -94
  846. data/spec/io/json_drb_object_spec.rb +99 -99
  847. data/spec/io/json_drb_spec.rb +311 -311
  848. data/spec/io/json_rpc_spec.rb +264 -264
  849. data/spec/io/raw_logger_pair_spec.rb +76 -76
  850. data/spec/io/raw_logger_spec.rb +133 -133
  851. data/spec/io/serial_driver_spec.rb +61 -61
  852. data/spec/io/stderr_spec.rb +32 -32
  853. data/spec/io/stdout_spec.rb +32 -32
  854. data/spec/io/tcpip_server_spec.rb +338 -338
  855. data/spec/io/udp_sockets_spec.rb +94 -94
  856. data/spec/io/win32_serial_driver_spec.rb +88 -88
  857. data/spec/packet_logs/meta_packet_log_writer_spec.rb +170 -170
  858. data/spec/packet_logs/packet_log_reader_spec.rb +408 -408
  859. data/spec/packet_logs/packet_log_writer_pair_spec.rb +30 -30
  860. data/spec/packet_logs/packet_log_writer_spec.rb +223 -223
  861. data/spec/packets/binary_accessor_spec.rb +2073 -2073
  862. data/spec/packets/commands_spec.rb +369 -369
  863. data/spec/packets/limits_response_spec.rb +25 -25
  864. data/spec/packets/limits_spec.rb +326 -326
  865. data/spec/packets/packet_config_spec.rb +1620 -1620
  866. data/spec/packets/packet_item_limits_spec.rb +161 -161
  867. data/spec/packets/packet_item_spec.rb +386 -386
  868. data/spec/packets/packet_spec.rb +1057 -949
  869. data/spec/packets/structure_item_spec.rb +195 -195
  870. data/spec/packets/structure_spec.rb +419 -419
  871. data/spec/packets/telemetry_spec.rb +535 -535
  872. data/spec/processors/new_packet_log_processor_spec.rb +39 -39
  873. data/spec/processors/processor_spec.rb +55 -55
  874. data/spec/processors/statistics_processor_spec.rb +60 -60
  875. data/spec/processors/watermark_processor_spec.rb +51 -51
  876. data/spec/script/script_spec.rb +654 -654
  877. data/spec/spec_helper.rb +154 -148
  878. data/spec/streams/burst_stream_protocol_spec.rb +32 -32
  879. data/spec/streams/fixed_stream_protocol_spec.rb +110 -110
  880. data/spec/streams/length_stream_protocol_spec.rb +297 -297
  881. data/spec/streams/preidentified_stream_protocol_spec.rb +118 -118
  882. data/spec/streams/serial_stream_spec.rb +105 -105
  883. data/spec/streams/stream_protocol_spec.rb +332 -332
  884. data/spec/streams/stream_spec.rb +29 -29
  885. data/spec/streams/tcpip_client_stream_spec.rb +54 -54
  886. data/spec/streams/tcpip_socket_stream_spec.rb +146 -146
  887. data/spec/streams/template_stream_protocol_spec.rb +151 -151
  888. data/spec/streams/terminated_stream_protocol_spec.rb +123 -123
  889. data/spec/system/system_spec.rb +645 -645
  890. data/spec/system/target_spec.rb +248 -248
  891. data/spec/tools/cmd_tlm_server/api_spec.rb +1087 -1113
  892. data/spec/tools/cmd_tlm_server/background_task_spec.rb +32 -32
  893. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +81 -81
  894. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +411 -411
  895. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +415 -415
  896. data/spec/tools/cmd_tlm_server/commanding_spec.rb +123 -123
  897. data/spec/tools/cmd_tlm_server/connections_spec.rb +147 -147
  898. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +306 -306
  899. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +252 -238
  900. data/spec/tools/cmd_tlm_server/packet_logging_spec.rb +143 -143
  901. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +98 -101
  902. data/spec/tools/cmd_tlm_server/routers_spec.rb +223 -208
  903. data/spec/top_level/top_level_spec.rb +334 -321
  904. data/spec/utilities/crc_spec.rb +45 -45
  905. data/spec/utilities/csv_spec.rb +97 -97
  906. data/spec/utilities/logger_spec.rb +102 -102
  907. data/spec/utilities/message_log_spec.rb +89 -89
  908. data/spec/utilities/quaternion_spec.rb +107 -107
  909. data/spec/utilities/ruby_lex_utils_spec.rb +86 -86
  910. data/tasks/manifest.rake +22 -22
  911. data/tasks/spec.rake +23 -23
  912. metadata +18 -2
@@ -1,914 +1,914 @@
1
- # encoding: ascii-8bit
2
-
3
- # Copyright 2014 Ball Aerospace & Technologies Corp.
4
- # All Rights Reserved.
5
- #
6
- # This program is free software; you can modify and/or redistribute it
7
- # under the terms of the GNU General Public License
8
- # as published by the Free Software Foundation; version 3 with
9
- # attribution addendums as found in the LICENSE.txt
10
-
11
- require 'cosmos'
12
- Cosmos.catch_fatal_exception do
13
- require 'cosmos/gui/qt_tool'
14
- require 'cosmos/tools/script_runner/script_runner_frame'
15
- require 'cosmos/tools/script_runner/script_runner_config'
16
- require 'cosmos/tools/script_runner/script_audit'
17
- require 'cosmos/gui/dialogs/progress_dialog'
18
- require 'cosmos/gui/dialogs/scroll_text_dialog'
19
- end
20
-
21
- module Cosmos
22
-
23
- class ScriptRunner < QtTool
24
- slots 'handle_tab_change(int)'
25
- slots 'context_menu(const QPoint&)'
26
- slots 'undo_available(bool)'
27
-
28
- UNTITLED_TAB_TEXT = ' Untitled '
29
-
30
- def initialize(options)
31
- # All code before super is executed twice in RubyQt Based classes
32
- super(options) # MUST BE FIRST
33
- Cosmos.load_cosmos_icon("script_runner.png")
34
- setAcceptDrops(true) # Allow dropping in files
35
-
36
- @config_file = options.config_file
37
- @server_config_file = options.server_config_file
38
-
39
- # Add procedures to search path
40
- System.paths['PROCEDURES'].each do |path|
41
- Cosmos.add_to_search_path(path)
42
- end
43
-
44
- initialize_actions()
45
- initialize_menus()
46
- initialize_central_widget()
47
- complete_initialize()
48
-
49
- # Load icons
50
- @running_icon = Cosmos.get_icon('running.png')
51
- @no_icon = Qt::Icon.new
52
-
53
- # Handle configuration
54
- filename = File.join(::Cosmos::USERPATH, %w(config tools script_runner), @config_file)
55
- if File.exist?(filename)
56
- ScriptRunnerConfig.new(filename)
57
- elsif @config_file != 'script_runner.txt'
58
- raise "Could not find config file #{filename}"
59
- end
60
-
61
- @procedure_dir = System.paths['PROCEDURES'][0]
62
- @debug = false
63
-
64
- # Create the initial tab(s)
65
- if ARGV.length == 0
66
- create_tab()
67
- else
68
- ARGV.each {|argv_filename| create_tab(argv_filename)}
69
- end
70
- end
71
-
72
- def initialize_actions
73
- super()
74
-
75
- # File actions
76
- @file_new = Qt::Action.new(Cosmos.get_icon('file.png'), tr('&New'), self)
77
- @file_new_keyseq = Qt::KeySequence.new(tr('Ctrl+N'))
78
- @file_new.shortcut = @file_new_keyseq
79
- @file_new.statusTip = tr('Start a new script')
80
- @file_new.connect(SIGNAL('triggered()')) { file_new() }
81
-
82
- @file_open = Qt::Action.new(Cosmos.get_icon('open.png'), tr('&Open'), self)
83
- @file_open_keyseq = Qt::KeySequence.new(tr('Ctrl+O'))
84
- @file_open.shortcut = @file_open_keyseq
85
- @file_open.statusTip = tr('Open a script')
86
- @file_open.connect(SIGNAL('triggered()')) { file_open() }
87
-
88
- @file_close = Qt::Action.new(tr('&Close'), self)
89
- @file_close_keyseq = Qt::KeySequence.new(tr('Ctrl+W'))
90
- @file_close.shortcut = @file_close_keyseq
91
- @file_close.statusTip = tr('Close the script')
92
- @file_close.connect(SIGNAL('triggered()')) { file_close() }
93
-
94
- @file_reload = Qt::Action.new(tr('&Reload'), self)
95
- @file_reload_keyseq = Qt::KeySequence.new(tr('Ctrl+R'))
96
- @file_reload.shortcut = @file_reload_keyseq
97
- @file_reload.statusTip = tr('Reload a script')
98
- @file_reload.connect(SIGNAL('triggered()')) { file_reload() }
99
-
100
- @file_save = Qt::Action.new(Cosmos.get_icon('save.png'), tr('&Save'), self)
101
- @file_save_keyseq = Qt::KeySequence.new(tr('Ctrl+S'))
102
- @file_save.shortcut = @file_save_keyseq
103
- @file_save.statusTip = tr('Save the script')
104
- @file_save.connect(SIGNAL('triggered()')) { file_save(false) }
105
-
106
- @file_save_as = Qt::Action.new(Cosmos.get_icon('save_as.png'), tr('Save &As'), self)
107
- @file_save_as.statusTip = tr('Save the script')
108
- @file_save_as.connect(SIGNAL('triggered()')) { file_save(true) }
109
-
110
- @file_options = Qt::Action.new(tr('O&ptions'), self)
111
- @file_options.statusTip = tr('Application Options')
112
- @file_options.connect(SIGNAL('triggered()')) { file_options() }
113
-
114
- # Edit actions
115
- @edit_undo = Qt::Action.new(Cosmos.get_icon('undo.png'), tr('&Undo'), self)
116
- @edit_undo_keyseq = Qt::KeySequence.new(tr('Ctrl+Z'))
117
- @edit_undo.shortcut = @edit_undo_keyseq
118
- @edit_undo.statusTip = tr('Undo')
119
- @edit_undo.connect(SIGNAL('triggered()')) { active_script_runner_frame().undo }
120
-
121
- @edit_redo = Qt::Action.new(Cosmos.get_icon('redo.png'), tr('&Redo'), self)
122
- @edit_redo_keyseq = Qt::KeySequence.new(tr('Ctrl+Y'))
123
- @edit_redo.shortcut = @edit_redo_keyseq
124
- @edit_redo.statusTip = tr('Redo')
125
- @edit_redo.connect(SIGNAL('triggered()')) { active_script_runner_frame().redo }
126
-
127
- @edit_cut = Qt::Action.new(Cosmos.get_icon('cut.png'), tr('Cu&t'), self)
128
- @edit_cut_keyseq = Qt::KeySequence.new(tr('Ctrl+X'))
129
- @edit_cut.shortcut = @edit_cut_keyseq
130
- @edit_cut.statusTip = tr('Cut')
131
- @edit_cut.connect(SIGNAL('triggered()')) { active_script_runner_frame().cut }
132
-
133
- @edit_copy = Qt::Action.new(Cosmos.get_icon('copy.png'), tr('&Copy'), self)
134
- @edit_copy_keyseq = Qt::KeySequence.new(tr('Ctrl+C'))
135
- @edit_copy.shortcut = @edit_copy_keyseq
136
- @edit_copy.statusTip = tr('Copy')
137
- @edit_copy.connect(SIGNAL('triggered()')) { active_script_runner_frame().copy }
138
-
139
- @edit_paste = Qt::Action.new(tr('&Paste'), self)
140
- @edit_paste_keyseq = Qt::KeySequence.new(tr('Ctrl+V'))
141
- @edit_paste.shortcut = @edit_paste_keyseq
142
- @edit_paste.statusTip = tr('Paste')
143
- @edit_paste.connect(SIGNAL('triggered()')) { active_script_runner_frame().paste }
144
-
145
- @edit_select_all = Qt::Action.new(tr('Select &All'), self)
146
- @edit_select_all_keyseq = Qt::KeySequence.new(tr('Ctrl+A'))
147
- @edit_select_all.shortcut = @edit_select_all_keyseq
148
- @edit_select_all.statusTip = tr('Select All')
149
- @edit_select_all.connect(SIGNAL('triggered()')) { active_script_runner_frame().select_all }
150
-
151
- @edit_comment = Qt::Action.new(tr('Comment/Uncomment &Lines'), self)
152
- @edit_comment_keyseq = Qt::KeySequence.new(tr('Ctrl+K'))
153
- @edit_comment.shortcut = @edit_comment_keyseq
154
- @edit_comment.statusTip = tr('Comment/Uncomment Lines')
155
- @edit_comment.connect(SIGNAL('triggered()')) { active_script_runner_frame().comment_or_uncomment_lines }
156
-
157
- # Search Actions
158
- @search_find = Qt::Action.new(Cosmos.get_icon('search.png'), tr('&Find'), self)
159
- @search_find_keyseq = Qt::KeySequence.new(tr('Ctrl+F'))
160
- @search_find.shortcut = @search_find_keyseq
161
- @search_find.statusTip = tr('Find text')
162
- @search_find.connect(SIGNAL('triggered()')) { active_script_runner_frame.find() }
163
-
164
- @search_find_next = Qt::Action.new(tr('Find &Next'), self)
165
- @search_find_next_keyseq = Qt::KeySequence.new(tr('F3'))
166
- @search_find_next.shortcut = @search_find_next_keyseq
167
- @search_find_next.statusTip = tr('Find next instance')
168
- @search_find_next.connect(SIGNAL('triggered()')) { active_script_runner_frame.find_next() }
169
-
170
- @search_find_previous = Qt::Action.new(tr('Find &Previous'), self)
171
- @search_find_previous_keyseq = Qt::KeySequence.new(tr('Shift+F3'))
172
- @search_find_previous.shortcut = @search_find_previous_keyseq
173
- @search_find_previous.statusTip = tr('Find previous instance')
174
- @search_find_previous.connect(SIGNAL('triggered()')) { active_script_runner_frame.find_previous() }
175
-
176
- @search_replace = Qt::Action.new(tr('&Replace'), self)
177
- @search_replace_keyseq = Qt::KeySequence.new(tr('Ctrl+H'))
178
- @search_replace.shortcut = @search_replace_keyseq
179
- @search_replace.statusTip = tr('Replace')
180
- @search_replace.connect(SIGNAL('triggered()')) { active_script_runner_frame.replace() }
181
-
182
- # Script Actions
183
- @script_syntax_all = Qt::Action.new(tr('&Ruby Syntax Check'), self)
184
- @script_syntax_all.statusTip = tr('Check ruby syntax of this script')
185
- @script_syntax_all.connect(SIGNAL('triggered()')) do
186
- active_script_runner_frame().ruby_syntax_check_text(active_script_runner_frame().text)
187
- end
188
-
189
- @script_mnemonic_all = Qt::Action.new(tr('&Mnemonic Check'), self)
190
- @script_mnemonic_all.statusTip = tr('Check mnemonics of this script')
191
- @script_mnemonic_all.connect(SIGNAL('triggered()')) do
192
- active_script_runner_frame().mnemonic_check_text(active_script_runner_frame().text)
193
- end
194
-
195
- @script_execute_lines = Qt::Action.new(tr('&Execute Selected Lines'), self)
196
- @script_execute_lines.statusTip = tr('Execute selected lines')
197
- @script_execute_lines.connect(SIGNAL('triggered()')) { active_script_runner_frame().run_selection }
198
-
199
- @script_execute_cursor = Qt::Action.new(tr('E&xecute From Cursor'), self)
200
- @script_execute_cursor.statusTip = tr('Execute from cursor position')
201
- @script_execute_cursor.connect(SIGNAL('triggered()')) { active_script_runner_frame().run_from_cursor }
202
-
203
- @script_syntax_lines = Qt::Action.new(tr('Ruby &Syntax Check Selected Lines'), self)
204
- @script_syntax_lines.statusTip = tr('Check ruby syntax of selected lines')
205
- @script_syntax_lines.connect(SIGNAL('triggered()')) { active_script_runner_frame().ruby_syntax_check_selection }
206
-
207
- @script_mnemonic_lines = Qt::Action.new(tr('M&nemonic Check Selected Lines'), self)
208
- @script_mnemonic_lines.statusTip = tr('Check mnemonics of selected lines')
209
- @script_mnemonic_lines.connect(SIGNAL('triggered()')) { active_script_runner_frame().mnemonic_check_selection }
210
-
211
- @script_audit = Qt::Action.new(tr('&Generate Cmd/Tlm Audit'), self)
212
- @script_audit.statusTip = tr('Generate audit about commands sent and telemetry checked')
213
- @script_audit.connect(SIGNAL('triggered()')) { script_audit() }
214
-
215
- @script_instrumented = Qt::Action.new(tr('&View Instrumented Script'), self)
216
- @script_instrumented.statusTip = tr('View instrumented script')
217
- @script_instrumented.connect(SIGNAL('triggered()')) { script_view_instrumented() }
218
-
219
- @script_log_message = Qt::Action.new(tr('Log Message to Script Log'), self)
220
- @script_log_message.statusTip = tr('Log Message to Script Log')
221
- @script_log_message.connect(SIGNAL('triggered()')) { script_log_message() }
222
- @script_log_message.setEnabled(false)
223
-
224
- @script_call_stack = Qt::Action.new(tr('Show Call Stack'), self)
225
- @script_call_stack.statusTip = tr('Show Call Stack')
226
- @script_call_stack.connect(SIGNAL('triggered()')) { script_call_stack() }
227
- @script_call_stack.setEnabled(false)
228
-
229
- @script_debug = Qt::Action.new(Cosmos.get_icon('bug.png'), tr('Toggle &Debug'), self)
230
- @script_debug_keyseq = Qt::KeySequence.new(tr('Ctrl+D'))
231
- @script_debug.shortcut = @script_debug_keyseq
232
- @script_debug.statusTip = tr('Toggle debug capabilities for the script')
233
- @script_debug.connect(SIGNAL('triggered()')) { script_toggle_debug() }
234
-
235
- @script_disconnect = Qt::Action.new(Cosmos.get_icon('disconnected.png'), tr('&Toggle Disconnect'), self)
236
- @script_disconnect_keyseq = Qt::KeySequence.new(tr('Ctrl+T'))
237
- @script_disconnect.shortcut = @script_disconnect_keyseq
238
- @script_disconnect.statusTip = tr('Toggle disconnect from the server')
239
- @script_disconnect.connect(SIGNAL('triggered()')) { script_toggle_disconnect() }
240
- end
241
-
242
- def initialize_menus
243
- # File Menu
244
- file_menu = menuBar.addMenu(tr('&File'))
245
- file_menu.addAction(@file_new)
246
- file_menu.addAction(@file_open)
247
- file_menu.addAction(@file_close)
248
- file_menu.addAction(@file_reload)
249
- file_menu.addSeparator()
250
- file_menu.addAction(@file_save)
251
- file_menu.addAction(@file_save_as)
252
- file_menu.addSeparator()
253
- file_menu.addAction(@file_options)
254
- file_menu.addSeparator()
255
- file_menu.addAction(@exit_action)
256
-
257
- # Edit Menu
258
- mode_menu = menuBar.addMenu(tr('&Edit'))
259
- mode_menu.addAction(@edit_undo)
260
- mode_menu.addAction(@edit_redo)
261
- mode_menu.addSeparator()
262
- mode_menu.addAction(@edit_cut)
263
- mode_menu.addAction(@edit_copy)
264
- mode_menu.addAction(@edit_paste)
265
- mode_menu.addSeparator()
266
- mode_menu.addAction(@edit_select_all)
267
- mode_menu.addSeparator()
268
- mode_menu.addAction(@edit_comment)
269
-
270
- # Search Menu
271
- view_menu = menuBar.addMenu(tr('&Search'))
272
- view_menu.addAction(@search_find)
273
- view_menu.addAction(@search_find_next)
274
- view_menu.addAction(@search_find_previous)
275
- view_menu.addAction(@search_replace)
276
-
277
- # Script Menu
278
- view_menu = menuBar.addMenu(tr('Scrip&t'))
279
- view_menu.addAction(@script_syntax_all)
280
- view_menu.addAction(@script_syntax_lines)
281
- view_menu.addSeparator()
282
- view_menu.addAction(@script_mnemonic_all)
283
- view_menu.addAction(@script_mnemonic_lines)
284
- view_menu.addSeparator()
285
- view_menu.addAction(@script_execute_lines)
286
- view_menu.addAction(@script_execute_cursor)
287
- view_menu.addSeparator()
288
- view_menu.addAction(@script_audit)
289
- view_menu.addAction(@script_instrumented)
290
- view_menu.addSeparator()
291
- view_menu.addAction(@script_log_message)
292
- view_menu.addAction(@script_call_stack)
293
- view_menu.addAction(@script_debug)
294
- view_menu.addAction(@script_disconnect)
295
-
296
- # Help Menu
297
- @about_string = "Script Runner allows the user to execute commands "\
298
- "and take action on telemetry within a saveable script. "\
299
- "It allows the full power of the Ruby programming language "\
300
- "while defining several keywords to manipulate commands and telemetry in COSMOS.\n"
301
-
302
- initialize_help_menu()
303
- end
304
-
305
- def initialize_central_widget
306
- # Create the central widget
307
- @tab_book = Qt::TabWidget.new
308
- @tab_book.setMovable(true)
309
- @tab_book.setContextMenuPolicy(Qt::CustomContextMenu)
310
- connect(@tab_book,
311
- SIGNAL('customContextMenuRequested(const QPoint&)'),
312
- self,
313
- SLOT('context_menu(const QPoint&)'))
314
- connect(@tab_book,
315
- SIGNAL('currentChanged(int)'),
316
- self,
317
- SLOT('handle_tab_change(int)'))
318
- setCentralWidget(@tab_book)
319
-
320
- # Display a blank message to force the statusBar to show
321
- statusBar.showMessage("")
322
- end
323
-
324
- ###########################################
325
- # Drag files into ScriptRunner support
326
- ###########################################
327
-
328
- def dragEnterEvent(event)
329
- if event.mimeData.hasUrls
330
- event.acceptProposedAction();
331
- end
332
- end
333
-
334
- def dragMoveEvent(event)
335
- if event.mimeData.hasUrls
336
- event.acceptProposedAction();
337
- end
338
- end
339
-
340
- def dropEvent(event)
341
- event.mimeData.urls.each do |url|
342
- filename = url.toLocalFile
343
- extension = File.extname(filename).to_s.downcase
344
- if extension == '.rb' or extension == '.txt'
345
- file_open(filename)
346
- end
347
- end
348
- end
349
-
350
- ###########################################
351
- # File Menu Options
352
- ###########################################
353
-
354
- # File->New
355
- def file_new
356
- create_tab()
357
- end
358
-
359
- # File->Open
360
- def file_open(filename = nil)
361
- if !filename
362
- filename = Qt::FileDialog.getOpenFileName(self, "Select Script", @procedure_dir)
363
- end
364
- unless filename.nil? || filename.empty?
365
- # If the user opens a file we already have open
366
- # just set the current tab to that file and return
367
- @tab_book.tabs.each_with_index do |tab, index|
368
- if tab.filename == filename
369
- @tab_book.setCurrentIndex(index)
370
- @tab_book.currentTab.set_text_from_file(filename)
371
- @tab_book.currentTab.filename = filename
372
- return
373
- end
374
- end
375
-
376
- if ((@tab_book.count == 1) &&
377
- @tab_book.currentTab.filename.empty? &&
378
- !@tab_book.currentTab.modified)
379
- # Active Tab is an unmodified Untitled so just open the file in it
380
- @tab_book.currentTab.set_text_from_file(filename)
381
- @tab_book.currentTab.filename = filename
382
- @tab_book.setTabText(@tab_book.currentIndex, File.basename(filename))
383
- else
384
- create_tab(filename)
385
- end
386
-
387
- update_title()
388
- @procedure_dir = File.dirname(filename)
389
- @procedure_dir << '/' if @procedure_dir[-1..-1] != '/' and @procedure_dir[-1..-1] != '\\'
390
- end
391
- end
392
-
393
- # File->Reload
394
- def file_reload
395
- safe_to_continue = true
396
- if @tab_book.currentTab.modified
397
- case Qt::MessageBox.question(self, # parent
398
- 'Discard Changes?', # title
399
- 'Warning: Changes will be lost. Continue?', # text
400
- Qt::MessageBox::Yes | Qt::MessageBox::No, # buttons
401
- Qt::MessageBox::No) # default button
402
- when Qt::MessageBox::No
403
- safe_to_continue = false
404
- end
405
- end
406
-
407
- if safe_to_continue
408
- if active_script_runner_frame().filename.empty?
409
- active_script_runner_frame().set_text('')
410
- else
411
- active_script_runner_frame().set_text_from_file(active_script_runner_frame().filename)
412
- end
413
- @tab_book.currentTab.modified = false
414
- update_title()
415
- end
416
- end
417
-
418
- # File->Save and File->Save As
419
- def file_save(save_as = false)
420
- saved = false
421
- filename = active_script_runner_frame().filename
422
- if filename.empty?
423
- filename = Qt::FileDialog::getSaveFileName(self, # parent
424
- 'Save As...', # caption
425
- @procedure_dir + '/procedure.rb', # dir
426
- 'Procedure Files (*.rb)') # filter
427
- elsif save_as
428
- filename = Qt::FileDialog::getSaveFileName(self, # parent
429
- 'Save As...', # caption
430
- filename, # dir
431
- 'Procedure Files (*.rb)') # filter
432
- end
433
- if not filename.nil? and not filename.empty?
434
- begin
435
- @tab_book.currentTab.filename = filename
436
- @tab_book.currentTab.modified = false
437
- @tab_book.setTabText(@tab_book.currentIndex, File.basename(filename))
438
- active_script_runner_frame().filename = filename
439
- File.open(filename, "w") {|file| file.write(active_script_runner_frame().text)}
440
- saved = true
441
- update_title()
442
- statusBar.showMessage(tr("#{filename} saved"))
443
- @procedure_dir = File.dirname(filename)
444
- @procedure_dir << '/' if @procedure_dir[-1..-1] != '/' and @procedure_dir[-1..-1] != '\\'
445
- rescue => error
446
- statusBar.showMessage(tr("Error Saving Script : #{error.class} : #{error.message}"))
447
- end
448
- end
449
-
450
- return saved
451
- end
452
-
453
- # File->Close
454
- def file_close
455
- if prompt_for_save_if_needed('Save Current Script?')
456
- if @tab_book.count > 1
457
- close_active_tab()
458
- else
459
- active_script_runner_frame().stop_message_log
460
- @tab_book.setTabText(0, ' Untitled ')
461
- @tab_book.currentTab.clear
462
- end
463
- update_title()
464
- end
465
- end
466
-
467
- # File->Options
468
- def file_options
469
- dialog = Qt::Dialog.new(self)
470
- dialog.setWindowTitle('Script Runner Options')
471
- layout = Qt::VBoxLayout.new
472
-
473
- form = Qt::FormLayout.new
474
- box = Qt::DoubleSpinBox.new
475
- box.setRange(0, 60)
476
- box.setValue(ScriptRunnerFrame.line_delay)
477
- form.addRow(tr("&Delay between each script line:"), box)
478
- pause_on_error = Qt::CheckBox.new
479
- form.addRow(tr("&Pause on error:"), pause_on_error)
480
- monitor = Qt::CheckBox.new
481
- form.addRow(tr("&Monitor limits:"), monitor)
482
- if ScriptRunnerFrame.pause_on_error
483
- pause_on_error.setCheckState(Qt::Checked)
484
- else
485
- pause_on_error.setCheckState(Qt::Unchecked)
486
- end
487
- pause_on_red = Qt::CheckBox.new
488
- form.addRow(tr("Pause on &red limit:"), pause_on_red)
489
- if ScriptRunnerFrame.monitor_limits
490
- monitor.setCheckState(Qt::Checked)
491
- pause_on_red.setCheckState(Qt::Checked) if ScriptRunnerFrame.pause_on_red
492
- else
493
- pause_on_red.setEnabled(false)
494
- end
495
- monitor.connect(SIGNAL('stateChanged(int)')) do
496
- if monitor.isChecked()
497
- pause_on_red.setEnabled(true)
498
- else
499
- pause_on_red.setCheckState(Qt::Unchecked)
500
- pause_on_red.setEnabled(false)
501
- end
502
- end
503
- layout.addLayout(form)
504
-
505
- divider = Qt::Frame.new
506
- divider.setFrameStyle(Qt::Frame::HLine | Qt::Frame::Raised)
507
- divider.setLineWidth(1)
508
- layout.addWidget(divider)
509
-
510
- ok = Qt::PushButton.new('Ok')
511
- ok.setDefault(true)
512
- ok.connect(SIGNAL('clicked(bool)')) do
513
- ScriptRunnerFrame.line_delay = box.value
514
- ScriptRunnerFrame.pause_on_error = (pause_on_error.checkState == Qt::Checked)
515
- ScriptRunnerFrame.monitor_limits = (monitor.checkState == Qt::Checked)
516
- ScriptRunnerFrame.pause_on_red = (pause_on_red.checkState == Qt::Checked)
517
- dialog.accept
518
- end
519
- cancel = Qt::PushButton.new('Cancel')
520
- cancel.connect(SIGNAL('clicked(bool)')) { dialog.reject }
521
- button_layout = Qt::HBoxLayout.new
522
- button_layout.addWidget(ok)
523
- button_layout.addWidget(cancel)
524
- layout.addLayout(button_layout)
525
- dialog.setLayout(layout)
526
- dialog.exec
527
- dialog.dispose
528
- end
529
-
530
- ###########################################
531
- # Script Menu Options
532
- ###########################################
533
-
534
- include ScriptAudit
535
-
536
- # Script->View Instrumented
537
- def script_view_instrumented
538
- begin
539
- instrumented_script =
540
- ScriptRunnerFrame.instrument_script(active_script_runner_frame().text,
541
- active_script_runner_frame().filename,
542
- true)
543
- rescue StopScript
544
- return
545
- end
546
-
547
- # Show Dialog box containing script code
548
- box = Qt::Dialog.new(self)
549
- box.setWindowTitle('Instrumented Script')
550
- text = Qt::PlainTextEdit.new
551
- text.setWordWrapMode(Qt::TextOption::NoWrap)
552
- text.setReadOnly(true)
553
- text.setPlainText(instrumented_script)
554
- layout = Qt::VBoxLayout.new
555
- layout.addWidget(text)
556
- ok = Qt::PushButton.new('OK')
557
- ok.setDefault(true)
558
- ok.connect(SIGNAL('clicked(bool)')) { box.accept }
559
- button_layout = Qt::HBoxLayout.new
560
- button_layout.addStretch
561
- button_layout.addWidget(ok)
562
- button_layout.addStretch
563
- layout.addLayout(button_layout)
564
- box.setLayout(layout)
565
- box.setMinimumWidth([Qt::CoreApplication.instance.desktop.availableGeometry.width,
566
- text.document.size.width].min)
567
- screen_height = Qt::CoreApplication.instance.desktop.availableGeometry.height
568
- preferred_height = (text.document.size.height * text.fontMetrics.lineSpacing) +
569
- text.horizontalScrollBar.height + ok.sizeHint.height + (layout.spacing * 5)
570
- box.setMinimumHeight([screen_height, preferred_height].min)
571
- box.exec
572
- box.dispose
573
- end
574
-
575
- # Script->Log Message to Script Log
576
- def script_log_message
577
- message = get_scriptrunner_log_message()
578
- if message
579
- active_script_runner_frame().scriptrunner_puts 'User logged: ' + message.to_s
580
- active_script_runner_frame().handle_output_io
581
- end
582
- end
583
-
584
- # Script->Show Call Stack
585
- def script_call_stack
586
- trace = active_script_runner_frame().current_backtrace
587
- ScrollTextDialog.new(self, 'Call Stack', trace.join("\n"))
588
- end
589
-
590
- # Script->Toggle Debug
591
- def script_toggle_debug
592
- @debug = !@debug
593
- if @tab_book.count > 0
594
- (0..(@tab_book.count - 1)).each do |index|
595
- @tab_book.tab(index).toggle_debug(@debug)
596
- end
597
- end
598
- end
599
-
600
- # Script->Toggle Disconnect
601
- def script_toggle_disconnect
602
- @server_config_file = active_script_runner_frame().toggle_disconnect(@server_config_file)
603
- end
604
-
605
- ###########################################
606
- # Callbacks
607
- ###########################################
608
-
609
- def undo_available(bool)
610
- update_title()
611
- end
612
-
613
- def closeEvent(event)
614
- if active_script_runner_frame().prompt_if_running_on_close()
615
- if prompt_for_save_if_needed_on_close()
616
- shutdown_cmd_tlm()
617
- @tab_book.tabs.each_with_index do |tab, index|
618
- tab.stop_message_log
619
- end
620
- super(event)
621
- else
622
- event.ignore()
623
- end
624
- else
625
- event.ignore()
626
- end
627
- end
628
-
629
- # This method disables things that you shouldn't do while running
630
- def run_callback(script_runner_frame = nil)
631
- if script_runner_frame
632
- @tab_book.tabs.each_with_index do |tab, index|
633
- if tab != script_runner_frame
634
- @tab_book.setTabEnabled(index, false)
635
- else
636
- @tab_book.tabBar.setTabIcon(index, @running_icon)
637
- end
638
- end
639
- end
640
- disable_menu_items()
641
- end
642
-
643
- # This method reenables things after running
644
- def stop_callback(script_runner_frame = nil)
645
- if script_runner_frame
646
- @tab_book.tabs.each_with_index do |tab, index|
647
- @tab_book.setTabEnabled(index, true)
648
- @tab_book.tabBar.setTabIcon(index, @no_icon)
649
- end
650
- end
651
- enable_menu_items()
652
- end
653
-
654
- def enable_menu_items
655
- # Enable File Menu Items
656
- @file_new.setEnabled(true)
657
- @file_open.setEnabled(true)
658
- @file_close.setEnabled(true)
659
- @file_reload.setEnabled(true)
660
- @file_save.setEnabled(true)
661
- @file_save_as.setEnabled(true)
662
- @file_options.setEnabled(true)
663
-
664
- # Enable Edit Menu Items
665
- @edit_undo.setEnabled(true)
666
- @edit_redo.setEnabled(true)
667
- @edit_cut.setEnabled(true)
668
- @edit_copy.setEnabled(true)
669
- @edit_paste.setEnabled(true)
670
- @edit_select_all.setEnabled(true)
671
- @edit_comment.setEnabled(true)
672
-
673
- # Enable Script Menu Items
674
- @script_syntax_all.setEnabled(true)
675
- @script_syntax_lines.setEnabled(true)
676
- @script_mnemonic_all.setEnabled(true)
677
- @script_mnemonic_lines.setEnabled(true)
678
- @script_execute_lines.setEnabled(true)
679
- @script_execute_cursor.setEnabled(true)
680
-
681
- # Disable Script Runtime Items'
682
- @script_log_message.setEnabled(false)
683
- @script_call_stack.setEnabled(false)
684
- end
685
-
686
- def disable_menu_items
687
- # Disable File Menu Items
688
- @file_new.setEnabled(false)
689
- @file_open.setEnabled(false)
690
- @file_close.setEnabled(false)
691
- @file_reload.setEnabled(false)
692
- @file_save.setEnabled(false)
693
- @file_save_as.setEnabled(false)
694
- @file_options.setEnabled(false)
695
-
696
- # Disable Edit Menu Items
697
- @edit_undo.setEnabled(false)
698
- @edit_redo.setEnabled(false)
699
- @edit_cut.setEnabled(false)
700
- @edit_copy.setEnabled(false)
701
- @edit_paste.setEnabled(false)
702
- @edit_select_all.setEnabled(false)
703
- @edit_comment.setEnabled(false)
704
-
705
- # Disable Script Menu Items
706
- @script_syntax_all.setEnabled(false)
707
- @script_syntax_lines.setEnabled(false)
708
- @script_mnemonic_all.setEnabled(false)
709
- @script_mnemonic_lines.setEnabled(false)
710
- @script_execute_lines.setEnabled(false)
711
- @script_execute_cursor.setEnabled(false)
712
-
713
- # Enable Script Runtime Items
714
- @script_log_message.setEnabled(true)
715
- @script_call_stack.setEnabled(true)
716
- end
717
-
718
- # Handle the user changing tabs
719
- def handle_tab_change(index)
720
- update_title()
721
- end
722
-
723
- def handle_script_keypress(event)
724
- update_title()
725
- if event.matches(Qt::KeySequence::NextChild)
726
- index = @tab_book.currentIndex + 1
727
- index = 0 if index >= @tab_book.count
728
- @tab_book.setCurrentIndex(index)
729
- elsif event.matches(Qt::KeySequence::PreviousChild)
730
- index = @tab_book.currentIndex - 1
731
- index = @tab_book.count - 1 if index < 0
732
- @tab_book.setCurrentIndex(index)
733
- end
734
- end
735
-
736
- def context_menu(point)
737
- index = 0
738
- @tab_book.tabBar.count.times do
739
- break if @tab_book.tabBar.tabRect(index).contains(point)
740
- index += 1
741
- end
742
-
743
- return if (index == @tab_book.tabBar.count)
744
-
745
- # Bring the right clicked tab to the front
746
- @tab_book.setCurrentIndex(index)
747
-
748
- menu = Qt::Menu.new()
749
-
750
- new_action = Qt::Action.new(tr("&New"), self)
751
- new_action.statusTip = tr("Create a new script")
752
- new_action.connect(SIGNAL('triggered()')) { file_new() }
753
- menu.addAction(new_action)
754
-
755
- close_action = Qt::Action.new(tr("&Close"), self)
756
- close_action.statusTip = tr("Close the script")
757
- close_action.connect(SIGNAL('triggered()')) { file_close() }
758
- menu.addAction(close_action)
759
-
760
- save_action = Qt::Action.new(tr("&Save"), self)
761
- save_action.statusTip = tr("Save the script")
762
- save_action.connect(SIGNAL('triggered()')) { file_save(false) }
763
- menu.addAction(save_action)
764
-
765
- save_action = Qt::Action.new(tr("Save &As"), self)
766
- save_action.statusTip = tr("Save the script as")
767
- save_action.connect(SIGNAL('triggered()')) { file_save(true) }
768
- menu.addAction(save_action)
769
-
770
- menu.exec(@tab_book.mapToGlobal(point))
771
- menu.dispose
772
- end
773
-
774
- #############################################################
775
- # Helper Methods
776
- #############################################################
777
-
778
- # Called by cosmos_script_module by the user calling the status_bar scripting method
779
- def script_set_status(message)
780
- Qt.execute_in_main_thread(true) do
781
- # Check for self.disposed? to work around crash when using SimpleCov
782
- unless self.disposed?
783
- status_bar = statusBar()
784
- status_bar.showMessage(message)
785
- end
786
- end
787
- end
788
-
789
- # Updates the title appropriately to show the tabs filename and modified status
790
- def update_title
791
- if @tab_book.currentTab.filename.empty?
792
- self.setWindowTitle("Script Runner : Untitled")
793
- else
794
- self.setWindowTitle("Script Runner : #{@tab_book.currentTab.filename}")
795
- end
796
- self.setWindowTitle(self.windowTitle += '*') if @tab_book.currentTab.modified
797
- end
798
-
799
- # Returns the script runner frame of the active tab
800
- def active_script_runner_frame
801
- @tab_book.currentTab
802
- end
803
-
804
- # Creates a new tab
805
- def create_tab(filename = '')
806
- if filename.empty?
807
- tab_item_name = UNTITLED_TAB_TEXT
808
- else
809
- tab_item_name = ' ' + File.basename(filename) + ' '
810
- end
811
-
812
- script_runner_frame = ScriptRunnerFrame.new(self)
813
- script_runner_frame.toggle_debug(@debug)
814
- script_runner_frame.setContentsMargins(5,5,5,5)
815
- connect(script_runner_frame,
816
- SIGNAL('undoAvailable(bool)'),
817
- self,
818
- SLOT('undo_available(bool)'))
819
- script_runner_frame.run_callback = method(:run_callback)
820
- script_runner_frame.stop_callback = method(:stop_callback)
821
- script_runner_frame.set_text_from_file(filename) unless filename.empty?
822
- script_runner_frame.filename = filename
823
- # Register a keypress handler so we can Ctrl-Tab our way through the tabs
824
- script_runner_frame.key_press_callback = method(:handle_script_keypress)
825
- # Update the title if the frame changes so we can add/remove the asterix
826
- script_runner_frame.connect(SIGNAL('modificationChanged(bool)')) { update_title() }
827
-
828
- @tab_book.addTab(script_runner_frame, tab_item_name)
829
- @tab_book.setCurrentIndex(@tab_book.count-1) # index is 0 based
830
- # Set the focus on the input now that we've added the tab
831
- script_runner_frame.setFocus
832
- update_title()
833
- end
834
-
835
- # Closes the active tab
836
- def close_active_tab
837
- if @tab_book.count > 1
838
- active_script_runner_frame().stop_message_log
839
- tab_index = @tab_book.currentIndex
840
- @tab_book.removeTab(tab_index)
841
- if tab_index >= 1
842
- @tab_book.setCurrentIndex(tab_index - 1)
843
- else
844
- @tab_book.setCurrentIndex(0)
845
- end
846
- end
847
- end
848
-
849
- # Prompts for save if the current tab has been modified
850
- def prompt_for_save_if_needed(message = 'Save?')
851
- safe_to_continue = true
852
- if @tab_book.currentTab.modified
853
- case Qt::MessageBox.question(
854
- self, # parent
855
- 'Save?', # title
856
- message, # text
857
- Qt::MessageBox::Yes | Qt::MessageBox::No | Qt::MessageBox::Cancel, # buttons
858
- Qt::MessageBox::Cancel) # default button
859
- when Qt::MessageBox::Cancel
860
- safe_to_continue = false
861
- when Qt::MessageBox::Yes
862
- saved = file_save(false)
863
- if not saved
864
- safe_to_continue = false
865
- end
866
- end
867
- end
868
- return safe_to_continue
869
- end
870
-
871
- # Prompts the user that unsaved changes have been made before they close the app
872
- def prompt_for_save_if_needed_on_close
873
- safe_to_continue = true
874
- @tab_book.tabs.each_with_index do |tab, index|
875
- if tab.modified
876
- @tab_book.setCurrentIndex(index)
877
- if tab.filename.empty?
878
- message = "Save changes to 'Untitled'?"
879
- else
880
- message = "Save changes to '#{tab.filename}'?"
881
- end
882
- safe_to_continue = prompt_for_save_if_needed(message)
883
- #~ break unless safe_to_continue
884
- end
885
- end
886
- return safe_to_continue
887
- end
888
-
889
- def self.run(option_parser = nil, options = nil)
890
- Cosmos.catch_fatal_exception do
891
- unless option_parser and options
892
- option_parser, options = create_default_options()
893
- options.width = 750
894
- options.height = 600
895
- options.title = "Script Runner : Untitiled"
896
- options.auto_size = false
897
- options.config_file = "script_runner.txt"
898
- options.server_config_file = CmdTlmServer::DEFAULT_CONFIG_FILE
899
-
900
- option_parser.separator "Script Runner Specific Options:"
901
- option_parser.on("-c", "--config FILE", "Use the specified configuration file") do |arg|
902
- options.config_file = arg
903
- end
904
- option_parser.on("-s", "--server FILE", "Use the specified server configuration file for disconnect mode") do |arg|
905
- options.server_config_file = arg
906
- end
907
- end
908
-
909
- super(option_parser, options)
910
- end
911
- end
912
- end # class ScriptRunner
913
-
914
- end # module Cosmos
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+
11
+ require 'cosmos'
12
+ Cosmos.catch_fatal_exception do
13
+ require 'cosmos/gui/qt_tool'
14
+ require 'cosmos/tools/script_runner/script_runner_frame'
15
+ require 'cosmos/tools/script_runner/script_runner_config'
16
+ require 'cosmos/tools/script_runner/script_audit'
17
+ require 'cosmos/gui/dialogs/progress_dialog'
18
+ require 'cosmos/gui/dialogs/scroll_text_dialog'
19
+ end
20
+
21
+ module Cosmos
22
+
23
+ class ScriptRunner < QtTool
24
+ slots 'handle_tab_change(int)'
25
+ slots 'context_menu(const QPoint&)'
26
+ slots 'undo_available(bool)'
27
+
28
+ UNTITLED_TAB_TEXT = ' Untitled '
29
+
30
+ def initialize(options)
31
+ # All code before super is executed twice in RubyQt Based classes
32
+ super(options) # MUST BE FIRST
33
+ Cosmos.load_cosmos_icon("script_runner.png")
34
+ setAcceptDrops(true) # Allow dropping in files
35
+
36
+ @config_file = options.config_file
37
+ @server_config_file = options.server_config_file
38
+
39
+ # Add procedures to search path
40
+ System.paths['PROCEDURES'].each do |path|
41
+ Cosmos.add_to_search_path(path)
42
+ end
43
+
44
+ initialize_actions()
45
+ initialize_menus()
46
+ initialize_central_widget()
47
+ complete_initialize()
48
+
49
+ # Load icons
50
+ @running_icon = Cosmos.get_icon('running.png')
51
+ @no_icon = Qt::Icon.new
52
+
53
+ # Handle configuration
54
+ filename = File.join(::Cosmos::USERPATH, %w(config tools script_runner), @config_file)
55
+ if File.exist?(filename)
56
+ ScriptRunnerConfig.new(filename)
57
+ elsif @config_file != 'script_runner.txt'
58
+ raise "Could not find config file #{filename}"
59
+ end
60
+
61
+ @procedure_dir = System.paths['PROCEDURES'][0]
62
+ @debug = false
63
+
64
+ # Create the initial tab(s)
65
+ if ARGV.length == 0
66
+ create_tab()
67
+ else
68
+ ARGV.each {|argv_filename| create_tab(argv_filename)}
69
+ end
70
+ end
71
+
72
+ def initialize_actions
73
+ super()
74
+
75
+ # File actions
76
+ @file_new = Qt::Action.new(Cosmos.get_icon('file.png'), tr('&New'), self)
77
+ @file_new_keyseq = Qt::KeySequence.new(tr('Ctrl+N'))
78
+ @file_new.shortcut = @file_new_keyseq
79
+ @file_new.statusTip = tr('Start a new script')
80
+ @file_new.connect(SIGNAL('triggered()')) { file_new() }
81
+
82
+ @file_open = Qt::Action.new(Cosmos.get_icon('open.png'), tr('&Open'), self)
83
+ @file_open_keyseq = Qt::KeySequence.new(tr('Ctrl+O'))
84
+ @file_open.shortcut = @file_open_keyseq
85
+ @file_open.statusTip = tr('Open a script')
86
+ @file_open.connect(SIGNAL('triggered()')) { file_open() }
87
+
88
+ @file_close = Qt::Action.new(tr('&Close'), self)
89
+ @file_close_keyseq = Qt::KeySequence.new(tr('Ctrl+W'))
90
+ @file_close.shortcut = @file_close_keyseq
91
+ @file_close.statusTip = tr('Close the script')
92
+ @file_close.connect(SIGNAL('triggered()')) { file_close() }
93
+
94
+ @file_reload = Qt::Action.new(tr('&Reload'), self)
95
+ @file_reload_keyseq = Qt::KeySequence.new(tr('Ctrl+R'))
96
+ @file_reload.shortcut = @file_reload_keyseq
97
+ @file_reload.statusTip = tr('Reload a script')
98
+ @file_reload.connect(SIGNAL('triggered()')) { file_reload() }
99
+
100
+ @file_save = Qt::Action.new(Cosmos.get_icon('save.png'), tr('&Save'), self)
101
+ @file_save_keyseq = Qt::KeySequence.new(tr('Ctrl+S'))
102
+ @file_save.shortcut = @file_save_keyseq
103
+ @file_save.statusTip = tr('Save the script')
104
+ @file_save.connect(SIGNAL('triggered()')) { file_save(false) }
105
+
106
+ @file_save_as = Qt::Action.new(Cosmos.get_icon('save_as.png'), tr('Save &As'), self)
107
+ @file_save_as.statusTip = tr('Save the script')
108
+ @file_save_as.connect(SIGNAL('triggered()')) { file_save(true) }
109
+
110
+ @file_options = Qt::Action.new(tr('O&ptions'), self)
111
+ @file_options.statusTip = tr('Application Options')
112
+ @file_options.connect(SIGNAL('triggered()')) { file_options() }
113
+
114
+ # Edit actions
115
+ @edit_undo = Qt::Action.new(Cosmos.get_icon('undo.png'), tr('&Undo'), self)
116
+ @edit_undo_keyseq = Qt::KeySequence.new(tr('Ctrl+Z'))
117
+ @edit_undo.shortcut = @edit_undo_keyseq
118
+ @edit_undo.statusTip = tr('Undo')
119
+ @edit_undo.connect(SIGNAL('triggered()')) { active_script_runner_frame().undo }
120
+
121
+ @edit_redo = Qt::Action.new(Cosmos.get_icon('redo.png'), tr('&Redo'), self)
122
+ @edit_redo_keyseq = Qt::KeySequence.new(tr('Ctrl+Y'))
123
+ @edit_redo.shortcut = @edit_redo_keyseq
124
+ @edit_redo.statusTip = tr('Redo')
125
+ @edit_redo.connect(SIGNAL('triggered()')) { active_script_runner_frame().redo }
126
+
127
+ @edit_cut = Qt::Action.new(Cosmos.get_icon('cut.png'), tr('Cu&t'), self)
128
+ @edit_cut_keyseq = Qt::KeySequence.new(tr('Ctrl+X'))
129
+ @edit_cut.shortcut = @edit_cut_keyseq
130
+ @edit_cut.statusTip = tr('Cut')
131
+ @edit_cut.connect(SIGNAL('triggered()')) { active_script_runner_frame().cut }
132
+
133
+ @edit_copy = Qt::Action.new(Cosmos.get_icon('copy.png'), tr('&Copy'), self)
134
+ @edit_copy_keyseq = Qt::KeySequence.new(tr('Ctrl+C'))
135
+ @edit_copy.shortcut = @edit_copy_keyseq
136
+ @edit_copy.statusTip = tr('Copy')
137
+ @edit_copy.connect(SIGNAL('triggered()')) { active_script_runner_frame().copy }
138
+
139
+ @edit_paste = Qt::Action.new(tr('&Paste'), self)
140
+ @edit_paste_keyseq = Qt::KeySequence.new(tr('Ctrl+V'))
141
+ @edit_paste.shortcut = @edit_paste_keyseq
142
+ @edit_paste.statusTip = tr('Paste')
143
+ @edit_paste.connect(SIGNAL('triggered()')) { active_script_runner_frame().paste }
144
+
145
+ @edit_select_all = Qt::Action.new(tr('Select &All'), self)
146
+ @edit_select_all_keyseq = Qt::KeySequence.new(tr('Ctrl+A'))
147
+ @edit_select_all.shortcut = @edit_select_all_keyseq
148
+ @edit_select_all.statusTip = tr('Select All')
149
+ @edit_select_all.connect(SIGNAL('triggered()')) { active_script_runner_frame().select_all }
150
+
151
+ @edit_comment = Qt::Action.new(tr('Comment/Uncomment &Lines'), self)
152
+ @edit_comment_keyseq = Qt::KeySequence.new(tr('Ctrl+K'))
153
+ @edit_comment.shortcut = @edit_comment_keyseq
154
+ @edit_comment.statusTip = tr('Comment/Uncomment Lines')
155
+ @edit_comment.connect(SIGNAL('triggered()')) { active_script_runner_frame().comment_or_uncomment_lines }
156
+
157
+ # Search Actions
158
+ @search_find = Qt::Action.new(Cosmos.get_icon('search.png'), tr('&Find'), self)
159
+ @search_find_keyseq = Qt::KeySequence.new(tr('Ctrl+F'))
160
+ @search_find.shortcut = @search_find_keyseq
161
+ @search_find.statusTip = tr('Find text')
162
+ @search_find.connect(SIGNAL('triggered()')) { active_script_runner_frame.find() }
163
+
164
+ @search_find_next = Qt::Action.new(tr('Find &Next'), self)
165
+ @search_find_next_keyseq = Qt::KeySequence.new(tr('F3'))
166
+ @search_find_next.shortcut = @search_find_next_keyseq
167
+ @search_find_next.statusTip = tr('Find next instance')
168
+ @search_find_next.connect(SIGNAL('triggered()')) { active_script_runner_frame.find_next() }
169
+
170
+ @search_find_previous = Qt::Action.new(tr('Find &Previous'), self)
171
+ @search_find_previous_keyseq = Qt::KeySequence.new(tr('Shift+F3'))
172
+ @search_find_previous.shortcut = @search_find_previous_keyseq
173
+ @search_find_previous.statusTip = tr('Find previous instance')
174
+ @search_find_previous.connect(SIGNAL('triggered()')) { active_script_runner_frame.find_previous() }
175
+
176
+ @search_replace = Qt::Action.new(tr('&Replace'), self)
177
+ @search_replace_keyseq = Qt::KeySequence.new(tr('Ctrl+H'))
178
+ @search_replace.shortcut = @search_replace_keyseq
179
+ @search_replace.statusTip = tr('Replace')
180
+ @search_replace.connect(SIGNAL('triggered()')) { active_script_runner_frame.replace() }
181
+
182
+ # Script Actions
183
+ @script_syntax_all = Qt::Action.new(tr('&Ruby Syntax Check'), self)
184
+ @script_syntax_all.statusTip = tr('Check ruby syntax of this script')
185
+ @script_syntax_all.connect(SIGNAL('triggered()')) do
186
+ active_script_runner_frame().ruby_syntax_check_text(active_script_runner_frame().text)
187
+ end
188
+
189
+ @script_mnemonic_all = Qt::Action.new(tr('&Mnemonic Check'), self)
190
+ @script_mnemonic_all.statusTip = tr('Check mnemonics of this script')
191
+ @script_mnemonic_all.connect(SIGNAL('triggered()')) do
192
+ active_script_runner_frame().mnemonic_check_text(active_script_runner_frame().text)
193
+ end
194
+
195
+ @script_execute_lines = Qt::Action.new(tr('&Execute Selected Lines'), self)
196
+ @script_execute_lines.statusTip = tr('Execute selected lines')
197
+ @script_execute_lines.connect(SIGNAL('triggered()')) { active_script_runner_frame().run_selection }
198
+
199
+ @script_execute_cursor = Qt::Action.new(tr('E&xecute From Cursor'), self)
200
+ @script_execute_cursor.statusTip = tr('Execute from cursor position')
201
+ @script_execute_cursor.connect(SIGNAL('triggered()')) { active_script_runner_frame().run_from_cursor }
202
+
203
+ @script_syntax_lines = Qt::Action.new(tr('Ruby &Syntax Check Selected Lines'), self)
204
+ @script_syntax_lines.statusTip = tr('Check ruby syntax of selected lines')
205
+ @script_syntax_lines.connect(SIGNAL('triggered()')) { active_script_runner_frame().ruby_syntax_check_selection }
206
+
207
+ @script_mnemonic_lines = Qt::Action.new(tr('M&nemonic Check Selected Lines'), self)
208
+ @script_mnemonic_lines.statusTip = tr('Check mnemonics of selected lines')
209
+ @script_mnemonic_lines.connect(SIGNAL('triggered()')) { active_script_runner_frame().mnemonic_check_selection }
210
+
211
+ @script_audit = Qt::Action.new(tr('&Generate Cmd/Tlm Audit'), self)
212
+ @script_audit.statusTip = tr('Generate audit about commands sent and telemetry checked')
213
+ @script_audit.connect(SIGNAL('triggered()')) { script_audit() }
214
+
215
+ @script_instrumented = Qt::Action.new(tr('&View Instrumented Script'), self)
216
+ @script_instrumented.statusTip = tr('View instrumented script')
217
+ @script_instrumented.connect(SIGNAL('triggered()')) { script_view_instrumented() }
218
+
219
+ @script_log_message = Qt::Action.new(tr('Log Message to Script Log'), self)
220
+ @script_log_message.statusTip = tr('Log Message to Script Log')
221
+ @script_log_message.connect(SIGNAL('triggered()')) { script_log_message() }
222
+ @script_log_message.setEnabled(false)
223
+
224
+ @script_call_stack = Qt::Action.new(tr('Show Call Stack'), self)
225
+ @script_call_stack.statusTip = tr('Show Call Stack')
226
+ @script_call_stack.connect(SIGNAL('triggered()')) { script_call_stack() }
227
+ @script_call_stack.setEnabled(false)
228
+
229
+ @script_debug = Qt::Action.new(Cosmos.get_icon('bug.png'), tr('Toggle &Debug'), self)
230
+ @script_debug_keyseq = Qt::KeySequence.new(tr('Ctrl+D'))
231
+ @script_debug.shortcut = @script_debug_keyseq
232
+ @script_debug.statusTip = tr('Toggle debug capabilities for the script')
233
+ @script_debug.connect(SIGNAL('triggered()')) { script_toggle_debug() }
234
+
235
+ @script_disconnect = Qt::Action.new(Cosmos.get_icon('disconnected.png'), tr('&Toggle Disconnect'), self)
236
+ @script_disconnect_keyseq = Qt::KeySequence.new(tr('Ctrl+T'))
237
+ @script_disconnect.shortcut = @script_disconnect_keyseq
238
+ @script_disconnect.statusTip = tr('Toggle disconnect from the server')
239
+ @script_disconnect.connect(SIGNAL('triggered()')) { script_toggle_disconnect() }
240
+ end
241
+
242
+ def initialize_menus
243
+ # File Menu
244
+ file_menu = menuBar.addMenu(tr('&File'))
245
+ file_menu.addAction(@file_new)
246
+ file_menu.addAction(@file_open)
247
+ file_menu.addAction(@file_close)
248
+ file_menu.addAction(@file_reload)
249
+ file_menu.addSeparator()
250
+ file_menu.addAction(@file_save)
251
+ file_menu.addAction(@file_save_as)
252
+ file_menu.addSeparator()
253
+ file_menu.addAction(@file_options)
254
+ file_menu.addSeparator()
255
+ file_menu.addAction(@exit_action)
256
+
257
+ # Edit Menu
258
+ mode_menu = menuBar.addMenu(tr('&Edit'))
259
+ mode_menu.addAction(@edit_undo)
260
+ mode_menu.addAction(@edit_redo)
261
+ mode_menu.addSeparator()
262
+ mode_menu.addAction(@edit_cut)
263
+ mode_menu.addAction(@edit_copy)
264
+ mode_menu.addAction(@edit_paste)
265
+ mode_menu.addSeparator()
266
+ mode_menu.addAction(@edit_select_all)
267
+ mode_menu.addSeparator()
268
+ mode_menu.addAction(@edit_comment)
269
+
270
+ # Search Menu
271
+ view_menu = menuBar.addMenu(tr('&Search'))
272
+ view_menu.addAction(@search_find)
273
+ view_menu.addAction(@search_find_next)
274
+ view_menu.addAction(@search_find_previous)
275
+ view_menu.addAction(@search_replace)
276
+
277
+ # Script Menu
278
+ view_menu = menuBar.addMenu(tr('Scrip&t'))
279
+ view_menu.addAction(@script_syntax_all)
280
+ view_menu.addAction(@script_syntax_lines)
281
+ view_menu.addSeparator()
282
+ view_menu.addAction(@script_mnemonic_all)
283
+ view_menu.addAction(@script_mnemonic_lines)
284
+ view_menu.addSeparator()
285
+ view_menu.addAction(@script_execute_lines)
286
+ view_menu.addAction(@script_execute_cursor)
287
+ view_menu.addSeparator()
288
+ view_menu.addAction(@script_audit)
289
+ view_menu.addAction(@script_instrumented)
290
+ view_menu.addSeparator()
291
+ view_menu.addAction(@script_log_message)
292
+ view_menu.addAction(@script_call_stack)
293
+ view_menu.addAction(@script_debug)
294
+ view_menu.addAction(@script_disconnect)
295
+
296
+ # Help Menu
297
+ @about_string = "Script Runner allows the user to execute commands "\
298
+ "and take action on telemetry within a saveable script. "\
299
+ "It allows the full power of the Ruby programming language "\
300
+ "while defining several keywords to manipulate commands and telemetry in COSMOS.\n"
301
+
302
+ initialize_help_menu()
303
+ end
304
+
305
+ def initialize_central_widget
306
+ # Create the central widget
307
+ @tab_book = Qt::TabWidget.new
308
+ @tab_book.setMovable(true)
309
+ @tab_book.setContextMenuPolicy(Qt::CustomContextMenu)
310
+ connect(@tab_book,
311
+ SIGNAL('customContextMenuRequested(const QPoint&)'),
312
+ self,
313
+ SLOT('context_menu(const QPoint&)'))
314
+ connect(@tab_book,
315
+ SIGNAL('currentChanged(int)'),
316
+ self,
317
+ SLOT('handle_tab_change(int)'))
318
+ setCentralWidget(@tab_book)
319
+
320
+ # Display a blank message to force the statusBar to show
321
+ statusBar.showMessage("")
322
+ end
323
+
324
+ ###########################################
325
+ # Drag files into ScriptRunner support
326
+ ###########################################
327
+
328
+ def dragEnterEvent(event)
329
+ if event.mimeData.hasUrls
330
+ event.acceptProposedAction();
331
+ end
332
+ end
333
+
334
+ def dragMoveEvent(event)
335
+ if event.mimeData.hasUrls
336
+ event.acceptProposedAction();
337
+ end
338
+ end
339
+
340
+ def dropEvent(event)
341
+ event.mimeData.urls.each do |url|
342
+ filename = url.toLocalFile
343
+ extension = File.extname(filename).to_s.downcase
344
+ if extension == '.rb' or extension == '.txt'
345
+ file_open(filename)
346
+ end
347
+ end
348
+ end
349
+
350
+ ###########################################
351
+ # File Menu Options
352
+ ###########################################
353
+
354
+ # File->New
355
+ def file_new
356
+ create_tab()
357
+ end
358
+
359
+ # File->Open
360
+ def file_open(filename = nil)
361
+ if !filename
362
+ filename = Qt::FileDialog.getOpenFileName(self, "Select Script", @procedure_dir)
363
+ end
364
+ unless filename.nil? || filename.empty?
365
+ # If the user opens a file we already have open
366
+ # just set the current tab to that file and return
367
+ @tab_book.tabs.each_with_index do |tab, index|
368
+ if tab.filename == filename
369
+ @tab_book.setCurrentIndex(index)
370
+ @tab_book.currentTab.set_text_from_file(filename)
371
+ @tab_book.currentTab.filename = filename
372
+ return
373
+ end
374
+ end
375
+
376
+ if ((@tab_book.count == 1) &&
377
+ @tab_book.currentTab.filename.empty? &&
378
+ !@tab_book.currentTab.modified)
379
+ # Active Tab is an unmodified Untitled so just open the file in it
380
+ @tab_book.currentTab.set_text_from_file(filename)
381
+ @tab_book.currentTab.filename = filename
382
+ @tab_book.setTabText(@tab_book.currentIndex, File.basename(filename))
383
+ else
384
+ create_tab(filename)
385
+ end
386
+
387
+ update_title()
388
+ @procedure_dir = File.dirname(filename)
389
+ @procedure_dir << '/' if @procedure_dir[-1..-1] != '/' and @procedure_dir[-1..-1] != '\\'
390
+ end
391
+ end
392
+
393
+ # File->Reload
394
+ def file_reload
395
+ safe_to_continue = true
396
+ if @tab_book.currentTab.modified
397
+ case Qt::MessageBox.question(self, # parent
398
+ 'Discard Changes?', # title
399
+ 'Warning: Changes will be lost. Continue?', # text
400
+ Qt::MessageBox::Yes | Qt::MessageBox::No, # buttons
401
+ Qt::MessageBox::No) # default button
402
+ when Qt::MessageBox::No
403
+ safe_to_continue = false
404
+ end
405
+ end
406
+
407
+ if safe_to_continue
408
+ if active_script_runner_frame().filename.empty?
409
+ active_script_runner_frame().set_text('')
410
+ else
411
+ active_script_runner_frame().set_text_from_file(active_script_runner_frame().filename)
412
+ end
413
+ @tab_book.currentTab.modified = false
414
+ update_title()
415
+ end
416
+ end
417
+
418
+ # File->Save and File->Save As
419
+ def file_save(save_as = false)
420
+ saved = false
421
+ filename = active_script_runner_frame().filename
422
+ if filename.empty?
423
+ filename = Qt::FileDialog::getSaveFileName(self, # parent
424
+ 'Save As...', # caption
425
+ @procedure_dir + '/procedure.rb', # dir
426
+ 'Procedure Files (*.rb)') # filter
427
+ elsif save_as
428
+ filename = Qt::FileDialog::getSaveFileName(self, # parent
429
+ 'Save As...', # caption
430
+ filename, # dir
431
+ 'Procedure Files (*.rb)') # filter
432
+ end
433
+ if not filename.nil? and not filename.empty?
434
+ begin
435
+ @tab_book.currentTab.filename = filename
436
+ @tab_book.currentTab.modified = false
437
+ @tab_book.setTabText(@tab_book.currentIndex, File.basename(filename))
438
+ active_script_runner_frame().filename = filename
439
+ File.open(filename, "w") {|file| file.write(active_script_runner_frame().text)}
440
+ saved = true
441
+ update_title()
442
+ statusBar.showMessage(tr("#{filename} saved"))
443
+ @procedure_dir = File.dirname(filename)
444
+ @procedure_dir << '/' if @procedure_dir[-1..-1] != '/' and @procedure_dir[-1..-1] != '\\'
445
+ rescue => error
446
+ statusBar.showMessage(tr("Error Saving Script : #{error.class} : #{error.message}"))
447
+ end
448
+ end
449
+
450
+ return saved
451
+ end
452
+
453
+ # File->Close
454
+ def file_close
455
+ if prompt_for_save_if_needed('Save Current Script?')
456
+ if @tab_book.count > 1
457
+ close_active_tab()
458
+ else
459
+ active_script_runner_frame().stop_message_log
460
+ @tab_book.setTabText(0, ' Untitled ')
461
+ @tab_book.currentTab.clear
462
+ end
463
+ update_title()
464
+ end
465
+ end
466
+
467
+ # File->Options
468
+ def file_options
469
+ dialog = Qt::Dialog.new(self)
470
+ dialog.setWindowTitle('Script Runner Options')
471
+ layout = Qt::VBoxLayout.new
472
+
473
+ form = Qt::FormLayout.new
474
+ box = Qt::DoubleSpinBox.new
475
+ box.setRange(0, 60)
476
+ box.setValue(ScriptRunnerFrame.line_delay)
477
+ form.addRow(tr("&Delay between each script line:"), box)
478
+ pause_on_error = Qt::CheckBox.new
479
+ form.addRow(tr("&Pause on error:"), pause_on_error)
480
+ monitor = Qt::CheckBox.new
481
+ form.addRow(tr("&Monitor limits:"), monitor)
482
+ if ScriptRunnerFrame.pause_on_error
483
+ pause_on_error.setCheckState(Qt::Checked)
484
+ else
485
+ pause_on_error.setCheckState(Qt::Unchecked)
486
+ end
487
+ pause_on_red = Qt::CheckBox.new
488
+ form.addRow(tr("Pause on &red limit:"), pause_on_red)
489
+ if ScriptRunnerFrame.monitor_limits
490
+ monitor.setCheckState(Qt::Checked)
491
+ pause_on_red.setCheckState(Qt::Checked) if ScriptRunnerFrame.pause_on_red
492
+ else
493
+ pause_on_red.setEnabled(false)
494
+ end
495
+ monitor.connect(SIGNAL('stateChanged(int)')) do
496
+ if monitor.isChecked()
497
+ pause_on_red.setEnabled(true)
498
+ else
499
+ pause_on_red.setCheckState(Qt::Unchecked)
500
+ pause_on_red.setEnabled(false)
501
+ end
502
+ end
503
+ layout.addLayout(form)
504
+
505
+ divider = Qt::Frame.new
506
+ divider.setFrameStyle(Qt::Frame::HLine | Qt::Frame::Raised)
507
+ divider.setLineWidth(1)
508
+ layout.addWidget(divider)
509
+
510
+ ok = Qt::PushButton.new('Ok')
511
+ ok.setDefault(true)
512
+ ok.connect(SIGNAL('clicked(bool)')) do
513
+ ScriptRunnerFrame.line_delay = box.value
514
+ ScriptRunnerFrame.pause_on_error = (pause_on_error.checkState == Qt::Checked)
515
+ ScriptRunnerFrame.monitor_limits = (monitor.checkState == Qt::Checked)
516
+ ScriptRunnerFrame.pause_on_red = (pause_on_red.checkState == Qt::Checked)
517
+ dialog.accept
518
+ end
519
+ cancel = Qt::PushButton.new('Cancel')
520
+ cancel.connect(SIGNAL('clicked(bool)')) { dialog.reject }
521
+ button_layout = Qt::HBoxLayout.new
522
+ button_layout.addWidget(ok)
523
+ button_layout.addWidget(cancel)
524
+ layout.addLayout(button_layout)
525
+ dialog.setLayout(layout)
526
+ dialog.exec
527
+ dialog.dispose
528
+ end
529
+
530
+ ###########################################
531
+ # Script Menu Options
532
+ ###########################################
533
+
534
+ include ScriptAudit
535
+
536
+ # Script->View Instrumented
537
+ def script_view_instrumented
538
+ begin
539
+ instrumented_script =
540
+ ScriptRunnerFrame.instrument_script(active_script_runner_frame().text,
541
+ active_script_runner_frame().filename,
542
+ true)
543
+ rescue StopScript
544
+ return
545
+ end
546
+
547
+ # Show Dialog box containing script code
548
+ box = Qt::Dialog.new(self)
549
+ box.setWindowTitle('Instrumented Script')
550
+ text = Qt::PlainTextEdit.new
551
+ text.setWordWrapMode(Qt::TextOption::NoWrap)
552
+ text.setReadOnly(true)
553
+ text.setPlainText(instrumented_script)
554
+ layout = Qt::VBoxLayout.new
555
+ layout.addWidget(text)
556
+ ok = Qt::PushButton.new('OK')
557
+ ok.setDefault(true)
558
+ ok.connect(SIGNAL('clicked(bool)')) { box.accept }
559
+ button_layout = Qt::HBoxLayout.new
560
+ button_layout.addStretch
561
+ button_layout.addWidget(ok)
562
+ button_layout.addStretch
563
+ layout.addLayout(button_layout)
564
+ box.setLayout(layout)
565
+ box.setMinimumWidth([Qt::CoreApplication.instance.desktop.availableGeometry.width,
566
+ text.document.size.width].min)
567
+ screen_height = Qt::CoreApplication.instance.desktop.availableGeometry.height
568
+ preferred_height = (text.document.size.height * text.fontMetrics.lineSpacing) +
569
+ text.horizontalScrollBar.height + ok.sizeHint.height + (layout.spacing * 5)
570
+ box.setMinimumHeight([screen_height, preferred_height].min)
571
+ box.exec
572
+ box.dispose
573
+ end
574
+
575
+ # Script->Log Message to Script Log
576
+ def script_log_message
577
+ message = get_scriptrunner_log_message()
578
+ if message
579
+ active_script_runner_frame().scriptrunner_puts 'User logged: ' + message.to_s
580
+ active_script_runner_frame().handle_output_io
581
+ end
582
+ end
583
+
584
+ # Script->Show Call Stack
585
+ def script_call_stack
586
+ trace = active_script_runner_frame().current_backtrace
587
+ ScrollTextDialog.new(self, 'Call Stack', trace.join("\n"))
588
+ end
589
+
590
+ # Script->Toggle Debug
591
+ def script_toggle_debug
592
+ @debug = !@debug
593
+ if @tab_book.count > 0
594
+ (0..(@tab_book.count - 1)).each do |index|
595
+ @tab_book.tab(index).toggle_debug(@debug)
596
+ end
597
+ end
598
+ end
599
+
600
+ # Script->Toggle Disconnect
601
+ def script_toggle_disconnect
602
+ @server_config_file = active_script_runner_frame().toggle_disconnect(@server_config_file)
603
+ end
604
+
605
+ ###########################################
606
+ # Callbacks
607
+ ###########################################
608
+
609
+ def undo_available(bool)
610
+ update_title()
611
+ end
612
+
613
+ def closeEvent(event)
614
+ if active_script_runner_frame().prompt_if_running_on_close()
615
+ if prompt_for_save_if_needed_on_close()
616
+ shutdown_cmd_tlm()
617
+ @tab_book.tabs.each_with_index do |tab, index|
618
+ tab.stop_message_log
619
+ end
620
+ super(event)
621
+ else
622
+ event.ignore()
623
+ end
624
+ else
625
+ event.ignore()
626
+ end
627
+ end
628
+
629
+ # This method disables things that you shouldn't do while running
630
+ def run_callback(script_runner_frame = nil)
631
+ if script_runner_frame
632
+ @tab_book.tabs.each_with_index do |tab, index|
633
+ if tab != script_runner_frame
634
+ @tab_book.setTabEnabled(index, false)
635
+ else
636
+ @tab_book.tabBar.setTabIcon(index, @running_icon)
637
+ end
638
+ end
639
+ end
640
+ disable_menu_items()
641
+ end
642
+
643
+ # This method reenables things after running
644
+ def stop_callback(script_runner_frame = nil)
645
+ if script_runner_frame
646
+ @tab_book.tabs.each_with_index do |tab, index|
647
+ @tab_book.setTabEnabled(index, true)
648
+ @tab_book.tabBar.setTabIcon(index, @no_icon)
649
+ end
650
+ end
651
+ enable_menu_items()
652
+ end
653
+
654
+ def enable_menu_items
655
+ # Enable File Menu Items
656
+ @file_new.setEnabled(true)
657
+ @file_open.setEnabled(true)
658
+ @file_close.setEnabled(true)
659
+ @file_reload.setEnabled(true)
660
+ @file_save.setEnabled(true)
661
+ @file_save_as.setEnabled(true)
662
+ @file_options.setEnabled(true)
663
+
664
+ # Enable Edit Menu Items
665
+ @edit_undo.setEnabled(true)
666
+ @edit_redo.setEnabled(true)
667
+ @edit_cut.setEnabled(true)
668
+ @edit_copy.setEnabled(true)
669
+ @edit_paste.setEnabled(true)
670
+ @edit_select_all.setEnabled(true)
671
+ @edit_comment.setEnabled(true)
672
+
673
+ # Enable Script Menu Items
674
+ @script_syntax_all.setEnabled(true)
675
+ @script_syntax_lines.setEnabled(true)
676
+ @script_mnemonic_all.setEnabled(true)
677
+ @script_mnemonic_lines.setEnabled(true)
678
+ @script_execute_lines.setEnabled(true)
679
+ @script_execute_cursor.setEnabled(true)
680
+
681
+ # Disable Script Runtime Items'
682
+ @script_log_message.setEnabled(false)
683
+ @script_call_stack.setEnabled(false)
684
+ end
685
+
686
+ def disable_menu_items
687
+ # Disable File Menu Items
688
+ @file_new.setEnabled(false)
689
+ @file_open.setEnabled(false)
690
+ @file_close.setEnabled(false)
691
+ @file_reload.setEnabled(false)
692
+ @file_save.setEnabled(false)
693
+ @file_save_as.setEnabled(false)
694
+ @file_options.setEnabled(false)
695
+
696
+ # Disable Edit Menu Items
697
+ @edit_undo.setEnabled(false)
698
+ @edit_redo.setEnabled(false)
699
+ @edit_cut.setEnabled(false)
700
+ @edit_copy.setEnabled(false)
701
+ @edit_paste.setEnabled(false)
702
+ @edit_select_all.setEnabled(false)
703
+ @edit_comment.setEnabled(false)
704
+
705
+ # Disable Script Menu Items
706
+ @script_syntax_all.setEnabled(false)
707
+ @script_syntax_lines.setEnabled(false)
708
+ @script_mnemonic_all.setEnabled(false)
709
+ @script_mnemonic_lines.setEnabled(false)
710
+ @script_execute_lines.setEnabled(false)
711
+ @script_execute_cursor.setEnabled(false)
712
+
713
+ # Enable Script Runtime Items
714
+ @script_log_message.setEnabled(true)
715
+ @script_call_stack.setEnabled(true)
716
+ end
717
+
718
+ # Handle the user changing tabs
719
+ def handle_tab_change(index)
720
+ update_title()
721
+ end
722
+
723
+ def handle_script_keypress(event)
724
+ update_title()
725
+ if event.matches(Qt::KeySequence::NextChild)
726
+ index = @tab_book.currentIndex + 1
727
+ index = 0 if index >= @tab_book.count
728
+ @tab_book.setCurrentIndex(index)
729
+ elsif event.matches(Qt::KeySequence::PreviousChild)
730
+ index = @tab_book.currentIndex - 1
731
+ index = @tab_book.count - 1 if index < 0
732
+ @tab_book.setCurrentIndex(index)
733
+ end
734
+ end
735
+
736
+ def context_menu(point)
737
+ index = 0
738
+ @tab_book.tabBar.count.times do
739
+ break if @tab_book.tabBar.tabRect(index).contains(point)
740
+ index += 1
741
+ end
742
+
743
+ return if (index == @tab_book.tabBar.count)
744
+
745
+ # Bring the right clicked tab to the front
746
+ @tab_book.setCurrentIndex(index)
747
+
748
+ menu = Qt::Menu.new()
749
+
750
+ new_action = Qt::Action.new(tr("&New"), self)
751
+ new_action.statusTip = tr("Create a new script")
752
+ new_action.connect(SIGNAL('triggered()')) { file_new() }
753
+ menu.addAction(new_action)
754
+
755
+ close_action = Qt::Action.new(tr("&Close"), self)
756
+ close_action.statusTip = tr("Close the script")
757
+ close_action.connect(SIGNAL('triggered()')) { file_close() }
758
+ menu.addAction(close_action)
759
+
760
+ save_action = Qt::Action.new(tr("&Save"), self)
761
+ save_action.statusTip = tr("Save the script")
762
+ save_action.connect(SIGNAL('triggered()')) { file_save(false) }
763
+ menu.addAction(save_action)
764
+
765
+ save_action = Qt::Action.new(tr("Save &As"), self)
766
+ save_action.statusTip = tr("Save the script as")
767
+ save_action.connect(SIGNAL('triggered()')) { file_save(true) }
768
+ menu.addAction(save_action)
769
+
770
+ menu.exec(@tab_book.mapToGlobal(point))
771
+ menu.dispose
772
+ end
773
+
774
+ #############################################################
775
+ # Helper Methods
776
+ #############################################################
777
+
778
+ # Called by cosmos_script_module by the user calling the status_bar scripting method
779
+ def script_set_status(message)
780
+ Qt.execute_in_main_thread(true) do
781
+ # Check for self.disposed? to work around crash when using SimpleCov
782
+ unless self.disposed?
783
+ status_bar = statusBar()
784
+ status_bar.showMessage(message)
785
+ end
786
+ end
787
+ end
788
+
789
+ # Updates the title appropriately to show the tabs filename and modified status
790
+ def update_title
791
+ if @tab_book.currentTab.filename.empty?
792
+ self.setWindowTitle("Script Runner : Untitled")
793
+ else
794
+ self.setWindowTitle("Script Runner : #{@tab_book.currentTab.filename}")
795
+ end
796
+ self.setWindowTitle(self.windowTitle += '*') if @tab_book.currentTab.modified
797
+ end
798
+
799
+ # Returns the script runner frame of the active tab
800
+ def active_script_runner_frame
801
+ @tab_book.currentTab
802
+ end
803
+
804
+ # Creates a new tab
805
+ def create_tab(filename = '')
806
+ if filename.empty?
807
+ tab_item_name = UNTITLED_TAB_TEXT
808
+ else
809
+ tab_item_name = ' ' + File.basename(filename) + ' '
810
+ end
811
+
812
+ script_runner_frame = ScriptRunnerFrame.new(self)
813
+ script_runner_frame.toggle_debug(@debug)
814
+ script_runner_frame.setContentsMargins(5,5,5,5)
815
+ connect(script_runner_frame,
816
+ SIGNAL('undoAvailable(bool)'),
817
+ self,
818
+ SLOT('undo_available(bool)'))
819
+ script_runner_frame.run_callback = method(:run_callback)
820
+ script_runner_frame.stop_callback = method(:stop_callback)
821
+ script_runner_frame.set_text_from_file(filename) unless filename.empty?
822
+ script_runner_frame.filename = filename
823
+ # Register a keypress handler so we can Ctrl-Tab our way through the tabs
824
+ script_runner_frame.key_press_callback = method(:handle_script_keypress)
825
+ # Update the title if the frame changes so we can add/remove the asterix
826
+ script_runner_frame.connect(SIGNAL('modificationChanged(bool)')) { update_title() }
827
+
828
+ @tab_book.addTab(script_runner_frame, tab_item_name)
829
+ @tab_book.setCurrentIndex(@tab_book.count-1) # index is 0 based
830
+ # Set the focus on the input now that we've added the tab
831
+ script_runner_frame.setFocus
832
+ update_title()
833
+ end
834
+
835
+ # Closes the active tab
836
+ def close_active_tab
837
+ if @tab_book.count > 1
838
+ active_script_runner_frame().stop_message_log
839
+ tab_index = @tab_book.currentIndex
840
+ @tab_book.removeTab(tab_index)
841
+ if tab_index >= 1
842
+ @tab_book.setCurrentIndex(tab_index - 1)
843
+ else
844
+ @tab_book.setCurrentIndex(0)
845
+ end
846
+ end
847
+ end
848
+
849
+ # Prompts for save if the current tab has been modified
850
+ def prompt_for_save_if_needed(message = 'Save?')
851
+ safe_to_continue = true
852
+ if @tab_book.currentTab.modified
853
+ case Qt::MessageBox.question(
854
+ self, # parent
855
+ 'Save?', # title
856
+ message, # text
857
+ Qt::MessageBox::Yes | Qt::MessageBox::No | Qt::MessageBox::Cancel, # buttons
858
+ Qt::MessageBox::Cancel) # default button
859
+ when Qt::MessageBox::Cancel
860
+ safe_to_continue = false
861
+ when Qt::MessageBox::Yes
862
+ saved = file_save(false)
863
+ if not saved
864
+ safe_to_continue = false
865
+ end
866
+ end
867
+ end
868
+ return safe_to_continue
869
+ end
870
+
871
+ # Prompts the user that unsaved changes have been made before they close the app
872
+ def prompt_for_save_if_needed_on_close
873
+ safe_to_continue = true
874
+ @tab_book.tabs.each_with_index do |tab, index|
875
+ if tab.modified
876
+ @tab_book.setCurrentIndex(index)
877
+ if tab.filename.empty?
878
+ message = "Save changes to 'Untitled'?"
879
+ else
880
+ message = "Save changes to '#{tab.filename}'?"
881
+ end
882
+ safe_to_continue = prompt_for_save_if_needed(message)
883
+ #~ break unless safe_to_continue
884
+ end
885
+ end
886
+ return safe_to_continue
887
+ end
888
+
889
+ def self.run(option_parser = nil, options = nil)
890
+ Cosmos.catch_fatal_exception do
891
+ unless option_parser and options
892
+ option_parser, options = create_default_options()
893
+ options.width = 750
894
+ options.height = 600
895
+ options.title = "Script Runner : Untitiled"
896
+ options.auto_size = false
897
+ options.config_file = "script_runner.txt"
898
+ options.server_config_file = CmdTlmServer::DEFAULT_CONFIG_FILE
899
+
900
+ option_parser.separator "Script Runner Specific Options:"
901
+ option_parser.on("-c", "--config FILE", "Use the specified configuration file") do |arg|
902
+ options.config_file = arg
903
+ end
904
+ option_parser.on("-s", "--server FILE", "Use the specified server configuration file for disconnect mode") do |arg|
905
+ options.server_config_file = arg
906
+ end
907
+ end
908
+
909
+ super(option_parser, options)
910
+ end
911
+ end
912
+ end # class ScriptRunner
913
+
914
+ end # module Cosmos