cosmos 4.0.3-java → 4.1.0-java

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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -5
  3. data/Manifest.txt +11 -1
  4. data/README.md +3 -2
  5. data/Rakefile +18 -4
  6. data/appveyor.yml +19 -0
  7. data/cosmos.gemspec +12 -3
  8. data/data/config/cmd_tlm_server.yaml +3 -0
  9. data/data/crc.txt +63 -60
  10. data/demo/config/targets/INST/cmd_tlm_server.txt +1 -0
  11. data/demo/config/targets/INST/cmd_tlm_server2.txt +7 -0
  12. data/demo/config/tools/cmd_sequence/cmd_sequence.txt +2 -0
  13. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +8 -12
  14. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +7 -9
  15. data/demo/lib/cmd_sequence_exporter.rb +52 -0
  16. data/demo/lib/example_background_task.rb +1 -0
  17. data/demo/procedures/replay_test.rb +32 -0
  18. data/ext/cosmos/ext/structure/structure.c +39 -3
  19. data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +1 -0
  20. data/install/config/tools/launcher/launcher.txt +2 -0
  21. data/lib/cosmos/config/config_parser.rb +2 -0
  22. data/lib/cosmos/core_ext/io.rb +89 -60
  23. data/lib/cosmos/gui/qt.rb +5 -8
  24. data/lib/cosmos/gui/qt_tool.rb +8 -8
  25. data/lib/cosmos/gui/text/ruby_editor.rb +12 -12
  26. data/lib/cosmos/gui/utilities/script_module_gui.rb +9 -9
  27. data/lib/cosmos/gui/widgets/realtime_button_bar.rb +18 -17
  28. data/lib/cosmos/interfaces/protocols/fixed_protocol.rb +2 -2
  29. data/lib/cosmos/interfaces/protocols/template_protocol.rb +3 -0
  30. data/lib/cosmos/interfaces/udp_interface.rb +27 -14
  31. data/lib/cosmos/io/buffered_file.rb +0 -1
  32. data/lib/cosmos/io/json_drb.rb +134 -214
  33. data/lib/cosmos/io/json_drb_object.rb +22 -61
  34. data/lib/cosmos/io/json_drb_rack.rb +79 -0
  35. data/lib/cosmos/io/json_rpc.rb +27 -0
  36. data/lib/cosmos/io/udp_sockets.rb +102 -58
  37. data/lib/cosmos/packets/commands.rb +1 -1
  38. data/lib/cosmos/packets/structure.rb +1 -1
  39. data/lib/cosmos/packets/structure_item.rb +37 -5
  40. data/lib/cosmos/script/cmd_tlm_server.rb +76 -2
  41. data/lib/cosmos/script/replay.rb +60 -0
  42. data/lib/cosmos/script/script.rb +20 -2
  43. data/lib/cosmos/script/scripting.rb +9 -9
  44. data/lib/cosmos/script/tools.rb +14 -0
  45. data/lib/cosmos/system/system.rb +185 -92
  46. data/lib/cosmos/system/target.rb +1 -1
  47. data/lib/cosmos/tools/cmd_sequence/cmd_sequence.rb +44 -4
  48. data/lib/cosmos/tools/cmd_sequence/sequence_item.rb +4 -0
  49. data/lib/cosmos/tools/cmd_sequence/sequence_list.rb +7 -0
  50. data/lib/cosmos/tools/cmd_tlm_server/api.rb +347 -20
  51. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +3 -0
  52. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +329 -111
  53. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +13 -0
  54. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +261 -95
  55. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +46 -35
  56. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +18 -8
  57. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +39 -28
  58. data/lib/cosmos/tools/cmd_tlm_server/gui/replay_tab.rb +242 -0
  59. data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +24 -8
  60. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +18 -6
  61. data/lib/cosmos/tools/cmd_tlm_server/limits_groups_background_task.rb +5 -4
  62. data/lib/cosmos/tools/cmd_tlm_server/replay_backend.rb +375 -0
  63. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +10 -2
  64. data/lib/cosmos/tools/data_viewer/data_viewer.rb +40 -5
  65. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +18 -20
  66. data/lib/cosmos/tools/launcher/launcher_config.rb +5 -16
  67. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +65 -39
  68. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +19 -0
  69. data/lib/cosmos/tools/replay/replay.rb +5 -505
  70. data/lib/cosmos/tools/script_runner/script_audit.rb +1 -0
  71. data/lib/cosmos/tools/script_runner/script_runner.rb +3 -4
  72. data/lib/cosmos/tools/script_runner/script_runner_config.rb +3 -4
  73. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +44 -23
  74. data/lib/cosmos/tools/test_runner/results_writer.rb +4 -0
  75. data/lib/cosmos/tools/test_runner/test_runner.rb +0 -3
  76. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +6 -2
  77. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +26 -1
  78. data/lib/cosmos/tools/tlm_viewer/screen.rb +24 -1
  79. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +25 -0
  80. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +24 -14
  81. data/lib/cosmos/top_level.rb +34 -24
  82. data/lib/cosmos/utilities/csv.rb +60 -8
  83. data/lib/cosmos/version.rb +5 -5
  84. data/spec/config/config_parser_spec.rb +10 -1
  85. data/spec/core_ext/socket_spec.rb +4 -2
  86. data/spec/gui/utilities/script_module_gui_spec.rb +102 -0
  87. data/spec/install/config/data/data.txt +1 -0
  88. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +2 -0
  89. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +1 -2
  90. data/spec/interfaces/protocols/template_protocol_spec.rb +72 -2
  91. data/spec/interfaces/serial_interface_spec.rb +1 -1
  92. data/spec/interfaces/udp_interface_spec.rb +14 -0
  93. data/spec/io/buffered_file_spec.rb +37 -0
  94. data/spec/io/json_drb_object_spec.rb +2 -15
  95. data/spec/io/json_drb_spec.rb +61 -121
  96. data/spec/io/udp_sockets_spec.rb +42 -2
  97. data/spec/packet_logs/packet_log_reader_spec.rb +5 -2
  98. data/spec/packets/binary_accessor_spec.rb +1 -1
  99. data/spec/packets/packet_item_spec.rb +1 -1
  100. data/spec/packets/structure_item_spec.rb +5 -6
  101. data/spec/script/cmd_tlm_server_spec.rb +39 -4
  102. data/spec/script/commands_disconnect_spec.rb +1 -1
  103. data/spec/script/commands_spec.rb +2 -1
  104. data/spec/script/scripting_spec.rb +18 -3
  105. data/spec/script/telemetry_spec.rb +5 -0
  106. data/spec/spec_helper.rb +43 -26
  107. data/spec/streams/tcpip_socket_stream_spec.rb +2 -2
  108. data/spec/system/system_spec.rb +11 -9
  109. data/spec/system/target_spec.rb +3 -0
  110. data/spec/tools/cmd_tlm_server/api_spec.rb +543 -29
  111. data/spec/tools/cmd_tlm_server/background_task_spec.rb +2 -2
  112. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +31 -75
  113. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +199 -66
  114. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +85 -9
  115. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +29 -127
  116. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +10 -50
  117. data/spec/tools/launcher/launcher_config_spec.rb +1 -1
  118. data/spec/tools/table_manager/table_item_spec.rb +1 -1
  119. data/spec/tools/table_manager/tablemanager_core_spec.rb +4 -4
  120. data/spec/top_level/top_level_spec.rb +151 -3
  121. data/spec/utilities/csv_spec.rb +24 -5
  122. metadata +61 -9
  123. data/lib/cosmos/tools/replay/replay_server.rb +0 -91
