source: src/mlx/gui/pirep.py@ 834:5651e303daa9

Last change on this file since 834:5651e303daa9 was 834:5651e303daa9, checked in by István Váradi <ivaradi@…>, 7 years ago

Backed out changeset f300ebc45a7f

File size: 22.1 KB
RevLine 
[220]1
2from common import *
3
[236]4from mlx.pirep import PIREP
[220]5from mlx.const import *
6
7import time
8
9#------------------------------------------------------------------------------
10
[300]11## @package mlx.gui.pirep
12#
[834]13# The detailed PIREP viewer.
[300]14#
15# The \ref PIREPViewer class is a dialog displaying all information found in a
16# PIREP. It consists of three tabs. The Data tab displays the simple,
17# itemizable data. The Comments & defects tab contains the flight comments and
18# defects, while the Log tab contains the flight log collected by the
19# \ref mlx.logger.Logger "logger".
20
21#------------------------------------------------------------------------------
22
[220]23class PIREPViewer(gtk.Dialog):
24 """The dialog for PIREP viewing."""
25 @staticmethod
26 def createFrame(label):
27 """Create a frame with the given label.
28
29 The frame will contain an alignment to properly distance the
30 insides. The alignment will contain a VBox to contain the real
[831]31 contents.
[220]32
33 The function returns a tuple with the following items:
34 - the frame,
35 - the inner VBox."""
36 frame = gtk.Frame(label = label)
37
38 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
39 xscale = 1.0, yscale = 1.0)
40 frame.add(alignment)
41 alignment.set_padding(padding_top = 4, padding_bottom = 4,
42 padding_left = 4, padding_right = 4)
43 box = gtk.VBox()
44 alignment.add(box)
[831]45
[220]46 return (frame, box)
47
48 @staticmethod
[834]49 def getLabel(text):
[220]50 """Get a bold label with the given text."""
[834]51 label = gtk.Label("<b>" + text + "</b>")
[220]52 label.set_use_markup(True)
53 label.set_alignment(0.0, 0.5)
54 return label
55
56 @staticmethod
57 def getDataLabel(width = None, xAlignment = 0.0):
58 """Get a bold label with the given text."""
59 label = gtk.Label()
60 if width is not None:
61 label.set_width_chars(width)
62 label.set_alignment(xAlignment, 0.5)
63 return label
64
65 @staticmethod
[834]66 def getTextWindow(heightRequest = 40):
[220]67 """Get a scrollable text window.
[831]68
[220]69 Returns a tuple of the following items:
70 - the window,
71 - the text view."""
72 scrolledWindow = gtk.ScrolledWindow()
73 scrolledWindow.set_shadow_type(SHADOW_IN)
74 scrolledWindow.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
75
76 textView = gtk.TextView()
77 textView.set_wrap_mode(WRAP_WORD)
[834]78 textView.set_editable(False)
79 textView.set_cursor_visible(False)
[220]80 textView.set_size_request(-1, heightRequest)
81 scrolledWindow.add(textView)
82
83 return (scrolledWindow, textView)
84
85 @staticmethod
86 def tableAttach(table, column, row, labelText, width = None,
87 dataLabelXAlignment = 0.0):
88 """Attach a labeled data to the given column and row of the
[831]89 table.
90
[220]91 If width is given, that will be the width of the data
92 label.
93
94 Returns the data label attached."""
95 dataBox = gtk.HBox()
96 table.attach(dataBox, column, column+1, row, row+1)
[831]97
[220]98 dataLabel = PIREPViewer.addLabeledData(dataBox, labelText,
99 width = width)
100 dataLabel.set_alignment(dataLabelXAlignment, 0.5)
101
102 return dataLabel
103
104 @staticmethod
105 def addLabeledData(hBox, labelText, width = None, dataPadding = 8):
106 """Add a label and a data label to the given HBox.
[831]107
[834]108 Returnsd the data label."""
[220]109 label = PIREPViewer.getLabel(labelText)
110 hBox.pack_start(label, False, False, 0)
[831]111
[220]112 dataLabel = PIREPViewer.getDataLabel(width = width)
113 hBox.pack_start(dataLabel, False, False, dataPadding)
114
115 return dataLabel
116
117 @staticmethod
118 def addVFiller(vBox, height = 4):
[238]119 """Add a filler to the given vertical box."""
120 filler = gtk.Alignment(xalign = 0.0, yalign = 0.0,
121 xscale = 1.0, yscale = 1.0)
[220]122 filler.set_size_request(-1, height)
123 vBox.pack_start(filler, False, False, 0)
[831]124
[220]125 @staticmethod
126 def timestamp2text(label, timestamp):
127 """Convert the given timestamp into a text containing the hour
128 and minute in UTC and put that text into the given label."""
129 tm = time.gmtime(timestamp)
130 label.set_text("%02d:%02d" % (tm.tm_hour, tm.tm_min))
131
132 def __init__(self, gui):
133 """Construct the PIREP viewer."""
134 super(PIREPViewer, self).__init__(title = WINDOW_TITLE_BASE +
135 " - " +
136 xstr("pirepView_title"),
137 parent = gui.mainWindow)
[831]138
[220]139 self.set_resizable(False)
140
141 self._gui = gui
[831]142
[220]143 contentArea = self.get_content_area()
[221]144
145 self._notebook = gtk.Notebook()
146 contentArea.pack_start(self._notebook, False, False, 4)
[831]147
[220]148 dataTab = self._buildDataTab()
[221]149 label = gtk.Label(xstr("pirepView_tab_data"))
150 label.set_use_underline(True)
151 label.set_tooltip_text(xstr("pirepView_tab_data_tooltip"))
152 self._notebook.append_page(dataTab, label)
[831]153
[221]154 commentsTab = self._buildCommentsTab()
155 label = gtk.Label(xstr("pirepView_tab_comments"))
156 label.set_use_underline(True)
157 label.set_tooltip_text(xstr("pirepView_tab_comments_tooltip"))
158 self._notebook.append_page(commentsTab, label)
[831]159
[221]160 logTab = self._buildLogTab()
161 label = gtk.Label(xstr("pirepView_tab_log"))
162 label.set_use_underline(True)
163 label.set_tooltip_text(xstr("pirepView_tab_log_tooltip"))
164 self._notebook.append_page(logTab, label)
[224]165
166 self._okButton = self.add_button(xstr("button_ok"), RESPONSETYPE_OK)
167 self._okButton.set_can_default(True)
[831]168
[220]169 def setPIREP(self, pirep):
170 """Setup the data in the dialog from the given PIREP."""
171 bookedFlight = pirep.bookedFlight
172
173 self._callsign.set_text(bookedFlight.callsign)
174 self._tailNumber.set_text(bookedFlight.tailNumber)
175 aircraftType = xstr("aircraft_" + icaoCodes[bookedFlight.aircraftType].lower())
176 self._aircraftType.set_text(aircraftType)
[831]177
[220]178 self._departureICAO.set_text(bookedFlight.departureICAO)
179 self._departureTime.set_text("%02d:%02d" % \
180 (bookedFlight.departureTime.hour,
181 bookedFlight.departureTime.minute))
182
183 self._arrivalICAO.set_text(bookedFlight.arrivalICAO)
184 self._arrivalTime.set_text("%02d:%02d" % \
185 (bookedFlight.arrivalTime.hour,
186 bookedFlight.arrivalTime.minute))
187
188 self._numPassengers.set_text(str(bookedFlight.numPassengers))
189 self._numCrew.set_text(str(bookedFlight.numCrew))
190 self._bagWeight.set_text(str(bookedFlight.bagWeight))
191 self._cargoWeight.set_text(str(bookedFlight.cargoWeight))
192 self._mailWeight.set_text(str(bookedFlight.mailWeight))
[831]193
[220]194 self._route.get_buffer().set_text(bookedFlight.route)
195
196 self._filedCruiseLevel.set_text("FL" + str(pirep.filedCruiseAltitude/100))
197
198 if pirep.cruiseAltitude != pirep.filedCruiseAltitude:
199 self._modifiedCruiseLevel.set_text("FL" + str(pirep.cruiseAltitude/100))
200 else:
201 self._modifiedCruiseLevel.set_text("-")
202
203 self._userRoute.get_buffer().set_text(pirep.route)
204
205 self._departureMETAR.get_buffer().set_text(pirep.departureMETAR)
206
207 self._arrivalMETAR.get_buffer().set_text(pirep.arrivalMETAR)
208 self._departureRunway.set_text(pirep.departureRunway)
209 self._sid.set_text(pirep.sid)
210
211 self._star.set_text("-" if pirep.star is None else pirep.star)
212 self._transition.set_text("-" if pirep.transition is None else pirep.transition)
213 self._approachType.set_text(pirep.approachType)
214 self._arrivalRunway.set_text(pirep.arrivalRunway)
215
216 PIREPViewer.timestamp2text(self._blockTimeStart, pirep.blockTimeStart)
217 PIREPViewer.timestamp2text(self._blockTimeEnd, pirep.blockTimeEnd)
218 PIREPViewer.timestamp2text(self._flightTimeStart, pirep.flightTimeStart)
219 PIREPViewer.timestamp2text(self._flightTimeEnd, pirep.flightTimeEnd)
[831]220
[220]221 self._flownDistance.set_text("%.1f" % (pirep.flownDistance,))
222 self._fuelUsed.set_text("%.0f" % (pirep.fuelUsed,))
223
224 rating = pirep.rating
225 if rating<0:
226 self._rating.set_markup('<b><span foreground="red">NO GO</span></b>')
227 else:
228 self._rating.set_text("%.1f %%" % (rating,))
229
[303]230 self._flownNumCrew.set_text("%d" % (pirep.numCrew,))
231 self._flownNumPassengers.set_text("%d" % (pirep.numPassengers,))
232 self._flownBagWeight.set_text("%.0f" % (pirep.bagWeight,))
[223]233 self._flownCargoWeight.set_text("%.0f" % (pirep.cargoWeight,))
[303]234 self._flownMailWeight.set_text("%.0f" % (pirep.mailWeight,))
[831]235 self._flightType.set_text(xstr("flighttype_" +
[220]236 flightType2string(pirep.flightType)))
237 self._online.set_text(xstr("pirepView_" +
238 ("yes" if pirep.online else "no")))
239
240 delayCodes = ""
241 for code in pirep.delayCodes:
242 if delayCodes: delayCodes += ", "
[437]243 delayCodes += code
[831]244
245 self._delayCodes.get_buffer().set_text(delayCodes)
[221]246
247 self._comments.get_buffer().set_text(pirep.comments)
248 self._flightDefects.get_buffer().set_text(pirep.flightDefects)
249
250 logBuffer = self._log.get_buffer()
251 logBuffer.set_text("")
[225]252 lineIndex = 0
[221]253 for (timeStr, line) in pirep.logLines:
[225]254 isFault = lineIndex in pirep.faultLineIndexes
[226]255 appendTextBuffer(logBuffer,
256 formatFlightLogLine(timeStr, line),
257 isFault = isFault)
[225]258 lineIndex += 1
[221]259
260 self._notebook.set_current_page(0)
[224]261 self._okButton.grab_default()
[220]262
263 def _buildDataTab(self):
264 """Build the data tab of the viewer."""
265 table = gtk.Table(1, 2)
266 table.set_row_spacings(4)
267 table.set_col_spacings(16)
268 table.set_homogeneous(True)
269
270 box1 = gtk.VBox()
271 table.attach(box1, 0, 1, 0, 1)
[831]272
[220]273 box2 = gtk.VBox()
274 table.attach(box2, 1, 2, 0, 1)
[831]275
[220]276 flightFrame = self._buildFlightFrame()
277 box1.pack_start(flightFrame, False, False, 4)
278
279 routeFrame = self._buildRouteFrame()
280 box1.pack_start(routeFrame, False, False, 4)
281
282 departureFrame = self._buildDepartureFrame()
283 box2.pack_start(departureFrame, True, True, 4)
284
285 arrivalFrame = self._buildArrivalFrame()
286 box2.pack_start(arrivalFrame, True, True, 4)
287
288 statisticsFrame = self._buildStatisticsFrame()
289 box2.pack_start(statisticsFrame, False, False, 4)
290
291 miscellaneousFrame = self._buildMiscellaneousFrame()
292 box1.pack_start(miscellaneousFrame, False, False, 4)
293
294 return table
295
296 def _buildFlightFrame(self):
297 """Build the frame for the flight data."""
[831]298
[220]299 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_flight"))
[831]300
[220]301 dataBox = gtk.HBox()
302 mainBox.pack_start(dataBox, False, False, 0)
[831]303
[220]304 self._callsign = \
305 PIREPViewer.addLabeledData(dataBox,
306 xstr("pirepView_callsign"),
307 width = 8)
308
309 self._tailNumber = \
310 PIREPViewer.addLabeledData(dataBox,
311 xstr("pirepView_tailNumber"),
312 width = 7)
313
314 PIREPViewer.addVFiller(mainBox)
315
316 dataBox = gtk.HBox()
317 mainBox.pack_start(dataBox, False, False, 0)
318
319 self._aircraftType = \
320 PIREPViewer.addLabeledData(dataBox,
321 xstr("pirepView_aircraftType"),
322 width = 25)
323
324 PIREPViewer.addVFiller(mainBox)
325
326 table = gtk.Table(3, 2)
327 mainBox.pack_start(table, False, False, 0)
328 table.set_row_spacings(4)
[831]329 table.set_col_spacings(8)
[220]330
331 self._departureICAO = \
332 PIREPViewer.tableAttach(table, 0, 0,
333 xstr("pirepView_departure"),
334 width = 5)
335
336 self._departureTime = \
337 PIREPViewer.tableAttach(table, 1, 0,
338 xstr("pirepView_departure_time"),
339 width = 6)
340
341 self._arrivalICAO = \
342 PIREPViewer.tableAttach(table, 0, 1,
343 xstr("pirepView_arrival"),
344 width = 5)
345
346 self._arrivalTime = \
347 PIREPViewer.tableAttach(table, 1, 1,
348 xstr("pirepView_arrival_time"),
349 width = 6)
350
351 table = gtk.Table(3, 2)
352 mainBox.pack_start(table, False, False, 0)
353 table.set_row_spacings(4)
[831]354 table.set_col_spacings(8)
[220]355
356 self._numPassengers = \
357 PIREPViewer.tableAttach(table, 0, 0,
358 xstr("pirepView_numPassengers"),
359 width = 4)
360
361 self._numCrew = \
362 PIREPViewer.tableAttach(table, 1, 0,
363 xstr("pirepView_numCrew"),
364 width = 3)
365
366 self._bagWeight = \
[831]367 PIREPViewer.tableAttach(table, 0, 1,
[220]368 xstr("pirepView_bagWeight"),
369 width = 5)
370
371 self._cargoWeight = \
[831]372 PIREPViewer.tableAttach(table, 1, 1,
[220]373 xstr("pirepView_cargoWeight"),
374 width = 5)
375
376 self._mailWeight = \
[831]377 PIREPViewer.tableAttach(table, 2, 1,
[220]378 xstr("pirepView_mailWeight"),
379 width = 5)
[831]380
[220]381 PIREPViewer.addVFiller(mainBox)
382
383 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_route")),
384 False, False, 0)
[831]385
[220]386 (routeWindow, self._route) = PIREPViewer.getTextWindow()
387 mainBox.pack_start(routeWindow, False, False, 0)
388
389 return frame
390
391 def _buildRouteFrame(self):
392 """Build the frame for the user-specified route and flight
393 level."""
[831]394
[220]395 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_route"))
396
397 levelBox = gtk.HBox()
398 mainBox.pack_start(levelBox, False, False, 0)
[831]399
[220]400 self._filedCruiseLevel = \
[831]401 PIREPViewer.addLabeledData(levelBox,
[220]402 xstr("pirepView_filedCruiseLevel"),
403 width = 6)
404
405 self._modifiedCruiseLevel = \
406 PIREPViewer.addLabeledData(levelBox,
407 xstr("pirepView_modifiedCruiseLevel"),
408 width = 6)
409
410 PIREPViewer.addVFiller(mainBox)
411
412 (routeWindow, self._userRoute) = PIREPViewer.getTextWindow()
413 mainBox.pack_start(routeWindow, False, False, 0)
414
415 return frame
416
417 def _buildDepartureFrame(self):
[831]418 """Build the frame for the departure data."""
[220]419 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_departure"))
420
421 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
422 False, False, 0)
423 (metarWindow, self._departureMETAR) = \
424 PIREPViewer.getTextWindow(heightRequest = -1)
425 mainBox.pack_start(metarWindow, True, True, 0)
426
427 PIREPViewer.addVFiller(mainBox)
428
429 dataBox = gtk.HBox()
430 mainBox.pack_start(dataBox, False, False, 0)
[831]431
[220]432 self._departureRunway = \
433 PIREPViewer.addLabeledData(dataBox,
434 xstr("pirepView_runway"),
435 width = 5)
436
437 self._sid = \
438 PIREPViewer.addLabeledData(dataBox,
439 xstr("pirepView_sid"),
440 width = 12)
441
442 return frame
[831]443
[220]444 def _buildArrivalFrame(self):
[831]445 """Build the frame for the arrival data."""
[220]446 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_arrival"))
447
448 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
449 False, False, 0)
450 (metarWindow, self._arrivalMETAR) = \
451 PIREPViewer.getTextWindow(heightRequest = -1)
452 mainBox.pack_start(metarWindow, True, True, 0)
453
454 PIREPViewer.addVFiller(mainBox)
455
456 table = gtk.Table(2, 2)
457 mainBox.pack_start(table, False, False, 0)
458 table.set_row_spacings(4)
[831]459 table.set_col_spacings(8)
[220]460
461 self._star = \
462 PIREPViewer.tableAttach(table, 0, 0,
463 xstr("pirepView_star"),
464 width = 12)
465
466 self._transition = \
467 PIREPViewer.tableAttach(table, 1, 0,
468 xstr("pirepView_transition"),
469 width = 12)
[831]470
[220]471 self._approachType = \
472 PIREPViewer.tableAttach(table, 0, 1,
473 xstr("pirepView_approachType"),
474 width = 7)
[831]475
[220]476 self._arrivalRunway = \
[831]477 PIREPViewer.tableAttach(table, 1, 1,
[220]478 xstr("pirepView_runway"),
479 width = 5)
[831]480
[220]481 return frame
482
483 def _buildStatisticsFrame(self):
[831]484 """Build the frame for the statistics data."""
[220]485 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_statistics"))
486
487 table = gtk.Table(4, 2)
488 mainBox.pack_start(table, False, False, 0)
489 table.set_row_spacings(4)
490 table.set_col_spacings(8)
[221]491 table.set_homogeneous(False)
[831]492
[220]493 self._blockTimeStart = \
494 PIREPViewer.tableAttach(table, 0, 0,
495 xstr("pirepView_blockTimeStart"),
496 width = 6)
[831]497
[220]498 self._blockTimeEnd = \
499 PIREPViewer.tableAttach(table, 1, 0,
500 xstr("pirepView_blockTimeEnd"),
501 width = 8)
502
503 self._flightTimeStart = \
504 PIREPViewer.tableAttach(table, 0, 1,
505 xstr("pirepView_flightTimeStart"),
506 width = 6)
[831]507
[220]508 self._flightTimeEnd = \
[831]509 PIREPViewer.tableAttach(table, 1, 1,
[220]510 xstr("pirepView_flightTimeEnd"),
511 width = 6)
512
513 self._flownDistance = \
514 PIREPViewer.tableAttach(table, 0, 2,
515 xstr("pirepView_flownDistance"),
516 width = 8)
[831]517
[220]518 self._fuelUsed = \
519 PIREPViewer.tableAttach(table, 1, 2,
520 xstr("pirepView_fuelUsed"),
521 width = 6)
[831]522
[220]523 self._rating = \
524 PIREPViewer.tableAttach(table, 0, 3,
525 xstr("pirepView_rating"),
526 width = 7)
527 return frame
528
529 def _buildMiscellaneousFrame(self):
[831]530 """Build the frame for the miscellaneous data."""
[220]531 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_miscellaneous"))
[303]532
533 table = gtk.Table(3, 2)
534 mainBox.pack_start(table, False, False, 0)
535 table.set_row_spacings(4)
[831]536 table.set_col_spacings(8)
537
[303]538 self._flownNumPassengers = \
539 PIREPViewer.tableAttach(table, 0, 0,
540 xstr("pirepView_numPassengers"),
541 width = 4)
542
543 self._flownNumCrew = \
544 PIREPViewer.tableAttach(table, 1, 0,
545 xstr("pirepView_numCrew"),
546 width = 3)
547
548 self._flownBagWeight = \
549 PIREPViewer.tableAttach(table, 0, 1,
550 xstr("pirepView_bagWeight"),
551 width = 5)
552
[223]553 self._flownCargoWeight = \
[303]554 PIREPViewer.tableAttach(table, 1, 1,
555 xstr("pirepView_cargoWeight"),
556 width = 6)
557
558 self._flownMailWeight = \
559 PIREPViewer.tableAttach(table, 2, 1,
560 xstr("pirepView_mailWeight"),
561 width = 5)
[223]562
[220]563 self._flightType = \
[303]564 PIREPViewer.tableAttach(table, 0, 2,
565 xstr("pirepView_flightType"),
566 width = 15)
[831]567
[220]568 self._online = \
[303]569 PIREPViewer.tableAttach(table, 1, 2,
570 xstr("pirepView_online"),
571 width = 5)
[220]572
573 PIREPViewer.addVFiller(mainBox)
574
575 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_delayCodes")),
576 False, False, 0)
[831]577
[220]578 (textWindow, self._delayCodes) = PIREPViewer.getTextWindow()
579 mainBox.pack_start(textWindow, False, False, 0)
580
[831]581 return frame
[220]582
[221]583 def _buildCommentsTab(self):
584 """Build the tab with the comments and flight defects."""
585 table = gtk.Table(2, 1)
586 table.set_col_spacings(16)
587
588 (frame, commentsBox) = \
589 PIREPViewer.createFrame(xstr("pirepView_comments"))
590 table.attach(frame, 0, 1, 0, 1)
591
592 (commentsWindow, self._comments) = \
593 PIREPViewer.getTextWindow(heightRequest = -1)
594 commentsBox.pack_start(commentsWindow, True, True, 0)
595
596 (frame, flightDefectsBox) = \
597 PIREPViewer.createFrame(xstr("pirepView_flightDefects"))
598 table.attach(frame, 1, 2, 0, 1)
599
600 (flightDefectsWindow, self._flightDefects) = \
601 PIREPViewer.getTextWindow(heightRequest = -1)
602 flightDefectsBox.pack_start(flightDefectsWindow, True, True, 0)
[831]603
[221]604 return table
605
606 def _buildLogTab(self):
607 """Build the log tab."""
608 mainBox = gtk.VBox()
609
610 (logWindow, self._log) = PIREPViewer.getTextWindow(heightRequest = -1)
[226]611 addFaultTag(self._log.get_buffer())
[221]612 mainBox.pack_start(logWindow, True, True, 0)
[831]613
[221]614 return mainBox
[831]615
[220]616#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.