cosmos 3.3.3 → 3.4.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.
- checksums.yaml +4 -4
- data/.gitattributes +2 -0
- data/.travis.yml +2 -1
- data/Gemfile +4 -3
- data/Manifest.txt +22 -0
- data/autohotkey/tools/handbook_creator.ahk +9 -0
- data/autohotkey/tools/packet_viewer.ahk +4 -0
- data/bin/exchndl20-x64.dll +0 -0
- data/bin/exchndl20.dll +0 -0
- data/bin/exchndl21-x64.dll +0 -0
- data/bin/exchndl21.dll +0 -0
- data/bin/exchndl22-x64.dll +0 -0
- data/bin/exchndl22.dll +0 -0
- data/bin/mgwhelp-x64.dll +0 -0
- data/bin/mgwhelp.dll +0 -0
- data/cosmos.gemspec +1 -0
- data/data/crc.txt +30 -24
- data/demo/config/data/crc.txt +3 -3
- data/demo/config/tools/handbook_creator/templates/command_packets.html.erb +3 -1
- data/demo/config/tools/handbook_creator/templates/telemetry_packets.html.erb +3 -1
- data/demo/procedures/cosmos_api_test.rb +1 -1
- data/ext/cosmos/ext/low_fragmentation_array/low_fragmentation_array.c +4 -0
- data/ext/cosmos/ext/platform/platform.c +22 -2
- data/ext/cosmos/ext/structure/structure.c +631 -104
- data/ext/cosmos/ext/telemetry/telemetry.c +3 -2
- data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +71 -92
- data/lib/cosmos/gui/line_graph/overview_graph.rb +1 -1
- data/lib/cosmos/gui/qt.rb +38 -24
- data/lib/cosmos/gui/text/ruby_editor.rb +1 -1
- data/lib/cosmos/packets/binary_accessor.rb +1 -288
- data/lib/cosmos/packets/telemetry.rb +2 -1
- data/lib/cosmos/script/cmd_tlm_server.rb +110 -0
- data/lib/cosmos/script/commands.rb +166 -0
- data/lib/cosmos/script/extract.rb +2 -2
- data/lib/cosmos/script/limits.rb +108 -0
- data/lib/cosmos/script/script.rb +28 -1487
- data/lib/cosmos/script/scripting.rb +889 -0
- data/lib/cosmos/script/telemetry.rb +174 -0
- data/lib/cosmos/script/tools.rb +138 -0
- data/lib/cosmos/streams/stream_protocol.rb +9 -6
- data/lib/cosmos/system/target.rb +55 -38
- data/lib/cosmos/tools/cmd_tlm_server/api.rb +6 -3
- data/lib/cosmos/tools/cmd_tlm_server/connections.rb +0 -1
- data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +17 -7
- data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +15 -4
- data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +15 -8
- data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +41 -13
- data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +18 -1
- data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +1 -1
- data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +1 -1
- data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +1 -1
- data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +1 -1
- data/lib/cosmos/top_level.rb +1 -1
- data/lib/cosmos/utilities/ruby_lex_utils.rb +1 -1
- data/lib/cosmos/version.rb +5 -5
- data/spec/gui/line_graph/line_clip_spec.rb +6 -6
- data/spec/gui/qt_spec.rb +102 -0
- data/spec/interfaces/interface_spec.rb +9 -9
- data/spec/interfaces/linc_interface_spec.rb +72 -15
- data/spec/interfaces/serial_interface_spec.rb +9 -9
- data/spec/interfaces/simulated_target_interface_spec.rb +7 -7
- data/spec/interfaces/stream_interface_spec.rb +4 -4
- data/spec/interfaces/tcpip_client_interface_spec.rb +8 -8
- data/spec/interfaces/tcpip_server_interface_spec.rb +9 -9
- data/spec/interfaces/udp_interface_spec.rb +20 -20
- data/spec/io/json_drb_spec.rb +4 -4
- data/spec/io/raw_logger_pair_spec.rb +20 -20
- data/spec/io/raw_logger_spec.rb +3 -3
- data/spec/io/tcpip_server_spec.rb +9 -9
- data/spec/io/udp_sockets_spec.rb +2 -2
- data/spec/io/win32_serial_driver_spec.rb +2 -2
- data/spec/packets/binary_accessor_spec.rb +143 -6
- data/spec/packets/commands_spec.rb +5 -5
- data/spec/packets/limits_spec.rb +15 -15
- data/spec/packets/packet_config_spec.rb +19 -19
- data/spec/packets/packet_item_limits_spec.rb +3 -3
- data/spec/packets/packet_item_spec.rb +4 -4
- data/spec/packets/packet_spec.rb +33 -33
- data/spec/packets/structure_item_spec.rb +19 -19
- data/spec/packets/telemetry_spec.rb +6 -6
- data/spec/script/cmd_tlm_server_spec.rb +110 -0
- data/spec/script/commands_disconnect_spec.rb +270 -0
- data/spec/script/commands_spec.rb +288 -0
- data/spec/script/limits_spec.rb +153 -0
- data/spec/script/script_spec.rb +32 -696
- data/spec/script/scripting_spec.rb +436 -0
- data/spec/script/telemetry_spec.rb +130 -0
- data/spec/script/tools_spec.rb +117 -0
- data/spec/spec_helper.rb +10 -5
- data/spec/streams/preidentified_stream_protocol_spec.rb +4 -4
- data/spec/streams/serial_stream_spec.rb +8 -8
- data/spec/streams/stream_protocol_spec.rb +4 -4
- data/spec/streams/tcpip_client_stream_spec.rb +3 -3
- data/spec/streams/tcpip_socket_stream_spec.rb +7 -7
- data/spec/streams/template_stream_protocol_spec.rb +1 -1
- data/spec/system/system_spec.rb +6 -6
- data/spec/system/target_spec.rb +2 -0
- data/spec/tools/cmd_tlm_server/api_spec.rb +17 -17
- data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +5 -5
- data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +3 -3
- data/spec/top_level/top_level_spec.rb +8 -8
- data/spec/utilities/csv_spec.rb +3 -3
- data/spec/utilities/message_log_spec.rb +3 -3
- data/spec/utilities/ruby_lex_utils_spec.rb +7 -7
- data/test/performance/config/tools/launcher/launcher_threads.txt +8 -1
- data/test/performance/tools/CmdTlmServerMemProf +1 -1
- data/test/performance/tools/TlmGrapherMemProf +19 -0
- data/test/performance/tools/TlmGrapherMemProf.bat +59 -0
- metadata +38 -2
|
@@ -171,8 +171,9 @@ static VALUE value(int argc, VALUE* argv, VALUE self)
|
|
|
171
171
|
* can be passed which will convert all items the same way. Or
|
|
172
172
|
* an array of symbols can be passed to control how each item is
|
|
173
173
|
* converted.
|
|
174
|
-
* @return [Array, Array] The first array contains the item values
|
|
175
|
-
* second their limits state
|
|
174
|
+
* @return [Array, Array, Array] The first array contains the item values, the
|
|
175
|
+
* second their limits state, and the third the limits settings which includes
|
|
176
|
+
* red, yellow, and green (if given) limits values.
|
|
176
177
|
*/
|
|
177
178
|
static VALUE values_and_limits_states(int argc, VALUE* argv, VALUE self) {
|
|
178
179
|
VALUE item_array = Qnil;
|
|
@@ -33,7 +33,7 @@ module Cosmos
|
|
|
33
33
|
calculate_scaling_factors()
|
|
34
34
|
|
|
35
35
|
# Draw overall graph and origin lines
|
|
36
|
-
|
|
36
|
+
draw_graph_background(@painter)
|
|
37
37
|
draw_origin_lines(@painter)
|
|
38
38
|
|
|
39
39
|
# Draw gridlines and titles
|
|
@@ -45,7 +45,6 @@ module Cosmos
|
|
|
45
45
|
draw_y_axis_title(@painter, :LEFT)
|
|
46
46
|
draw_y_axis_title(@painter, :RIGHT)
|
|
47
47
|
|
|
48
|
-
# Draw legend and lines
|
|
49
48
|
draw_legend(@painter)
|
|
50
49
|
|
|
51
50
|
draw_lines(@painter, :LEFT)
|
|
@@ -54,7 +53,6 @@ module Cosmos
|
|
|
54
53
|
|
|
55
54
|
# Draws the graph to the screen
|
|
56
55
|
def draw_graph_to_screen
|
|
57
|
-
# Draw frame around graph
|
|
58
56
|
draw_frame(@painter)
|
|
59
57
|
|
|
60
58
|
# Draw cursor line and popups if present
|
|
@@ -64,16 +62,10 @@ module Cosmos
|
|
|
64
62
|
draw_error_icon(@painter)
|
|
65
63
|
end # def draw_graph_to_screen
|
|
66
64
|
|
|
67
|
-
#
|
|
68
|
-
def
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
dc.setPen(color)
|
|
72
|
-
dc.setBrush(Cosmos.getBrush(@@gradient))
|
|
73
|
-
dc.drawRect(@graph_left_x,@graph_top_y,@graph_right_x - @graph_left_x,@graph_bottom_y - @graph_top_y)
|
|
74
|
-
# Draw the graph border
|
|
75
|
-
dc.addRectColor(@graph_left_x, @graph_top_y, @graph_right_x - @graph_left_x, @graph_bottom_y - @graph_top_y, @label_and_border_color)
|
|
76
|
-
end # def clear_canvas_and_draw_graph_rectangle
|
|
65
|
+
# Draws the colored rectangle for the graph
|
|
66
|
+
def draw_graph_background(dc)
|
|
67
|
+
dc.addRectColorFill(@graph_left_x, @graph_top_y, @graph_right_x - @graph_left_x, @graph_bottom_y - @graph_top_y, @label_and_border_color, @@gradient)
|
|
68
|
+
end
|
|
77
69
|
|
|
78
70
|
# Draws origin lines if they fall on the graph
|
|
79
71
|
def draw_origin_lines(dc)
|
|
@@ -93,14 +85,19 @@ module Cosmos
|
|
|
93
85
|
|
|
94
86
|
# Draws the gridlines for a y-axis
|
|
95
87
|
def draw_y_axis_grid_lines(dc)
|
|
88
|
+
grid_lines = []
|
|
96
89
|
@y_grid_lines.each_with_index do |value, index|
|
|
97
90
|
# Don't draw gridlines that are too close to 0
|
|
98
91
|
if ((value > (@y_grid_line_scale / 2.0)) || (value < (@y_grid_line_scale / -2.0)))
|
|
99
|
-
|
|
92
|
+
grid_lines << draw_y_label(dc, value, index)
|
|
100
93
|
else
|
|
101
|
-
|
|
94
|
+
grid_lines << draw_y_label(dc, 0, index)
|
|
102
95
|
end
|
|
103
96
|
end
|
|
97
|
+
# Now draw all the grid lines so we can use a single Pen for all
|
|
98
|
+
grid_lines.each do |y|
|
|
99
|
+
dc.addLineColor(@graph_left_x, y, @graph_right_x, y, Cosmos::DASHLINE_PEN)
|
|
100
|
+
end
|
|
104
101
|
end # def draw_y_axis_grid_lines
|
|
105
102
|
|
|
106
103
|
# Calcuate the Y axis labels as well as their width and adjust the size of
|
|
@@ -144,10 +141,8 @@ module Cosmos
|
|
|
144
141
|
@graph_right_x -= (right_widths.max + GRAPH_SPACER)
|
|
145
142
|
end
|
|
146
143
|
|
|
147
|
-
# This function is used to draw
|
|
148
|
-
|
|
149
|
-
# label values calculated in calculate_y_labels.
|
|
150
|
-
def draw_y_label_and_grid_line(dc, value, index, show_line)
|
|
144
|
+
# This function is used to draw the y labels.
|
|
145
|
+
def draw_y_label(dc, value, index)
|
|
151
146
|
left_value = value
|
|
152
147
|
right_value = value
|
|
153
148
|
left_text = @left_text[index]
|
|
@@ -193,28 +188,29 @@ module Cosmos
|
|
|
193
188
|
y + (@font_size / 2))
|
|
194
189
|
end
|
|
195
190
|
end
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
dc.addLineColor(@graph_left_x, y, @graph_right_x, y, Cosmos::DASHLINE_PEN)
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
end # def draw_y_label_and_grid_line
|
|
191
|
+
return y
|
|
192
|
+
end
|
|
202
193
|
|
|
203
194
|
# Draws the gridlines for the x-axis
|
|
204
195
|
def draw_x_axis_grid_lines(dc)
|
|
196
|
+
grid_lines = []
|
|
205
197
|
@x_grid_lines.each do |value, label|
|
|
206
198
|
# If the line has states or is far enough away from the origin
|
|
207
199
|
if @lines.x_states || ((value > (@x_grid_line_scale / 2.0)) || (value < (@x_grid_line_scale / -2.0)))
|
|
208
|
-
|
|
200
|
+
grid_lines << draw_x_label(dc, value, label)
|
|
209
201
|
else
|
|
210
|
-
|
|
202
|
+
grid_lines << draw_x_label(dc, 0, nil)
|
|
211
203
|
end
|
|
212
204
|
end
|
|
205
|
+
# Now draw all the grid lines so we can use a single Pen for all
|
|
206
|
+
grid_lines.each do |x1, y1, x2, y2|
|
|
207
|
+
dc.addLineColor(x1, y1, x2, y2, Cosmos::DASHLINE_PEN)
|
|
208
|
+
end
|
|
213
209
|
end # def draw_x_axis_grid_lines
|
|
214
210
|
|
|
215
|
-
# This function is used to draw
|
|
216
|
-
#
|
|
217
|
-
def
|
|
211
|
+
# This function is used to draw the x labels and returns the line
|
|
212
|
+
# positions.
|
|
213
|
+
def draw_x_label(dc, value, label)
|
|
218
214
|
if label
|
|
219
215
|
text = label.to_s
|
|
220
216
|
else
|
|
@@ -231,13 +227,8 @@ module Cosmos
|
|
|
231
227
|
if (x1 > @graph_right_x)
|
|
232
228
|
x1 = @graph_right_x
|
|
233
229
|
end
|
|
234
|
-
|
|
235
|
-
y2 = @graph_top_y
|
|
236
|
-
else
|
|
237
|
-
y2 = @graph_bottom_y
|
|
238
|
-
end
|
|
230
|
+
y2 = @graph_top_y
|
|
239
231
|
x2 = x1
|
|
240
|
-
dc.addLineColor(x1, y1, x2, y2, Cosmos::DASHLINE_PEN)
|
|
241
232
|
|
|
242
233
|
# Only display the label if we have room. This really only affects the
|
|
243
234
|
# right side of the graph since that's where new grid lines appear. The
|
|
@@ -245,10 +236,11 @@ module Cosmos
|
|
|
245
236
|
# white space on the right side of the graph.
|
|
246
237
|
if (x1 == @graph_right_x) || (x1 < (@graph_right_x - (1.25 * text_width)))
|
|
247
238
|
# Shift the far right label left a bit to eliminate white space
|
|
248
|
-
x1
|
|
249
|
-
x1
|
|
250
|
-
dc.addSimpleTextAt(text,
|
|
239
|
+
text_x = x1 - text_width / 4 if x1 == @graph_right_x
|
|
240
|
+
text_x = x1 - text_width / 2 # center the text
|
|
241
|
+
dc.addSimpleTextAt(text, text_x, @graph_bottom_y + text_height + GRAPH_SPACER)
|
|
251
242
|
end
|
|
243
|
+
[x1, y1, x2, y2]
|
|
252
244
|
end # def draw_x_label_and_grid_line
|
|
253
245
|
|
|
254
246
|
# Converts a x value into text with a max number of characters
|
|
@@ -286,7 +278,7 @@ module Cosmos
|
|
|
286
278
|
end
|
|
287
279
|
end
|
|
288
280
|
|
|
289
|
-
# Draw the overall graph title
|
|
281
|
+
# Draw the overall graph title above the graph
|
|
290
282
|
def draw_title(dc)
|
|
291
283
|
if @title
|
|
292
284
|
metrics = Cosmos.getFontMetrics(@title_font)
|
|
@@ -294,9 +286,9 @@ module Cosmos
|
|
|
294
286
|
dc.addSimpleTextAt(@title, (self.width / 2) - (metrics.width(@title) / 2), metrics.height)
|
|
295
287
|
dc.setFont(@font)
|
|
296
288
|
end
|
|
297
|
-
end
|
|
289
|
+
end
|
|
298
290
|
|
|
299
|
-
# Draws the title
|
|
291
|
+
# Draws the x axis title below the graph
|
|
300
292
|
def draw_x_axis_title(dc)
|
|
301
293
|
if @x_axis_title
|
|
302
294
|
metrics = Cosmos.getFontMetrics(@font)
|
|
@@ -306,9 +298,9 @@ module Cosmos
|
|
|
306
298
|
(((@graph_right_x - @graph_left_x) / 2) + @graph_left_x) - (text_width / 2),
|
|
307
299
|
@graph_bottom_y + (2 * text_height) + GRAPH_SPACER)
|
|
308
300
|
end
|
|
309
|
-
end
|
|
301
|
+
end
|
|
310
302
|
|
|
311
|
-
# Draws
|
|
303
|
+
# Draws titles to the left and right of the Y axis
|
|
312
304
|
def draw_y_axis_title(dc, axis)
|
|
313
305
|
metrics = Cosmos.getFontMetrics(@font)
|
|
314
306
|
if axis == :LEFT
|
|
@@ -330,58 +322,46 @@ module Cosmos
|
|
|
330
322
|
dc.addSimpleTextAt(character, graph_x + ((max_width - cur_width) / 2), start_height + text_height * index)
|
|
331
323
|
end
|
|
332
324
|
end
|
|
333
|
-
end
|
|
325
|
+
end
|
|
334
326
|
|
|
335
327
|
# Draws the legend on the bottom of the graph
|
|
336
328
|
def draw_legend(dc)
|
|
329
|
+
return if !@show_legend || @lines.empty?
|
|
330
|
+
|
|
331
|
+
text_x, text_y, legend_width, legend_height = get_legend_position()
|
|
332
|
+
if @lines.axes == :BOTH
|
|
333
|
+
draw_legend_text(dc, :LEFT, text_x, text_y, legend_height)
|
|
334
|
+
draw_legend_text(dc, :RIGHT, text_x + (legend_width / 2), text_y, legend_height)
|
|
335
|
+
else
|
|
336
|
+
draw_legend_text(dc, false, text_x, text_y, legend_height)
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# Calculate the legend x, y, width and height
|
|
341
|
+
def get_legend_position
|
|
337
342
|
metrics = Cosmos.getFontMetrics(@font)
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
# Draw legend text for each line
|
|
358
|
-
if both_axis
|
|
359
|
-
left_text_x = text_x
|
|
360
|
-
right_text_x = text_x + (legend_width / 2)
|
|
361
|
-
left_text_y = text_y
|
|
362
|
-
right_text_y = text_y
|
|
363
|
-
@lines.legend.reverse_each do |legend_text, color, axis|
|
|
364
|
-
if axis == :LEFT
|
|
365
|
-
dc.addSimpleTextAt(legend_text, left_text_x, left_text_y, color)
|
|
366
|
-
left_text_y -= metrics.height
|
|
367
|
-
else
|
|
368
|
-
dc.addSimpleTextAt(legend_text, right_text_x, right_text_y, color)
|
|
369
|
-
right_text_y -= metrics.height
|
|
370
|
-
end
|
|
371
|
-
end
|
|
372
|
-
if left_text_y < right_text_y
|
|
373
|
-
text_y = left_text_y
|
|
374
|
-
else
|
|
375
|
-
text_y = right_text_y
|
|
376
|
-
end
|
|
377
|
-
else
|
|
378
|
-
@lines.legend.reverse_each do |legend_text, color, axis|
|
|
379
|
-
dc.addSimpleTextAt(legend_text, text_x, text_y, color)
|
|
380
|
-
text_y -= metrics.height
|
|
381
|
-
end
|
|
343
|
+
legend_width = 0
|
|
344
|
+
@lines.legend.each do |legend_text, color, axis|
|
|
345
|
+
text_width = metrics.width(legend_text)
|
|
346
|
+
legend_width = text_width if text_width > legend_width
|
|
347
|
+
end
|
|
348
|
+
legend_width += (GRAPH_SPACER * 2)
|
|
349
|
+
legend_width *= 2 if @lines.axes == :BOTH
|
|
350
|
+
legend_graph_x = (self.width - legend_width) / 2
|
|
351
|
+
|
|
352
|
+
text_x = legend_graph_x + GRAPH_SPACER
|
|
353
|
+
text_y = self.height - metrics.height
|
|
354
|
+
return [text_x, text_y, legend_width, metrics.height]
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def draw_legend_text(dc, specific_axis, text_x, text_y, line_height)
|
|
358
|
+
@lines.legend.reverse_each do |legend_text, color, axis|
|
|
359
|
+
if !specific_axis || specific_axis == axis
|
|
360
|
+
dc.addSimpleTextAt(legend_text, text_x, text_y, color)
|
|
361
|
+
text_y -= line_height
|
|
382
362
|
end
|
|
383
363
|
end
|
|
384
|
-
end
|
|
364
|
+
end
|
|
385
365
|
|
|
386
366
|
# Draws all lines for the given axis
|
|
387
367
|
# def draw_lines(dc, axis)
|
|
@@ -438,9 +418,8 @@ module Cosmos
|
|
|
438
418
|
end # unless popups.empty?
|
|
439
419
|
end
|
|
440
420
|
|
|
441
|
-
# Draws the overall frame around the
|
|
421
|
+
# Draws the overall frame around the graph, legend, labels, etc
|
|
442
422
|
def draw_frame(dc)
|
|
443
|
-
# Draw Frame Rectangle around canvas
|
|
444
423
|
dc.addRectColor(0,0,self.width-1,self.height-1, @frame_color)
|
|
445
424
|
end
|
|
446
425
|
|
|
@@ -400,7 +400,7 @@ module Cosmos
|
|
|
400
400
|
|
|
401
401
|
def draw_graph_into_back_buffer
|
|
402
402
|
# Draw overall graph and origin lines and graph lines
|
|
403
|
-
|
|
403
|
+
draw_graph_background(@painter)
|
|
404
404
|
draw_origin_lines(@painter)
|
|
405
405
|
draw_lines(@painter, :LEFT)
|
|
406
406
|
|
data/lib/cosmos/gui/qt.rb
CHANGED
|
@@ -94,6 +94,7 @@ module Cosmos
|
|
|
94
94
|
color = nil
|
|
95
95
|
key = color_r
|
|
96
96
|
key = key.to_i if key.is_a? Qt::Enum
|
|
97
|
+
|
|
97
98
|
if color_r && color_g && color_b
|
|
98
99
|
key = (color_r.to_i << 24) + (color_g.to_i << 16) + (color_b.to_i << 8)
|
|
99
100
|
end
|
|
@@ -112,6 +113,8 @@ module Cosmos
|
|
|
112
113
|
end
|
|
113
114
|
|
|
114
115
|
def self.getBrush(color)
|
|
116
|
+
return nil unless color
|
|
117
|
+
return color if color.is_a? Qt::Brush
|
|
115
118
|
brush = nil
|
|
116
119
|
color = Cosmos.getColor(color)
|
|
117
120
|
brush = BRUSHES[color]
|
|
@@ -280,10 +283,16 @@ class Qt::TableWidget
|
|
|
280
283
|
resizeRowsToContents()
|
|
281
284
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff)
|
|
282
285
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff)
|
|
283
|
-
setMinimumSize(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
286
|
+
setMinimumSize(fullWidth, fullHeight)
|
|
287
|
+
setMaximumSize(fullWidth, fullHeight)
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def fullWidth
|
|
291
|
+
2*frameWidth() + horizontalHeader.length + verticalHeader.width
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def fullHeight
|
|
295
|
+
2*frameWidth() + verticalHeader.length + horizontalHeader.height
|
|
287
296
|
end
|
|
288
297
|
end
|
|
289
298
|
|
|
@@ -669,47 +678,52 @@ class Qt::ColorListWidget < Qt::ListWidget
|
|
|
669
678
|
end
|
|
670
679
|
|
|
671
680
|
class Qt::Painter
|
|
681
|
+
def setPen(pen_color)
|
|
682
|
+
super(Cosmos::getColor(pen_color))
|
|
683
|
+
@pen_color = pen_color
|
|
684
|
+
end
|
|
685
|
+
def setBrush(brush)
|
|
686
|
+
super(Cosmos::getBrush(brush))
|
|
687
|
+
@brush = brush
|
|
688
|
+
end
|
|
689
|
+
|
|
672
690
|
def addLineColor(x, y, w, h, color = Cosmos::BLACK)
|
|
673
|
-
|
|
691
|
+
setPen(color) if color != @pen_color
|
|
674
692
|
drawLine(x,y,w,h)
|
|
675
693
|
end
|
|
676
694
|
|
|
677
695
|
def addRectColor(x, y, w, h, color = Cosmos::BLACK)
|
|
678
|
-
|
|
679
|
-
setBrush(nil)
|
|
696
|
+
setPen(color) if color != @pen_color
|
|
697
|
+
setBrush(nil) if @brush
|
|
680
698
|
drawRect(x,y,w,h)
|
|
681
699
|
end
|
|
682
700
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
701
|
+
# Note if brush_color is not specified it will be the same as pen_color
|
|
702
|
+
def addRectColorFill(x, y, w, h, pen_color = Cosmos::BLACK, brush_color = nil)
|
|
703
|
+
setPen(pen_color) if pen_color != @pen_color
|
|
704
|
+
brush_color = pen_color unless brush_color
|
|
705
|
+
setBrush(brush_color) if brush_color != @brush
|
|
686
706
|
drawRect(x,y,w,h)
|
|
687
707
|
end
|
|
688
708
|
|
|
689
709
|
def addSimpleTextAt(text, x, y, color = Cosmos::BLACK)
|
|
690
|
-
|
|
710
|
+
setPen(color) if color != @pen_color
|
|
691
711
|
drawText(x,y,text)
|
|
692
712
|
end
|
|
693
713
|
|
|
694
714
|
def addEllipseColor(x, y, w, h, color = Cosmos::BLACK)
|
|
695
|
-
|
|
696
|
-
setBrush(nil)
|
|
715
|
+
setPen(color) if color != @pen_color
|
|
716
|
+
setBrush(nil) if @brush
|
|
697
717
|
drawEllipse(x,y,w,h)
|
|
698
718
|
end
|
|
699
719
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
720
|
+
# Note if brush_color is not specified it will be the same as pen_color
|
|
721
|
+
def addEllipseColorFill(x, y, w, h, pen_color = Cosmos::BLACK, brush_color = nil)
|
|
722
|
+
setPen(pen_color) if pen_color != @pen_color
|
|
723
|
+
brush_color = pen_color unless brush_color
|
|
724
|
+
setBrush(brush_color) if brush_color != @brush
|
|
703
725
|
drawEllipse(x,y,w,h)
|
|
704
726
|
end
|
|
705
|
-
|
|
706
|
-
private
|
|
707
|
-
|
|
708
|
-
def setPenColor(color)
|
|
709
|
-
color = Cosmos::getColor(color)
|
|
710
|
-
setPen(color)
|
|
711
|
-
end
|
|
712
|
-
|
|
713
727
|
end
|
|
714
728
|
|
|
715
729
|
class Qt::MatrixLayout < Qt::GridLayout
|
|
@@ -111,294 +111,7 @@ module Cosmos
|
|
|
111
111
|
# @param endianness [Symbol] {ENDIANNESS}
|
|
112
112
|
# @param overflow [Symbol] {OVERFLOW_TYPES}
|
|
113
113
|
# @return [Integer] value passed in as a parameter
|
|
114
|
-
def self.write(value, bit_offset, bit_size, data_type, buffer, endianness, overflow)
|
|
115
|
-
# Save given values of bit offset and bit size
|
|
116
|
-
given_bit_offset = bit_offset
|
|
117
|
-
given_bit_size = bit_size
|
|
118
|
-
|
|
119
|
-
# Handle negative and zero bit sizes
|
|
120
|
-
if bit_size <= 0
|
|
121
|
-
if data_type == :STRING or data_type == :BLOCK
|
|
122
|
-
if given_bit_offset < 0
|
|
123
|
-
raise ArgumentError, "negative or zero bit_sizes (#{given_bit_size}) cannot be given with negative bit_offsets (#{given_bit_offset})"
|
|
124
|
-
else
|
|
125
|
-
bit_size = value.to_s.length * 8
|
|
126
|
-
end
|
|
127
|
-
else
|
|
128
|
-
raise ArgumentError, "bit_size #{given_bit_size} must be positive for data types other than :STRING and :BLOCK"
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# Handle negative bit offsets
|
|
133
|
-
if bit_offset < 0
|
|
134
|
-
bit_offset = ((buffer.length * 8) + bit_offset)
|
|
135
|
-
raise_buffer_error(:write, buffer, data_type, given_bit_offset, given_bit_size) if bit_offset < 0
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# Define bounds of string to access this item
|
|
139
|
-
lower_bound = bit_offset / 8
|
|
140
|
-
upper_bound = (bit_offset + bit_size - 1) / 8
|
|
141
|
-
|
|
142
|
-
# Check for byte alignment
|
|
143
|
-
byte_aligned = ((bit_offset % 8) == 0)
|
|
144
|
-
|
|
145
|
-
# Sanity check buffer size
|
|
146
|
-
if upper_bound >= buffer.length and given_bit_size > 0
|
|
147
|
-
# Check special case of little endian bit field
|
|
148
|
-
if endianness == :LITTLE_ENDIAN and (data_type == :INT or data_type == :UINT) and !(byte_aligned and (bit_size == 8 or bit_size == 16 or bit_size == 32 or bit_size == 64)) and lower_bound < buffer.length
|
|
149
|
-
# Ok little endian bit field
|
|
150
|
-
else
|
|
151
|
-
raise_buffer_error(:write, buffer, data_type, given_bit_offset, given_bit_size)
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
# Check overflow type
|
|
156
|
-
raise "unknown overflow type #{overflow}" unless OVERFLOW_TYPES.include?(overflow)
|
|
157
|
-
|
|
158
|
-
case data_type
|
|
159
|
-
when :STRING, :BLOCK
|
|
160
|
-
#######################################
|
|
161
|
-
# Handle :STRING and :BLOCK data types
|
|
162
|
-
#######################################
|
|
163
|
-
|
|
164
|
-
# Ensure value is the correct type
|
|
165
|
-
value = value.to_s
|
|
166
|
-
|
|
167
|
-
if byte_aligned
|
|
168
|
-
temp = value
|
|
169
|
-
if given_bit_size <= 0
|
|
170
|
-
end_bytes = -(given_bit_size / 8)
|
|
171
|
-
old_upper_bound = buffer.length - 1 - end_bytes
|
|
172
|
-
if old_upper_bound < lower_bound
|
|
173
|
-
# String was completely empty
|
|
174
|
-
if end_bytes > 0
|
|
175
|
-
# Preserve bytes at end of buffer
|
|
176
|
-
buffer_length = buffer.length
|
|
177
|
-
buffer << ZERO_STRING * value.length
|
|
178
|
-
buffer[(lower_bound + value.length)..(buffer.length - 1)] = buffer[lower_bound..(buffer_length - 1)]
|
|
179
|
-
end
|
|
180
|
-
elsif bit_size == 0
|
|
181
|
-
# Remove entire string
|
|
182
|
-
buffer[lower_bound..old_upper_bound] = ''
|
|
183
|
-
elsif upper_bound < old_upper_bound
|
|
184
|
-
# Remove extra bytes from old string
|
|
185
|
-
buffer[(upper_bound + 1)..old_upper_bound] = ''
|
|
186
|
-
elsif upper_bound > old_upper_bound and end_bytes > 0
|
|
187
|
-
# Preserve bytes at end of buffer
|
|
188
|
-
buffer_length = buffer.length
|
|
189
|
-
diff = upper_bound - old_upper_bound
|
|
190
|
-
buffer << ZERO_STRING * diff
|
|
191
|
-
buffer[(upper_bound + 1)..(buffer.length - 1)] = buffer[(old_upper_bound + 1)..(buffer_length - 1)]
|
|
192
|
-
end
|
|
193
|
-
else
|
|
194
|
-
byte_size = bit_size / 8
|
|
195
|
-
if value.length < byte_size
|
|
196
|
-
temp = value.ljust(byte_size, ZERO_STRING)
|
|
197
|
-
elsif value.length > byte_size
|
|
198
|
-
if overflow == :TRUNCATE
|
|
199
|
-
temp = value[0..(byte_size - 1)]
|
|
200
|
-
else
|
|
201
|
-
raise ArgumentError, "value of #{value.length} bytes does not fit into #{byte_size} bytes for data_type #{data_type}"
|
|
202
|
-
end
|
|
203
|
-
else
|
|
204
|
-
temp = value
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
buffer[lower_bound..upper_bound] = temp if bit_size != 0
|
|
208
|
-
else
|
|
209
|
-
raise ArgumentError, "bit_offset #{given_bit_offset} is not byte aligned for data_type #{data_type}"
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
when :INT, :UINT
|
|
213
|
-
###################################
|
|
214
|
-
# Handle :INT and :UINT data types
|
|
215
|
-
###################################
|
|
216
|
-
|
|
217
|
-
# Ensure value is the correct type
|
|
218
|
-
value = Integer(value)
|
|
219
|
-
|
|
220
|
-
if byte_aligned and (bit_size == 8 or bit_size == 16 or bit_size == 32 or bit_size == 64)
|
|
221
|
-
###########################################################
|
|
222
|
-
# Handle byte-aligned 8, 16, 32, and 64 bit :INT and :UINT
|
|
223
|
-
###########################################################
|
|
224
|
-
|
|
225
|
-
case bit_size
|
|
226
|
-
when 8
|
|
227
|
-
if data_type == :INT
|
|
228
|
-
value = self.check_overflow(value, -128, 127, 255, bit_size, data_type, overflow)
|
|
229
|
-
else
|
|
230
|
-
value = self.check_overflow(value, 0, 255, 255, bit_size, data_type, overflow)
|
|
231
|
-
end
|
|
232
|
-
buffer.setbyte(lower_bound, value % 256)
|
|
233
|
-
|
|
234
|
-
when 16
|
|
235
|
-
if data_type == :INT
|
|
236
|
-
value = self.check_overflow(value, -32768, 32767, 65535, bit_size, data_type, overflow)
|
|
237
|
-
if endianness == HOST_ENDIANNESS
|
|
238
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_16_BIT_INT)
|
|
239
|
-
else # endianness != HOST_ENDIANNESS
|
|
240
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_16_BIT_INT).reverse
|
|
241
|
-
end
|
|
242
|
-
else # data_type == :UINT
|
|
243
|
-
value = self.check_overflow(value, 0, 65535, 65535, bit_size, data_type, overflow)
|
|
244
|
-
if endianness == :BIG_ENDIAN
|
|
245
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_16_BIT_UINT)
|
|
246
|
-
else # endianness == :LITTLE_ENDIAN
|
|
247
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_16_BIT_UINT)
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
when 32
|
|
252
|
-
if data_type == :INT
|
|
253
|
-
# Note signed integers must allow up to the maximum unsigned value to support values given in hex
|
|
254
|
-
value = self.check_overflow(value, -2147483648, 2147483647, 4294967295, bit_size, data_type, overflow)
|
|
255
|
-
if endianness == HOST_ENDIANNESS
|
|
256
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_32_BIT_INT)
|
|
257
|
-
else # endianness != HOST_ENDIANNESS
|
|
258
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_32_BIT_INT).reverse
|
|
259
|
-
end
|
|
260
|
-
elsif data_type == :UINT
|
|
261
|
-
value = self.check_overflow(value, 0, 4294967295, 4294967295, bit_size, data_type, overflow)
|
|
262
|
-
if endianness == :BIG_ENDIAN
|
|
263
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_32_BIT_UINT)
|
|
264
|
-
else # endianness == :LITTLE_ENDIAN
|
|
265
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_32_BIT_UINT)
|
|
266
|
-
end
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
when 64
|
|
270
|
-
if data_type == :INT
|
|
271
|
-
# Note signed integers must allow up to the maximum unsigned value to support values given in hex
|
|
272
|
-
value = self.check_overflow(value, -9223372036854775808, 9223372036854775807, 18446744073709551615, bit_size, data_type, overflow)
|
|
273
|
-
if endianness == HOST_ENDIANNESS
|
|
274
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_INT)
|
|
275
|
-
else # endianness != HOST_ENDIANNESS
|
|
276
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_INT).reverse
|
|
277
|
-
end
|
|
278
|
-
elsif data_type == :UINT
|
|
279
|
-
value = self.check_overflow(value, 0, 18446744073709551615, 18446744073709551615, bit_size, data_type, overflow)
|
|
280
|
-
if endianness == HOST_ENDIANNESS
|
|
281
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_UINT)
|
|
282
|
-
else # endianness != HOST_ENDIANNESS
|
|
283
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_UINT).reverse
|
|
284
|
-
end
|
|
285
|
-
end
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
else
|
|
289
|
-
##################################
|
|
290
|
-
# Handle :INT and :UINT Bitfields
|
|
291
|
-
##################################
|
|
292
|
-
|
|
293
|
-
if data_type == :INT
|
|
294
|
-
# Note signed integers must allow up to the maximum unsigned value to support values given in hex
|
|
295
|
-
if bit_size > 1
|
|
296
|
-
min_value = -(2 ** (bit_size - 1))
|
|
297
|
-
max_value = -min_value - 1
|
|
298
|
-
hex_max_value = (2 ** bit_size) - 1
|
|
299
|
-
else
|
|
300
|
-
min_value = -1
|
|
301
|
-
max_value = 1
|
|
302
|
-
hex_max_value = 1
|
|
303
|
-
end
|
|
304
|
-
value = self.check_overflow(value, min_value, max_value, hex_max_value, bit_size, data_type, overflow)
|
|
305
|
-
else
|
|
306
|
-
max_value = (2 ** bit_size) - 1
|
|
307
|
-
value = self.check_overflow(value, 0, max_value, max_value, bit_size, data_type, overflow)
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
# Extract Existing Data
|
|
311
|
-
if endianness == :LITTLE_ENDIAN
|
|
312
|
-
# Bitoffset always refers to the most significant bit of a bitfield
|
|
313
|
-
num_bytes = (((bit_offset % 8) + bit_size - 1) / 8) + 1
|
|
314
|
-
upper_bound = bit_offset / 8
|
|
315
|
-
lower_bound = upper_bound - num_bytes + 1
|
|
316
|
-
|
|
317
|
-
if lower_bound < 0
|
|
318
|
-
raise ArgumentError, "LITTLE_ENDIAN bitfield with bit_offset #{given_bit_offset} and bit_size #{given_bit_size} is invalid"
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
temp_data = buffer[lower_bound..upper_bound].reverse
|
|
322
|
-
else
|
|
323
|
-
temp_data = buffer[lower_bound..upper_bound]
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
# Determine temp upper bound
|
|
327
|
-
temp_upper = upper_bound - lower_bound
|
|
328
|
-
|
|
329
|
-
# Determine Values needed to Handle Bitfield
|
|
330
|
-
start_bits = bit_offset % 8
|
|
331
|
-
start_mask = (0xFF << (8 - start_bits))
|
|
332
|
-
total_bits = (temp_upper + 1) * 8
|
|
333
|
-
end_bits = total_bits - start_bits - bit_size
|
|
334
|
-
end_mask = ~(0xFF << end_bits)
|
|
335
|
-
|
|
336
|
-
# Add in Start Bits
|
|
337
|
-
temp = temp_data.getbyte(0) & start_mask
|
|
338
|
-
|
|
339
|
-
# Adjust value to correct number of bits
|
|
340
|
-
temp_mask = (2 ** bit_size) - 1
|
|
341
|
-
temp_value = value.to_i & temp_mask
|
|
342
|
-
|
|
343
|
-
# Add in New Data
|
|
344
|
-
temp = (temp << (bit_size - (8 - start_bits))) + temp_value
|
|
345
|
-
|
|
346
|
-
# Add in Remainder of Existing Data
|
|
347
|
-
temp = (temp << end_bits) + (temp_data.getbyte(temp_upper) & end_mask)
|
|
348
|
-
|
|
349
|
-
# Extract into an array of bytes
|
|
350
|
-
temp_array = []
|
|
351
|
-
(0..temp_upper).each { temp_array.insert(0, (temp & 0xFF)); temp = temp >> 8 }
|
|
352
|
-
|
|
353
|
-
# Store into buffer
|
|
354
|
-
if endianness == :LITTLE_ENDIAN
|
|
355
|
-
buffer[lower_bound..upper_bound] = temp_array.pack(PACK_8_BIT_UINT_ARRAY).reverse
|
|
356
|
-
else
|
|
357
|
-
buffer[lower_bound..upper_bound] = temp_array.pack(PACK_8_BIT_UINT_ARRAY)
|
|
358
|
-
end
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
when :FLOAT
|
|
362
|
-
##########################
|
|
363
|
-
# Handle :FLOAT data type
|
|
364
|
-
##########################
|
|
365
|
-
|
|
366
|
-
# Ensure value is the correct type
|
|
367
|
-
value = Float(value)
|
|
368
|
-
|
|
369
|
-
if byte_aligned
|
|
370
|
-
case bit_size
|
|
371
|
-
when 32
|
|
372
|
-
if endianness == :BIG_ENDIAN
|
|
373
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_32_BIT_FLOAT)
|
|
374
|
-
else # endianness == :LITTLE_ENDIAN
|
|
375
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_32_BIT_FLOAT)
|
|
376
|
-
end
|
|
377
|
-
|
|
378
|
-
when 64
|
|
379
|
-
if endianness == :BIG_ENDIAN
|
|
380
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_64_BIT_FLOAT)
|
|
381
|
-
else # endianness == :LITTLE_ENDIAN
|
|
382
|
-
buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_64_BIT_FLOAT)
|
|
383
|
-
end
|
|
384
|
-
|
|
385
|
-
else
|
|
386
|
-
raise ArgumentError, "bit_size is #{given_bit_size} but must be 32 or 64 for data_type #{data_type}"
|
|
387
|
-
end
|
|
388
|
-
else
|
|
389
|
-
raise ArgumentError, "bit_offset #{given_bit_offset} is not byte aligned for data_type #{data_type}"
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
else
|
|
393
|
-
############################
|
|
394
|
-
# Handle Unknown data types
|
|
395
|
-
############################
|
|
396
|
-
|
|
397
|
-
raise ArgumentError, "data_type #{data_type} is not recognized"
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
value
|
|
401
|
-
end # def self.write
|
|
114
|
+
# def self.write(value, bit_offset, bit_size, data_type, buffer, endianness, overflow)
|
|
402
115
|
|
|
403
116
|
# Reads an array of binary data of any data type from a buffer
|
|
404
117
|
#
|