@@ -131,6 +131,7 @@ module Cosmos
131
131
  file.puts "#{tlm},#{total}"
132
132
  end
133
133
  end
134
+ File.chmod(0444, output_filename)
134
135
  end
135
136
  rescue => error
136
137
  progress.append_text("Error processing:\n#{error.formatted}\n")
@@ -49,10 +49,10 @@ module Cosmos
49
49
  @running_icon = Cosmos.get_icon('running.png')
50
50
  @no_icon = Qt::Icon.new
51
51
 
52
- if File.exist?(options.config_file)
52
+ begin
53
53
  ScriptRunnerConfig.new(options.config_file)
54
- else
55
- raise "Could not find config file #{options.config_file}"
54
+ rescue => error
55
+ ExceptionDialog.new(self, error, "Error parsing #{options.config_file}")
56
56
  end
57
57
 
58
58
  @procedure_dir = System.paths['PROCEDURES'][0]
@@ -955,7 +955,6 @@ module Cosmos
955
955
  options.height = 600
956
956
  options.title = "Script Runner : Untitled"
957
957
  options.auto_size = false
958
- options.config_file = "script_runner.txt"
959
958
  options.server_config_file = CmdTlmServer::DEFAULT_CONFIG_FILE
960
959
  options.run_procedure = nil
