source: src/mlx/gui/pirep.py@ 227:50c3ae93007d

Last change on this file since 227:50c3ae93007d was 226:473bbc9d355f, checked in by István Váradi <ivaradi@…>, 12 years ago

Faults are logged highlighted

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