cosmos 3.1.1 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +6 -0
  3. data/autohotkey/config/tools/handbook_creator/templates/command_packets.html.erb +1 -1
  4. data/autohotkey/config/tools/handbook_creator/templates/footer.html.erb +2 -2
  5. data/autohotkey/config/tools/handbook_creator/templates/header.html.erb +4 -4
  6. data/autohotkey/tools/autohotkey.rb +1 -1
  7. data/autohotkey/tools/cmd_tlm_server.ahk +1 -0
  8. data/autohotkey/tools/packet_viewer.ahk +45 -2
  9. data/data/crc.txt +20 -15
  10. data/demo/Rakefile +16 -0
  11. data/demo/config/data/crc.txt +3 -3
  12. data/demo/config/tools/handbook_creator/templates/footer.html.erb +2 -2
  13. data/demo/config/tools/handbook_creator/templates/header.html.erb +4 -4
  14. data/demo/procedures/example_test.rb +1 -1
  15. data/install/Rakefile +16 -0
  16. data/install/config/data/crc.txt +2 -2
  17. data/install/config/tools/handbook_creator/templates/footer.html.erb +2 -2
  18. data/install/config/tools/handbook_creator/templates/header.html.erb +4 -4
  19. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +64 -57
  20. data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +0 -9
  21. data/lib/cosmos/gui/qt.rb +22 -18
  22. data/lib/cosmos/packet_logs/packet_log_writer.rb +6 -2
  23. data/lib/cosmos/script/script.rb +1 -1
  24. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +0 -1
  25. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +99 -784
  26. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +189 -0
  27. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +176 -0
  28. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +144 -0
  29. data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +240 -0
  30. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +90 -0
  31. data/lib/cosmos/tools/launcher/launcher_config.rb +142 -110
  32. data/lib/cosmos/tools/test_runner/results_writer.rb +1 -1
  33. data/lib/cosmos/tools/test_runner/test_runner.rb +3 -2
  34. data/lib/cosmos/tools/tlm_grapher/data_objects/data_object.rb +18 -2
  35. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +4 -9
  36. data/lib/cosmos/tools/tlm_grapher/data_objects/xy_data_object.rb +5 -5
  37. data/lib/cosmos/top_level.rb +1 -1
  38. data/lib/cosmos/version.rb +4 -4
  39. data/run_gui_tests.bat +33 -31
  40. data/spec/core_ext/time_spec.rb +51 -0
  41. data/spec/script/script_spec.rb +96 -0
  42. data/spec/tools/cmd_tlm_server/commanding_spec.rb +28 -0
  43. data/spec/tools/cmd_tlm_server/connections_spec.rb +88 -0
  44. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +78 -25
  45. data/spec/tools/launcher/launcher_config_spec.rb +460 -0
  46. data/spec/top_level/top_level_spec.rb +1 -1
  47. metadata +8 -2