961
960
 
@@ -11,11 +11,11 @@
11
11
  require 'cosmos'
12
12
 
13
13
  module Cosmos
14
-
15
14
  # This class reads the Script Runner configuration file
16
15
  class ScriptRunnerConfig
17
16
  # Processes the config file
18
17
  def initialize(filename)
18
+ return unless filename
19
19
  parser = ConfigParser.new("http://cosmosrb.com/docs/tools/#script-runner-configuration")
20
20
  parser.parse_file(filename) do |keyword, params|
21
21
  case keyword
@@ -35,6 +35,5 @@ module Cosmos
35
35
  end
36
36
  end
37
37
  end
38
- end # class ScriptRunnerConfig
39
-
40
- end # module Cosmos
38
+ end
39
+ end
@@ -140,6 +140,7 @@ module Cosmos
140
140
  # Add Realtime Button Bar
141
141
  @realtime_button_bar = RealtimeButtonBar.new(self)
142
142
  @realtime_button_bar.state = 'Stopped'
143
+ @realtime_button_bar.step_callback = method(:handle_step_button)
143
144
  @realtime_button_bar.start_callback = method(:handle_start_go_button)
144
145
  @realtime_button_bar.pause_callback = method(:handle_pause_retry_button)
145
146
  @realtime_button_bar.stop_callback = method(:handle_stop_button)
@@ -549,13 +550,20 @@ module Cosmos
549
550
  return nil if @cancel_instrumentation
550
551
  instrumented_line = ''
551
552
  if instrumentable
553
+ # Skip the segment if it's empty. Note that the segment could have
554
+ # originally had comments but they were stripped in
555
+ # ruby_lex_utils.remove_comments
556
+ next if segment.strip.empty?
552
557
  # If not inside a begin block then create one to catch exceptions
553
558
  unless inside_begin
554
559
  instrumented_line << 'begin; '
555
560
  end
556
561
 
557
562
  # Add preline instrumentation
558
- instrumented_line << "ScriptRunnerFrame.instance.script_binding = binding(); if ScriptRunnerFrame.instance.inline_return then ScriptRunnerFrame.instance.inline_return = nil; return ScriptRunnerFrame.instance.inline_return_params; end; ScriptRunnerFrame.instance.pre_line_instrumentation('#{filename}', #{line_no}); "
563
+ instrumented_line << "ScriptRunnerFrame.instance.script_binding = binding(); "\
564
+ "if ScriptRunnerFrame.instance.inline_return then ScriptRunnerFrame.instance.inline_return = nil; "\
565
+ "return ScriptRunnerFrame.instance.inline_return_params; end; "\
566
+ "ScriptRunnerFrame.instance.pre_line_instrumentation('#{filename}', #{line_no}); "
559
567
 
560
568
  # Add the actual line
561
569
  instrumented_line << segment
@@ -566,7 +574,8 @@ module Cosmos
566
574
 
567
575
  # Complete begin block to catch exceptions
568
576
  unless inside_begin
569
- instrumented_line << "; rescue Exception => eval_error; retry if ScriptRunnerFrame.instance.exception_instrumentation(eval_error, '#{filename}', #{line_no}); end"
577
+ instrumented_line << "; rescue Exception => eval_error; "\
578
+ "retry if ScriptRunnerFrame.instance.exception_instrumentation(eval_error, '#{filename}', #{line_no}); end"
570
579
  end
571
580
 
572
581
  instrumented_line << "\n"
@@ -682,7 +691,16 @@ module Cosmos
682
691
  # Implement the breakpoint callbacks from the RubyEditor
683
692
  ######################################
684
693
  def breakpoint_set(line)
685
- ScriptRunnerFrame.set_breakpoint(current_tab_filename(), line)
694
+ # Check for blank and comment lines which can't have a breakpoint.
695
+ # There are other un-instrumentable lines which don't support breakpoints
696
+ # but this is the most common and is an easy check.
697
+ # Note: line is 1 based but @script.get_line is zero based so subtract 1
698
+ text = @script.get_line(line - 1)
699
+ if text.strip.empty? || text.strip[0] == '#'
700
+ @script.clear_breakpoint(line) # Immediately clear it
701
+ else
702
+ ScriptRunnerFrame.set_breakpoint(current_tab_filename(), line)
703
+ end
686
704
  end
687
705
 
688
706
  def breakpoint_cleared(line)
@@ -874,6 +892,7 @@ module Cosmos
874
892
 
875
893
  def show_debug
876
894
  unless @debug_frame
895
+ @realtime_button_bar.step_button.setHidden(false)
877
896
  @script.enable_breakpoints = true
878
897
  if @tab_book_shown
879
898
  if @tab_book.count > 0
@@ -946,20 +965,6 @@ module Cosmos
946
965
 
947
966
  @debug_frame.addWidget(@debug_text)
948
967
 
949
- @toggle_button = Qt::PushButton.new('Toggle Run/Step')
950
- @debug_frame.addWidget(@toggle_button)
951
- @toggle_button.connect(SIGNAL('clicked(bool)')) do
952
- if @@step_mode
953
- scriptrunner_puts "Debug: run_mode"
954
- handle_output_io()
955
- self.class.step_mode = false
956
- else
957
- scriptrunner_puts "Debug: step_mode"
958
- handle_output_io()
959
- self.class.step_mode = true
960
- end
961
- end
962
-
963
968
  @return_button = Qt::PushButton.new('Insert Return')
964
969
  @debug_frame.addWidget(@return_button)
965
970
  @return_button.connect(SIGNAL('clicked(bool)')) do
@@ -985,11 +990,19 @@ module Cosmos
985
990
  end
986
991
  end
987
992
  end
993
+ @realtime_button_bar.step_button.setHidden(true)
988
994
  # Remove the debug frame
989
995
  @bottom_frame.layout.takeAt(@bottom_frame.layout.count - 1) if @debug_frame
990
996
  @debug_frame.removeAll
991
997
  @debug_frame.dispose
992
998
  @debug_frame = nil
999
+
1000
+ # If step mode was previously active then pause the script so it doesn't
1001
+ # just take off when we end the debugging session
1002
+ if @@step_mode
1003
+ pause()
1004
+ @@step_mode = false
1005
+ end
993
1006
  end
994
1007
 
995
1008
  def self.set_breakpoint(filename, line_number)
@@ -1442,8 +1455,18 @@ module Cosmos
1442
1455
  true
1443
1456
  end
1444
1457
 
1445
- def handle_start_go_button
1446
- scriptrunner_puts "User pressed #{@realtime_button_bar.start_button.text.strip}"
1458
+ def handle_step_button
1459
+ scriptrunner_puts "User pressed #{@realtime_button_bar.step_button.text.strip}"
1460
+ pause()
1461
+ @@step_mode = true
1462
+ handle_start_go_button(step = true)
1463
+ end
1464
+
1465
+ def handle_start_go_button(step = false)
1466
+ unless step
1467
+ scriptrunner_puts "User pressed #{@realtime_button_bar.start_button.text.strip}"
1468
+ @@step_mode = false
1469
+ end
1447
1470
  handle_output_io()
1448
1471
  @realtime_button_bar.start_button.clear_focus()
1449
1472
 
@@ -1832,7 +1855,5 @@ module Cosmos
1832
1855
  # Oh Well
1833
1856
  end
1834
1857
  end
1835
-
1836
- end # class ScriptRunnerFrame
1837
-
1838
- end # module Cosmos
1858
+ end
1859
+ end
@@ -116,6 +116,9 @@ module Cosmos
116
116
  footer()
117
117
  ensure
118
118
  @file.close if @file and not @file.closed?
119
+ Cosmos.set_working_dir do
120
+ File.chmod(0444, @filename)
121
+ end
119
122
  end