@@ -0,0 +1,189 @@
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
+ require 'cosmos/gui/qt'
13
+
14
+ module Cosmos
15
+
16
+ # Implements the interfaces and routers tabs in the Command and Telemetry Server GUI
17
+ class InterfacesTab
18
+ INTERFACES = 'Interfaces'
19
+ ROUTERS = 'Routers'
20
+
21
+ def initialize
22
+ @interfaces_table = {}
23
+ end
24
+
25
+ # Create the interfaces tab and add it to the tab_widget
26
+ #
27
+ # @param tab_widget [Qt::TabWidget] The tab widget to add the tab to
28
+ def populate_interfaces(tab_widget)
29
+ populate(INTERFACES, CmdTlmServer.interfaces, tab_widget)
30
+ end
31
+
32
+ # Create the routers tab and add it to the tab_widget
33
+ #
34
+ # @param tab_widget [Qt::TabWidget] The tab widget to add the tab to
35
+ def populate_routers(tab_widget)
36
+ populate(ROUTERS, CmdTlmServer.routers, tab_widget)
37
+ end
38
+
39
+ # Update the interfaces or routers tab
40
+ #
41
+ # @param name [String] Must be Interfaces or Routers
42
+ def update(name)
43
+ if name == ROUTERS
44
+ interfaces = CmdTlmServer.routers
45
+ else
46
+ interfaces = CmdTlmServer.interfaces
47
+ end
48
+ row = 0
49
+ interfaces.all.each do |interface_name, interface|
50
+ button = @interfaces_table[name].cellWidget(row,1)
51
+ state = @interfaces_table[name].item(row,2)
52
+ if interface.connected?
53
+ button.setText('Disconnect')
54
+ button.setDisabled(true) if interface.disable_disconnect
55
+ state.setText('true')
56
+ state.textColor = Cosmos::GREEN
57
+ elsif interface.thread
58
+ button.text = 'Cancel Connect'
59
+ button.setDisabled(false)
60
+ state.text = 'attempting'
61
+ state.textColor = Cosmos::RED
62
+ else
63
+ button.setText('Connect')
64
+ button.setDisabled(false)
65
+ state.setText('false')
66
+ state.textColor = Cosmos::BLACK
67
+ end
68
+ @interfaces_table[name].item(row,3).setText(interface.num_clients.to_s)
69
+ @interfaces_table[name].item(row,4).setText(interface.write_queue_size.to_s)
70
+ @interfaces_table[name].item(row,5).setText(interface.read_queue_size.to_s)
71
+ @interfaces_table[name].item(row,6).setText(interface.bytes_written.to_s)
72
+ @interfaces_table[name].item(row,7).setText(interface.bytes_read.to_s)
73
+ if name == ROUTERS
74
+ @interfaces_table[name].item(row,8).setText(interface.read_count.to_s)
75
+ @interfaces_table[name].item(row,9).setText(interface.write_count.to_s)
76
+ else
77
+ @interfaces_table[name].item(row,8).setText(interface.write_count.to_s)
78
+ @interfaces_table[name].item(row,9).setText(interface.read_count.to_s)
79
+ end
80
+ row += 1
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def populate(name, interfaces, tab_widget)
87
+ return if interfaces.all.empty?
88
+
89
+ scroll = Qt::ScrollArea.new
90
+ scroll.setMinimumSize(800, 150)
91
+ widget = Qt::Widget.new
92
+ layout = Qt::VBoxLayout.new(widget)
93
+ # Since the layout will be inside a scroll area make sure it respects the sizes we set
94
+ layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
95
+
96
+ interfaces_table = Qt::TableWidget.new()
97
+ interfaces_table.verticalHeader.hide()
98
+ interfaces_table.setRowCount(interfaces.all.length)
99
+ interfaces_table.setColumnCount(10)
100
+ if name == ROUTERS
101
+ interfaces_table.setHorizontalHeaderLabels(["Router", "Connect/Disconnect", "Connected?", "Clients", "Tx Q Size", "Rx Q Size", " Bytes Tx ", " Bytes Rx ", " Cmd Pkts ", " Tlm Pkts "])
102
+ else
103
+ interfaces_table.setHorizontalHeaderLabels(["Interface", "Connect/Disconnect", "Connected?", "Clients", "Tx Q Size", "Rx Q Size", " Bytes Tx ", " Bytes Rx ", " Cmd Pkts ", " Tlm Pkts "])
104
+ end
105
+
106
+ populate_interface_table(name, interfaces, interfaces_table)
107
+ interfaces_table.displayFullSize
108
+
109
+ layout.addWidget(interfaces_table)
110
+ scroll.setWidget(widget)
111
+ @interfaces_table[name] = interfaces_table
112
+ tab_widget.addTab(scroll, name)
113
+ end
114
+
115
+ def populate_interface_table(name, interfaces, interfaces_table)
116
+ row = 0
117
+ interfaces.all.each do |interface_name, interface|
118
+ item = Qt::TableWidgetItem.new(Qt::Object.tr(interface_name))
119
+ item.setTextAlignment(Qt::AlignCenter)
120
+ interfaces_table.setItem(row, 0, item)
121
+ interfaces_table.setCellWidget(row, 1, create_button(name, interface, interface_name))
122
+ interfaces_table.setItem(row, 2, create_state(interface))
123
+
124
+ index = 3
125
+ [interface.num_clients, interface.write_queue_size, interface.read_queue_size,
126
+ interface.bytes_written, interface.bytes_read,
127
+ interface.write_count, interface.read_count].each do |val|
128
+
129
+ item = Qt::TableWidgetItem.new(Qt::Object.tr(val.to_s))
130
+ item.setTextAlignment(Qt::AlignCenter)
131
+ interfaces_table.setItem(row, index, item)
132
+ index += 1
133
+ end
134
+ row += 1
135
+ end
136
+ end
137
+
138
+ def create_button(name, interface, interface_name)
139
+ if interface.connected?
140
+ button_text = 'Disconnect'
141
+ elsif interface.thread.nil?
142
+ button_text = 'Connect'
143
+ else
144
+ button_text = 'Cancel Connect'
145
+ end
146
+ button = Qt::PushButton.new(button_text)
147
+ if name == ROUTERS
148
+ button.connect(SIGNAL('clicked()')) do
149
+ if interface.thread
150
+ Logger.info "User disconnecting router #{interface_name}"
151
+ CmdTlmServer.instance.disconnect_router(interface_name)
152
+ else
153
+ Logger.info "User connecting router #{interface_name}"
154
+ CmdTlmServer.instance.connect_router(interface_name)
155
+ end
156
+ end
157
+ else
158
+ button.connect(SIGNAL('clicked()')) do
159
+ if interface.thread
160
+ Logger.info "User disconnecting interface #{interface_name}"
161
+ CmdTlmServer.instance.disconnect_interface(interface_name)
162
+ else
163
+ Logger.info "User connecting interface #{interface_name}"
164
+ CmdTlmServer.instance.connect_interface(interface_name)
165
+ end
166
+ end
167
+ end
168
+ button.setDisabled(true) if interface.disable_disconnect
169
+ button
170
+ end
171
+
172
+ def create_state(interface)
173
+ state = Qt::TableWidgetItem.new
174
+ if interface.connected?
175
+ state.setText('true')
176
+ state.textColor = Cosmos::GREEN
177
+ elsif interface.thread
178
+ state.setText('attempting')
179
+ state.textColor = Cosmos::YELLOW
180
+ else
181
+ state.setText('false')
182
+ state.textColor = Cosmos::BLACK
183
+ end
184
+ state.setTextAlignment(Qt::AlignCenter)
185
+ state
186
+ end
187
+
188
+ end
189
+ end # module Cosmos
@@ -0,0 +1,176 @@
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
+ require 'cosmos/gui/qt'
13
+
14
+ module Cosmos
15
+
16
+ # Implements the logging tab in the Command and Telemetry Server GUI
17
+ class LoggingTab
18
+
19
+ def initialize(production)
20
+ @production = production
21
+ @logging_layouts = {}
22
+ end
23
+
24
+ # Create the logging tab and add it to the tab_widget
25
+ #
26
+ # @param tab_widget [Qt::TabWidget] The tab widget to add the tab to
27
+ def populate(tab_widget)
28
+ scroll = Qt::ScrollArea.new
29
+ widget = Qt::Widget.new
30
+ layout = Qt::VBoxLayout.new(widget)
31
+ # Since the layout will be inside a scroll area
32
+ # make sure it respects the sizes we set
33
+ layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
34
+
35
+ populate_logging_actions(layout)
36
+
37
+ # Add the cmd/tlm log files information
38
+ populate_log_file_info(layout)
39
+
40
+ # Set the scroll area widget last now that all the items have been layed out
41
+ scroll.setWidget(widget)
42
+ tab_widget.addTab(scroll, "Logging")
43
+ end
44
+
45
+ def update
46
+ CmdTlmServer.packet_logging.all.each do |packet_log_writer_pair_name, packet_log_writer_pair|
47
+ @logging_layouts[packet_log_writer_pair_name].itemAt(1, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.logging_enabled.to_s)
48
+ @logging_layouts[packet_log_writer_pair_name].itemAt(2, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.queue.size.to_s)
49
+ @logging_layouts[packet_log_writer_pair_name].itemAt(3, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.cmd_log_writer.filename)
50
+ file_size = 0
51
+ begin
52
+ file_size = File.size(packet_log_writer_pair.cmd_log_writer.filename) if packet_log_writer_pair.cmd_log_writer.filename
53
+ rescue Exception
54
+ # Do nothing on error
55
+ end
56
+ @logging_layouts[packet_log_writer_pair_name].itemAt(4, Qt::FormLayout::FieldRole).widget.setText(file_size.to_s)
57
+ @logging_layouts[packet_log_writer_pair_name].itemAt(5, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.logging_enabled.to_s)
58
+ @logging_layouts[packet_log_writer_pair_name].itemAt(6, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.queue.size.to_s)
59
+ @logging_layouts[packet_log_writer_pair_name].itemAt(7, Qt::FormLayout::FieldRole).widget.setText(packet_log_writer_pair.tlm_log_writer.filename)
60
+ file_size = 0
61
+ begin
62
+ file_size = File.size(packet_log_writer_pair.tlm_log_writer.filename) if packet_log_writer_pair.tlm_log_writer.filename
63
+ rescue Exception
64
+ # Do nothing on error
65
+ end
66
+ @logging_layouts[packet_log_writer_pair_name].itemAt(8, Qt::FormLayout::FieldRole).widget.setText(file_size.to_s)
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def populate_logging_actions(layout)
73
+ # Add all the action buttons
74
+ actions = Qt::GroupBox.new(Qt::Object.tr("Actions"))
75
+ actions_layout = Qt::VBoxLayout.new(actions)
76
+ button_layout = Qt::GridLayout.new
77
+
78
+ log_buttons = [
79
+ ["Start Logging on All", [0,0], :start_logging],
80
+ ["Stop Logging on All", [0,1], :stop_logging],
81
+ ["Start Telemetry Logging on All", [1,0], :start_tlm_log],
82
+ ["Stop Telemetry Logging on All", [1,1], :stop_tlm_log],
83
+ ["Start Command Logging on All", [2,0], :start_cmd_log],
84
+ ["Stop Command Logging on All", [2,1], :stop_cmd_log]
85
+ ]
86
+
87
+ log_buttons.each do |text, location, method|
88
+ next if text =~ /Stop/ and @production
89
+ button = Qt::PushButton.new(Qt::Object.tr(text))
90
+ button_layout.addWidget(button, location[0], location[1])
91
+ button.connect(SIGNAL('clicked()')) do
92
+ begin
93
+ CmdTlmServer.instance.send(method, 'ALL')
94
+ rescue Exception => error
95
+ statusBar.showMessage(Qt::Object.tr(error.message))
96
+ end
97
+ end
98
+ end
99
+
100
+ actions_layout.addLayout(button_layout)
101
+
102
+ layout.addWidget(actions)
103
+ end
104
+
105
+ def create_log_layout(form_layout, log_writer, label_prefix)
106
+ label = Qt::Label.new(Qt::Object.tr(log_writer.logging_enabled.to_s))
107
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
108
+ form_layout.addRow("#{label_prefix} Logging:", label)
109
+ label = Qt::Label.new(Qt::Object.tr(log_writer.queue.size.to_s))
110
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
111
+ form_layout.addRow("#{label_prefix} Queue Size:", label)
112
+ label = Qt::Label.new(Qt::Object.tr(log_writer.filename))
113
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
114
+ form_layout.addRow("#{label_prefix} Filename:", label)
115
+ file_size = 0
116
+ begin
117
+ file_size = File.size(log_writer.filename) if log_writer.filename
118
+ rescue Exception
119
+ # Do nothing on error
120
+ end
121
+ label = Qt::Label.new(Qt::Object.tr(file_size.to_s))
122
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
123
+ form_layout.addRow("#{label_prefix} File Size:", label)
124
+ end
125
+
126
+ def populate_log_file_info(layout)
127
+ CmdTlmServer.packet_logging.all.sort.each do |packet_log_writer_pair_name, packet_log_writer_pair|
128
+ log = Qt::GroupBox.new("#{packet_log_writer_pair_name} Packet Log Writer")
129
+ log_layout = Qt::VBoxLayout.new(log)
130
+ interfaces = []
131
+ CmdTlmServer.interfaces.all.each do |interface_name, interface|
132
+ if interface.packet_log_writer_pairs.include?(packet_log_writer_pair)
133
+ interfaces << interface.name
134
+ end
135
+ end
136
+
137
+ form_layout = Qt::FormLayout.new
138
+ @logging_layouts[packet_log_writer_pair_name] = form_layout
139
+ label = Qt::Label.new(Qt::Object.tr(interfaces.join(", ")))
140
+ label.setTextInteractionFlags(Qt::TextSelectableByMouse)
141
+ form_layout.addRow("Interfaces:", label)
142
+ create_log_layout(form_layout, packet_log_writer_pair.cmd_log_writer, 'Cmd')
143
+ create_log_layout(form_layout, packet_log_writer_pair.tlm_log_writer, 'Tlm')
144
+
145
+ button_layout = Qt::HBoxLayout.new
146
+ start_button = Qt::PushButton.new(Qt::Object.tr('Start Cmd Logging'))
147
+ button_layout.addWidget(start_button)
148
+ start_button.connect(SIGNAL('clicked()')) do
149
+ CmdTlmServer.instance.start_cmd_log(packet_log_writer_pair_name)
150
+ end
151
+ start_button = Qt::PushButton.new(Qt::Object.tr('Start Tlm Logging'))
152
+ button_layout.addWidget(start_button)
153
+ start_button.connect(SIGNAL('clicked()')) do
154
+ CmdTlmServer.instance.start_tlm_log(packet_log_writer_pair_name)
155
+ end
156
+ if @production == false
157
+ stop_button = Qt::PushButton.new(Qt::Object.tr('Stop Cmd Logging'))
158
+ button_layout.addWidget(stop_button)
159
+ stop_button.connect(SIGNAL('clicked()')) do
160
+ CmdTlmServer.instance.stop_cmd_log(packet_log_writer_pair_name)
161
+ end
162
+ stop_button = Qt::PushButton.new(Qt::Object.tr('Stop Tlm Logging'))
163
+ button_layout.addWidget(stop_button)
164
+ stop_button.connect(SIGNAL('clicked()')) do
165
+ CmdTlmServer.instance.stop_tlm_log(packet_log_writer_pair_name)
166
+ end
167
+ end
168
+ form_layout.addRow("Actions:", button_layout)
169
+ log_layout.addLayout(form_layout)
170
+ layout.addWidget(log)
171
+ end
172
+ layout.addWidget(Qt::Label.new(Qt::Object.tr("Note: Buffered IO operations cause file size to not reflect total logged data size until the log file is closed.")))
173
+ end
174
+
175
+ end
176
+ end # module Cosmos
@@ -0,0 +1,144 @@
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
+ require 'cosmos/gui/qt'
13
+ require 'cosmos/gui/dialogs/cmd_tlm_raw_dialog'
14
+
15
+ module Cosmos
16
+
17
+ # Implements the packets tab in the Command and Telemetry Server GUI
18
+ class PacketsTab
19
+ COMMANDS = "Commands"
20
+ TELEMETRY = "Telemetry"
21
+
22
+ def initialize(server_gui)
23
+ @server_gui = server_gui
24
+ @packets_table = {}
25
+ end
26
+
27
+ def populate_commands(tab_widget)
28
+ populate(COMMANDS, System.commands, tab_widget)
29
+ end
30
+
31
+ def populate_telemetry(tab_widget)
32
+ populate(TELEMETRY, System.telemetry, tab_widget)
33
+ end
34
+
35
+ def update(name)
36
+ cmd_tlm = nil
37
+ cmd_tlm = System.commands if name == COMMANDS
38
+ cmd_tlm = System.telemetry if name == TELEMETRY
39
+ return if cmd_tlm.nil? || cmd_tlm.target_names.empty?
40
+
41
+ row = 0
42
+ cmd_tlm.target_names.sort.each do |target_name|
43
+ packets = cmd_tlm.packets(target_name)
44
+ packets.sort.each do |packet_name, packet|
45
+ next if packet.hidden
46
+ @packets_table[name].item(row, 2).setText(packet.received_count.to_s)
47
+ row += 1
48
+ end
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def populate(name, cmd_tlm, tab_widget)
55
+ return if cmd_tlm.target_names.empty?
56
+
57
+ count = 0
58
+ cmd_tlm.target_names.sort.each do |target_name|
59
+ packets = cmd_tlm.packets(target_name)
60
+ packets.each do |packet_name, packet|
61
+ count += 1 unless packet.hidden
62
+ end
63
+ end
64
+
65
+ scroll = Qt::ScrollArea.new
66
+ widget = Qt::Widget.new
67
+ layout = Qt::VBoxLayout.new(widget)
68
+ # Since the layout will be inside a scroll area
69
+ # make sure it respects the sizes we set
70
+ layout.setSizeConstraint(Qt::Layout::SetMinAndMaxSize)
71
+
72
+ table = Qt::TableWidget.new()
73
+ table.verticalHeader.hide()
74
+ table.setRowCount(count)
75
+ column_cnt = 4
76
+ column_cnt += 1 if name == TELEMETRY
77
+ table.setColumnCount(column_cnt)
78
+ # Force the last section to fill all available space in the frame
79
+ #~ table.horizontalHeader.setStretchLastSection(true)
80
+ headers = ["Target Name", "Packet Name", "Packet Count", "View Raw"]
81
+ headers << "View in Packet Viewer" if name == TELEMETRY
82
+ table.setHorizontalHeaderLabels(headers)
83
+
84
+ populate_packets_table(name, cmd_tlm, table)
85
+ table.displayFullSize
86
+
87
+ layout.addWidget(table)
88
+ scroll.setWidget(widget)
89
+ tab_name = "Cmd Packets" if name == COMMANDS
90
+ tab_name = "Tlm Packets" if name == TELEMETRY
91
+ tab_widget.addTab(scroll, tab_name)
92
+
93
+ @packets_table[name] = table
94
+ end
95
+
96
+ def populate_packets_table(name, cmd_tlm, table)
97
+ row = 0
98
+ cmd_tlm.target_names.sort.each do |target_name|
99
+ packets = cmd_tlm.packets(target_name)
100
+ packets.sort.each do |packet_name, packet|
101
+ packet.received_count ||= 0
102
+ next if packet.hidden
103
+ target_name_widget = Qt::TableWidgetItem.new(Qt::Object.tr(target_name))
104
+ target_name_widget.setTextAlignment(Qt::AlignRight | Qt::AlignVCenter)
105
+ table.setItem(row, 0, target_name_widget)
106
+ table.setItem(row, 1, Qt::TableWidgetItem.new(Qt::Object.tr(packet_name)))
107
+ packet_count = Qt::TableWidgetItem.new(Qt::Object.tr(packet.received_count.to_s))
108
+ packet_count.setTextAlignment(Qt::AlignCenter)
109
+ table.setItem(row, 2, packet_count)
110
+ view_raw = Qt::PushButton.new("View Raw")
111
+ view_raw.connect(SIGNAL('clicked()')) do
112
+ @raw_dialogs ||= []
113
+ @raw_dialogs << CmdRawDialog.new(@server_gui, target_name, packet_name) if name == COMMANDS
114
+ @raw_dialogs << TlmRawDialog.new(@server_gui, target_name, packet_name) if name == TELEMETRY
115
+ end
116
+ table.setCellWidget(row, 3, view_raw)
117
+
118
+ if name == TELEMETRY
119
+ if target_name != 'UNKNOWN' and packet_name != 'UNKNOWN'
120
+ view_pv = Qt::PushButton.new("View in Packet Viewer")
121
+ view_pv.connect(SIGNAL('clicked()')) do
122
+ if Kernel.is_windows?
123
+ Cosmos.run_process("rubyw tools/PacketViewer -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
124
+ elsif Kernel.is_mac? and File.exist?("tools/mac/PacketViewer.app")
125
+ Cosmos.run_process("open tools/mac/PacketViewer.app --args -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
126
+ else
127
+ Cosmos.run_process("ruby tools/PacketViewer -p \"#{target_name} #{packet_name}\" --system #{File.basename(System.initial_filename)}")
128
+ end
129
+ end
130
+ table.setCellWidget(row, 4, view_pv)
131
+ else
132
+ table_widget = Qt::TableWidgetItem.new(Qt::Object.tr('N/A'))
133
+ table_widget.setTextAlignment(Qt::AlignCenter)
134
+ table.setItem(row, 4, table_widget)
135
+ end
136
+ end
137
+
138
+ row += 1
139
+ end
140
+ end
141
+ end
142
+
143
+ end
144
+ end # module Cosmos