120
123
 
121
124
  def header
@@ -166,6 +169,7 @@ module Cosmos
166
169
  end
167
170
  end
168
171
  end
172
+ File.chmod(0444, @data_package_filename)
169
173
  end
170
174
  progress_dialog.close_done if progress_dialog
171
175
  rescue => error
@@ -971,12 +971,9 @@ module Cosmos
971
971
 
972
972
  def process_config(filename)
973
973
  ScriptRunnerFrame.instance = @script_runner_frame
974
-
975
974
  # Remember all the requires that fail and warn the user
976
975
  require_errors = []
977
976
 
978
- # Ensure the file exists
979
- raise "Configuration File: #{filename} does not exist" unless test(?f, filename)
980
977
  parser = ConfigParser.new("http://cosmosrb.com/docs/tools/#test-runner-configuration")
981
978
  parser.parse_file(filename) do |keyword, params|
982
979
  case keyword
@@ -18,8 +18,12 @@ module Cosmos
18
18
  class TabbedPlotsRealtimeThread < InterfaceThread
19
19
 
20
20
  # Create a new TabbedPlotsRealtimeThread
21
- def initialize(tabbed_plots_config, connection_success_callback = nil, connection_failed_callback = nil, connection_lost_callback = nil, fatal_exception_callback = nil)
22
- interface = TcpipClientInterface.new(System.connect_hosts['CTS_PREIDENTIFIED'], nil, System.ports['CTS_PREIDENTIFIED'], nil, tabbed_plots_config.cts_timeout, 'PREIDENTIFIED')
21
+ def initialize(tabbed_plots_config, connection_success_callback = nil, connection_failed_callback = nil, connection_lost_callback = nil, fatal_exception_callback = nil, replay_mode = false)
22
+ if replay_mode
23
+ interface = TcpipClientInterface.new(System.connect_hosts['REPLAY_PREIDENTIFIED'], nil, System.ports['REPLAY_PREIDENTIFIED'], nil, tabbed_plots_config.cts_timeout, 'PREIDENTIFIED')
24
+ else
25
+ interface = TcpipClientInterface.new(System.connect_hosts['CTS_PREIDENTIFIED'], nil, System.ports['CTS_PREIDENTIFIED'], nil, tabbed_plots_config.cts_timeout, 'PREIDENTIFIED')
26
+ end
23
27
  super(interface)
24
28
 
25
29
  @queue = Queue.new
@@ -63,6 +63,7 @@ module Cosmos
63
63
  @tabbed_plots = nil
64
64
  @realtime_thread = nil
65
65
  @config_modified = false
66
+ @replay_mode = false
66
67
 
67
68
  # Bring up slash screen for long duration tasks after creation
68
69
  Splash.execute(self) do |splash|
@@ -107,6 +108,10 @@ module Cosmos
107
108
  @file_screenshot.statusTip = tr('Screenshot of Application')
108
109
  @file_screenshot.connect(SIGNAL('triggered()')) { on_file_screenshot() }
109
110
 
111
+ @replay_action = Qt::Action.new(tr('Toggle Replay Mode'), self)
112
+ @replay_action.statusTip = tr('Toggle Replay Mode')
113
+ @replay_action.connect(SIGNAL('triggered()')) { toggle_replay_mode() }
114
+
110
115
  # Tab Menu Actions
111
116
  @tab_add = Qt::Action.new(Cosmos.get_icon('add_tab.png'), tr('&Add Tab'), self)
112
117
  @tab_add.statusTip = tr('Add New Tab')
@@ -209,6 +214,8 @@ module Cosmos
209
214
  @file_menu.addSeparator()
210
215
  @file_menu.addAction(@file_screenshot)
211
216
  @file_menu.addSeparator()
217
+ @file_menu.addAction(@replay_action)
218
+ @file_menu.addSeparator()
212
219
  @file_menu.addAction(@exit_action)
213
220
 
214
221
  @tab_menu = menuBar.addMenu(tr('&Tab'))
@@ -265,6 +272,10 @@ module Cosmos
265
272
  # Create a Vertical Frame for the right contents
266
273
  @right_widget = Qt::Widget.new(self)
267
274
  @right_frame = Qt::VBoxLayout.new
275
+ @replay_flag = Qt::Label.new("Replay Mode")
276
+ @replay_flag.setStyleSheet("background:green;color:white;padding:5px;font-weight:bold;height:30px;")
277
+ @right_frame.addWidget(@replay_flag)
278
+ @replay_flag.hide
268
279
  @right_widget.setLayout(@right_frame)
269
280
  @splitter.addWidget(@right_widget)
270
281
  @splitter.setStretchFactor(0,0) # Set the left side stretch factor to 0
@@ -581,6 +592,20 @@ module Cosmos
581
592
  @tabbed_plots.resume unless paused
582
593
  end # def on_file_screenshot
583
594
 
595
+ def toggle_replay_mode
596
+ running = @realtime_thread ? true : false
597
+ handle_stop()
598
+ System.telemetry.reset
599
+ @tabbed_plots.reset_all_data_objects
600
+ @replay_mode = !@replay_mode
601
+ if @replay_mode
602
+ @replay_flag.show
603
+ else
604
+ @replay_flag.hide
605
+ end
606
+ handle_start() if running
607
+ end
608
+
584
609
  ###############################################################################
585
610
  # Tab Menu Handlers
586
611
  ###############################################################################
@@ -921,7 +946,7 @@ module Cosmos
921
946
  # Startup realtime thread
922
947
  @realtime_button_bar.state = 'Connecting'
923
948
  statusBar.showMessage(tr("Connecting to COSMOS Server"))
924
- @realtime_thread = TabbedPlotsRealtimeThread.new(@tabbed_plots_config, method(:realtime_thread_connection_success_callback), method(:realtime_thread_connection_failed_callback), method(:realtime_thread_connection_lost_callback), method(:realtime_thread_fatal_exception_callback))
949
+ @realtime_thread = TabbedPlotsRealtimeThread.new(@tabbed_plots_config, method(:realtime_thread_connection_success_callback), method(:realtime_thread_connection_failed_callback), method(:realtime_thread_connection_lost_callback), method(:realtime_thread_fatal_exception_callback), @replay_mode)
925
950
  end
926
951
  end # def handle_start
927
952
 
@@ -21,7 +21,7 @@ module Cosmos
21
21
  # close_all_screens is called
22
22
  @@open_screens = []
23
23
 
24
- attr_accessor :full_name, :width, :height, :window
24
+ attr_accessor :full_name, :width, :height, :window, :replay_flag
25
25
 
26
26
  class Widgets
27
27
  # Flag to indicate all screens should close
@@ -229,6 +229,7 @@ module Cosmos
229
229
  app_style = File.join(Cosmos::USERPATH, 'config', 'tools', 'application.css')
230
230
  setStyleSheet(File.read(app_style)) if File.exist? app_style
231
231
 
232
+ @replay_flag = nil
232
233
  @widgets = Widgets.new(self, mode)
233
234
  @window = process(filename)
234
235
  @@open_screens << self if @window
@@ -277,6 +278,12 @@ module Cosmos
277
278
  setCentralWidget(top_widget)
278
279
  frame = Qt::VBoxLayout.new()
279
280
  top_widget.setLayout(frame)
281
+
282
+ @replay_flag = Qt::Label.new("Replay Mode")
283
+ @replay_flag.setStyleSheet("background:green;color:white;padding:5px;font-weight:bold;")
284
+ frame.addWidget(@replay_flag)
285
+ @replay_flag.hide unless get_replay_mode()
286
+
280
287
  layout_stack[0] = frame
281
288
  Cosmos.load_cosmos_icon if @single_screen
282
289
  when 'END'
@@ -498,5 +505,21 @@ module Cosmos
498
505
  Widgets.closing_all = false
499
506
  end
500
507
 
508
+ def self.update_replay_mode
509
+ screens = @@open_screens.clone
510
+ replay_mode = get_replay_mode()
511
+ screens.each do |screen|
512
+ begin
513
+ if replay_mode
514
+ screen.replay_flag.show if screen.replay_flag
515
+ else
516
+ screen.replay_flag.hide if screen.replay_flag
517
+ end
518
+ rescue
519
+ # Oh well
520
+ end
521
+ end
522
+ end
523
+
501
524
  end
502
525
  end
@@ -57,6 +57,8 @@ module Cosmos
57
57
  end
58
58
 
59
59
  def self.load_config(filename)
60
+ raise "Configuration file #{filename} does not exist." unless filename && File.exist?(filename)
61
+
60
62
  # Find all screen files so we can calculate MD5
61
63
  tlmviewer_files = [filename, System.initial_filename]
62
64
  additional_data = ''
@@ -179,6 +181,10 @@ module Cosmos
179
181
  @file_audit.shortcut = @file_audit_keyseq
180
182
  @file_audit.statusTip = tr('Create a report listing which telemetry points are not on screens')
181
183
  @file_audit.connect(SIGNAL('triggered()')) { file_audit() }
184
+
185
+ @replay_action = Qt::Action.new(tr('Toggle Replay Mode'), self)
186
+ @replay_action.statusTip = tr('Toggle Replay Mode')
187
+ @replay_action.connect(SIGNAL('triggered()')) { toggle_replay_mode() }
182
188
  end
183
189
 
184
190
  def initialize_menus(options)
@@ -187,6 +193,7 @@ module Cosmos
187
193
  @file_menu.addAction(@file_save)
188
194
  @file_menu.addAction(@file_generate)
189
195
  @file_menu.addAction(@file_audit)
196
+ @file_menu.addAction(@replay_action)
190
197
  @file_menu.addSeparator()
191
198
  @file_menu.addAction(@exit_action)
192
199
 
@@ -202,6 +209,11 @@ module Cosmos
202
209
  setCentralWidget(central_widget)
203
210
  top_layout = Qt::VBoxLayout.new
204
211
 
212
+ @replay_flag = Qt::Label.new("Replay Mode")
213
+ @replay_flag.setStyleSheet("background:green;color:white;padding:5px;font-weight:bold;")
214
+ top_layout.addWidget(@replay_flag)
215
+ @replay_flag.hide
216
+
205
217
  @search_box = FullTextSearchLineEdit.new(self)
206
218
  top_layout.addWidget(@search_box)
207
219
 
@@ -406,6 +418,16 @@ module Cosmos
406
418
  Cosmos.open_in_text_editor(output_filename) if output_filename
407
419
  end
408
420
 
421
+ def toggle_replay_mode
422
+ set_replay_mode(!get_replay_mode())
423
+ if get_replay_mode()
424
+ @replay_flag.show
425
+ else
426
+ @replay_flag.hide
427
+ end
428
+ Screen.update_replay_mode
429
+ end
430
+
409
431
  # Method called by screens to notify that they have been closed
410
432
  def notify(closed_screen)
411
433
  screen_full_name = closed_screen.full_name
@@ -447,6 +469,9 @@ module Cosmos
447
469
 
448
470
  def display(screen_full_name, x_pos = nil, y_pos = nil)
449
471
  return unless screen_full_name
472
+ x_pos = x_pos.to_i if x_pos
473
+ y_pos = y_pos.to_i if y_pos
474
+
450
475
  # Find the specified screen
451
476
  screen_info = find_screen_info(screen_full_name)
452
477
 
@@ -46,6 +46,21 @@ module Cosmos
46
46
  @invalid_items = []
47
47
  end
48
48
 
49
+ def as_json(options = nil) #:nodoc:
50
+ {group: @group,
51
+ target_name: @target_name,
52
+ original_target_name:
53
+ @original_target_name,
54
+ name: @name,
55
+ filename: @filename,
56
+ x_pos: @x_pos,
57
+ y_pos: @y_pos,
58
+ substitute: @substitute,
59
+ force_substitute: @force_substitute,
60
+ show_on_startup: @show_on_startup
61
+ }
62
+ end
63
+
49
64
  def full_name
50
65
  @group ? @name : "#{@target_name} #{@name}"
51
66
  end
@@ -96,15 +111,10 @@ module Cosmos
96
111
  attr_accessor :completion_list
97
112
  attr_accessor :tlm_to_screen_mapping
98
113
 
99
- def initialize(filename = nil)
114
+ def initialize(filename = nil, skip_read_items = false)
100
115
  # Handle nil filename
101
116
  filename = File.join(Cosmos::USERPATH, 'config', 'tools', 'tlm_viewer', 'tlm_viewer.txt') unless filename
102
117
  @filename = filename
103
-
104
- # Ensure the file exists
105
- raise "Telemetry Viewer configuration file #{filename} does not exist" unless test ?f, filename
106
-
107
- # Initialize instance variables
108
118
  @columns = []
109
119
  @columns << {}
110
120
  @screen_infos = {}
@@ -129,7 +139,7 @@ module Cosmos
129
139
  screen_dir = File.join(target.dir, 'screens')
130
140
  if File.exist?(screen_dir) and num_screens(screen_dir) > 0
131
141
  start_target(target.name, parser)
132
- auto_screens()
142
+ auto_screens(skip_read_items)
133
143
  end
134
144
  end
135
145
 
@@ -141,7 +151,7 @@ module Cosmos
141
151
  screen_dir = File.join(target.dir, 'screens')
142
152
  if File.exist?(screen_dir) and num_screens(screen_dir) > 0
143
153
  start_target(target.name, parser)
144
- auto_screens()
154
+ auto_screens(skip_read_items)
145
155
  end
146
156
 
147
157
  when 'TARGET'
@@ -153,7 +163,7 @@ module Cosmos
153
163
  raise parser.error("No target defined. SCREEN must follow TARGET.") unless @current_target
154
164
  parser.verify_num_parameters(1, 3, 'SCREEN <Filename> <X Position (optional)> <Y Position (optional)>')
155
165
  screen_filename = File.join(@current_target.dir, 'screens', parameters[0])
156
- start_screen(screen_filename, parameters[1], parameters[2])
166
+ start_screen(screen_filename, parameters[1], parameters[2], skip_read_items)
157
167
 
158
168
  when 'SHOW_ON_STARTUP'
159
169
  raise parser.error("No screen defined. SHOW_ON_STARTUP must follow SCREEN or GROUP_SCREEN.") unless @current_screen_info
@@ -179,7 +189,7 @@ module Cosmos
179
189
  parser.verify_num_parameters(2, 4, 'GROUP_SCREEN <Target Name> <Screen Filename> <X Position (optional)> <Y Position (Optional)>')
180
190
  start_target(parameters[0].upcase, parser, @current_group)
181
191
  screen_filename = File.join(@current_target.dir, 'screens', parameters[1])
182
- start_screen(screen_filename, parameters[2], parameters[3])
192
+ start_screen(screen_filename, parameters[2], parameters[3], skip_read_items)
183
193
 
184
194
  else
185
195
  # blank config.lines will have a nil keyword and should not raise an exception
@@ -233,7 +243,7 @@ module Cosmos
233
243
  end
234
244
  end
235
245
 
236
- def start_screen(screen_filename, x_pos = nil, y_pos = nil)
246
+ def start_screen(screen_filename, x_pos = nil, y_pos = nil, skip_read_items = false)
237
247
  screen_name = File.basename(screen_filename, '.txt').upcase
238
248
  x_pos = x_pos.to_i if x_pos
239
249
  y_pos = y_pos.to_i if y_pos
@@ -244,15 +254,15 @@ module Cosmos
244
254
  @current_screen_info.force_substitute = true if @current_target.auto_screen_substitute
245
255
  @current_screen_info.original_target_name = @current_target.original_name
246
256
  @current_screen_info.substitute = @current_target.name if @current_target.substitute or @current_target.auto_screen_substitute
247
- @current_screen_info.read_items
257
+ @current_screen_info.read_items unless skip_read_items
248
258
  end
249
259
 
250
- def auto_screens
260
+ def auto_screens(skip_read_items = false)
251
261
  @current_group = nil
252
262
  screen_dir = File.join(@current_target.dir, 'screens')
253
263
  if File.exist?(screen_dir)
254
264
  Dir.new(screen_dir).each do |filename|
255
- start_screen(File.join(screen_dir, filename)) if valid_screen_name(filename)
265
+ start_screen(File.join(screen_dir, filename), nil, nil, skip_read_items) if valid_screen_name(filename)
256
266
  end
257
267
  end
258
268
  end