source: src/mlx/gui/pirep.py@ 302:a4e4cda5d89a

Last change on this file since 302:a4e4cda5d89a was 300:f101bd18f39d, checked in by István Váradi <ivaradi@…>, 12 years ago

Added the module comments for the GUI

File size: 21.6 KB
Line 
1
2from common import *
3
4from mlx.pirep import PIREP
5from mlx.const import *
6
7import time
8
9#------------------------------------------------------------------------------
10
11## @package mlx.gui.pirep
12#
13# The detailed PIREP viewer.
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
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
31 contents.
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)
45
46 return (frame, box)
47
48 @staticmethod
49 def getLabel(text):
50 """Get a bold label with the given text."""
51 label = gtk.Label("<b>" + text + "</b>")
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
66 def getTextWindow(heightRequest = 40):
67 """Get a scrollable text window.
68
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)
78 textView.set_editable(False)
79 textView.set_cursor_visible(False)
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
89 table.
90
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)
97
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.
107
108 Returnsd the data label."""
109 label = PIREPViewer.getLabel(labelText)
110 hBox.pack_start(label, False, False, 0)
111
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):
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)
122 filler.set_size_request(-1, height)
123 vBox.pack_start(filler, False, False, 0)
124
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)
138
139 self.set_resizable(False)
140
141 self._gui = gui
142
143 contentArea = self.get_content_area()
144
145 self._notebook = gtk.Notebook()
146 contentArea.pack_start(self._notebook, False, False, 4)
147
148 dataTab = self._buildDataTab()
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)
153
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)
159
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)
165
166 self._okButton = self.add_button(xstr("button_ok"), RESPONSETYPE_OK)
167 self._okButton.set_can_default(True)
168
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)
177
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))
193
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)
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
230 self._flownCargoWeight.set_text("%.0f" % (pirep.cargoWeight,))
231 self._flightType.set_text(xstr("flighttype_" +
232 flightType2string(pirep.flightType)))
233 self._online.set_text(xstr("pirepView_" +
234 ("yes" if pirep.online else "no")))
235
236 delayCodes = ""
237 for code in pirep.delayCodes:
238 if delayCodes: delayCodes += ", "
239 delayCodes += PIREP.delayCodeNames[code]
240
241 self._delayCodes.get_buffer().set_text(delayCodes)
242
243 self._comments.get_buffer().set_text(pirep.comments)
244 self._flightDefects.get_buffer().set_text(pirep.flightDefects)
245
246 logBuffer = self._log.get_buffer()
247 logBuffer.set_text("")
248 lineIndex = 0
249 for (timeStr, line) in pirep.logLines:
250 isFault = lineIndex in pirep.faultLineIndexes
251 appendTextBuffer(logBuffer,
252 formatFlightLogLine(timeStr, line),
253 isFault = isFault)
254 lineIndex += 1
255
256 self._notebook.set_current_page(0)
257 self._okButton.grab_default()
258
259 def _buildDataTab(self):
260 """Build the data tab of the viewer."""
261 table = gtk.Table(1, 2)
262 table.set_row_spacings(4)
263 table.set_col_spacings(16)
264 table.set_homogeneous(True)
265
266 box1 = gtk.VBox()
267 table.attach(box1, 0, 1, 0, 1)
268
269 box2 = gtk.VBox()
270 table.attach(box2, 1, 2, 0, 1)
271
272 flightFrame = self._buildFlightFrame()
273 box1.pack_start(flightFrame, False, False, 4)
274
275 routeFrame = self._buildRouteFrame()
276 box1.pack_start(routeFrame, False, False, 4)
277
278 departureFrame = self._buildDepartureFrame()
279 box2.pack_start(departureFrame, True, True, 4)
280
281 arrivalFrame = self._buildArrivalFrame()
282 box2.pack_start(arrivalFrame, True, True, 4)
283
284 statisticsFrame = self._buildStatisticsFrame()
285 box2.pack_start(statisticsFrame, False, False, 4)
286
287 miscellaneousFrame = self._buildMiscellaneousFrame()
288 box1.pack_start(miscellaneousFrame, False, False, 4)
289
290 return table
291
292 def _buildFlightFrame(self):
293 """Build the frame for the flight data."""
294
295 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_flight"))
296
297 dataBox = gtk.HBox()
298 mainBox.pack_start(dataBox, False, False, 0)
299
300 self._callsign = \
301 PIREPViewer.addLabeledData(dataBox,
302 xstr("pirepView_callsign"),
303 width = 8)
304
305 self._tailNumber = \
306 PIREPViewer.addLabeledData(dataBox,
307 xstr("pirepView_tailNumber"),
308 width = 7)
309
310 PIREPViewer.addVFiller(mainBox)
311
312 dataBox = gtk.HBox()
313 mainBox.pack_start(dataBox, False, False, 0)
314
315 self._aircraftType = \
316 PIREPViewer.addLabeledData(dataBox,
317 xstr("pirepView_aircraftType"),
318 width = 25)
319
320 PIREPViewer.addVFiller(mainBox)
321
322 table = gtk.Table(3, 2)
323 mainBox.pack_start(table, False, False, 0)
324 table.set_row_spacings(4)
325 table.set_col_spacings(8)
326
327 self._departureICAO = \
328 PIREPViewer.tableAttach(table, 0, 0,
329 xstr("pirepView_departure"),
330 width = 5)
331
332 self._departureTime = \
333 PIREPViewer.tableAttach(table, 1, 0,
334 xstr("pirepView_departure_time"),
335 width = 6)
336
337 self._arrivalICAO = \
338 PIREPViewer.tableAttach(table, 0, 1,
339 xstr("pirepView_arrival"),
340 width = 5)
341
342 self._arrivalTime = \
343 PIREPViewer.tableAttach(table, 1, 1,
344 xstr("pirepView_arrival_time"),
345 width = 6)
346
347 table = gtk.Table(3, 2)
348 mainBox.pack_start(table, False, False, 0)
349 table.set_row_spacings(4)
350 table.set_col_spacings(8)
351
352 self._numPassengers = \
353 PIREPViewer.tableAttach(table, 0, 0,
354 xstr("pirepView_numPassengers"),
355 width = 4)
356
357 self._numCrew = \
358 PIREPViewer.tableAttach(table, 1, 0,
359 xstr("pirepView_numCrew"),
360 width = 3)
361
362 self._bagWeight = \
363 PIREPViewer.tableAttach(table, 0, 1,
364 xstr("pirepView_bagWeight"),
365 width = 5)
366
367 self._cargoWeight = \
368 PIREPViewer.tableAttach(table, 1, 1,
369 xstr("pirepView_cargoWeight"),
370 width = 5)
371
372 self._mailWeight = \
373 PIREPViewer.tableAttach(table, 2, 1,
374 xstr("pirepView_mailWeight"),
375 width = 5)
376
377 PIREPViewer.addVFiller(mainBox)
378
379 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_route")),
380 False, False, 0)
381
382 (routeWindow, self._route) = PIREPViewer.getTextWindow()
383 mainBox.pack_start(routeWindow, False, False, 0)
384
385 return frame
386
387 def _buildRouteFrame(self):
388 """Build the frame for the user-specified route and flight
389 level."""
390
391 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_route"))
392
393 levelBox = gtk.HBox()
394 mainBox.pack_start(levelBox, False, False, 0)
395
396 self._filedCruiseLevel = \
397 PIREPViewer.addLabeledData(levelBox,
398 xstr("pirepView_filedCruiseLevel"),
399 width = 6)
400
401 self._modifiedCruiseLevel = \
402 PIREPViewer.addLabeledData(levelBox,
403 xstr("pirepView_modifiedCruiseLevel"),
404 width = 6)
405
406 PIREPViewer.addVFiller(mainBox)
407
408 (routeWindow, self._userRoute) = PIREPViewer.getTextWindow()
409 mainBox.pack_start(routeWindow, False, False, 0)
410
411 return frame
412
413 def _buildDepartureFrame(self):
414 """Build the frame for the departure data."""
415 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_departure"))
416
417 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
418 False, False, 0)
419 (metarWindow, self._departureMETAR) = \
420 PIREPViewer.getTextWindow(heightRequest = -1)
421 mainBox.pack_start(metarWindow, True, True, 0)
422
423 PIREPViewer.addVFiller(mainBox)
424
425 dataBox = gtk.HBox()
426 mainBox.pack_start(dataBox, False, False, 0)
427
428 self._departureRunway = \
429 PIREPViewer.addLabeledData(dataBox,
430 xstr("pirepView_runway"),
431 width = 5)
432
433 self._sid = \
434 PIREPViewer.addLabeledData(dataBox,
435 xstr("pirepView_sid"),
436 width = 12)
437
438 return frame
439
440 def _buildArrivalFrame(self):
441 """Build the frame for the arrival data."""
442 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_arrival"))
443
444 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
445 False, False, 0)
446 (metarWindow, self._arrivalMETAR) = \
447 PIREPViewer.getTextWindow(heightRequest = -1)
448 mainBox.pack_start(metarWindow, True, True, 0)
449
450 PIREPViewer.addVFiller(mainBox)
451
452 table = gtk.Table(2, 2)
453 mainBox.pack_start(table, False, False, 0)
454 table.set_row_spacings(4)
455 table.set_col_spacings(8)
456
457 self._star = \
458 PIREPViewer.tableAttach(table, 0, 0,
459 xstr("pirepView_star"),
460 width = 12)
461
462 self._transition = \
463 PIREPViewer.tableAttach(table, 1, 0,
464 xstr("pirepView_transition"),
465 width = 12)
466
467 self._approachType = \
468 PIREPViewer.tableAttach(table, 0, 1,
469 xstr("pirepView_approachType"),
470 width = 7)
471
472 self._arrivalRunway = \
473 PIREPViewer.tableAttach(table, 1, 1,
474 xstr("pirepView_runway"),
475 width = 5)
476
477 return frame
478
479 def _buildStatisticsFrame(self):
480 """Build the frame for the statistics data."""
481 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_statistics"))
482
483 table = gtk.Table(4, 2)
484 mainBox.pack_start(table, False, False, 0)
485 table.set_row_spacings(4)
486 table.set_col_spacings(8)
487 table.set_homogeneous(False)
488
489 self._blockTimeStart = \
490 PIREPViewer.tableAttach(table, 0, 0,
491 xstr("pirepView_blockTimeStart"),
492 width = 6)
493
494 self._blockTimeEnd = \
495 PIREPViewer.tableAttach(table, 1, 0,
496 xstr("pirepView_blockTimeEnd"),
497 width = 8)
498
499 self._flightTimeStart = \
500 PIREPViewer.tableAttach(table, 0, 1,
501 xstr("pirepView_flightTimeStart"),
502 width = 6)
503
504 self._flightTimeEnd = \
505 PIREPViewer.tableAttach(table, 1, 1,
506 xstr("pirepView_flightTimeEnd"),
507 width = 6)
508
509 self._flownDistance = \
510 PIREPViewer.tableAttach(table, 0, 2,
511 xstr("pirepView_flownDistance"),
512 width = 8)
513
514 self._fuelUsed = \
515 PIREPViewer.tableAttach(table, 1, 2,
516 xstr("pirepView_fuelUsed"),
517 width = 6)
518
519 self._rating = \
520 PIREPViewer.tableAttach(table, 0, 3,
521 xstr("pirepView_rating"),
522 width = 7)
523 return frame
524
525 def _buildMiscellaneousFrame(self):
526 """Build the frame for the miscellaneous data."""
527 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_miscellaneous"))
528
529 dataBox = gtk.HBox()
530 mainBox.pack_start(dataBox, False, False, 0)
531
532 self._flownCargoWeight = \
533 PIREPViewer.addLabeledData(dataBox,
534 xstr("pirepView_cargoWeight"),
535 width = 6)
536
537 self._flightType = \
538 PIREPViewer.addLabeledData(dataBox,
539 xstr("pirepView_flightType"),
540 width = 15)
541
542 self._online = \
543 PIREPViewer.addLabeledData(dataBox,
544 xstr("pirepView_online"),
545 width = 5)
546
547 PIREPViewer.addVFiller(mainBox)
548
549 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_delayCodes")),
550 False, False, 0)
551
552 (textWindow, self._delayCodes) = PIREPViewer.getTextWindow()
553 mainBox.pack_start(textWindow, False, False, 0)
554
555 return frame
556
557 def _buildCommentsTab(self):
558 """Build the tab with the comments and flight defects."""
559 table = gtk.Table(2, 1)
560 table.set_col_spacings(16)
561
562 (frame, commentsBox) = \
563 PIREPViewer.createFrame(xstr("pirepView_comments"))
564 table.attach(frame, 0, 1, 0, 1)
565
566 (commentsWindow, self._comments) = \
567 PIREPViewer.getTextWindow(heightRequest = -1)
568 commentsBox.pack_start(commentsWindow, True, True, 0)
569
570 (frame, flightDefectsBox) = \
571 PIREPViewer.createFrame(xstr("pirepView_flightDefects"))
572 table.attach(frame, 1, 2, 0, 1)
573
574 (flightDefectsWindow, self._flightDefects) = \
575 PIREPViewer.getTextWindow(heightRequest = -1)
576 flightDefectsBox.pack_start(flightDefectsWindow, True, True, 0)
577
578 return table
579
580 def _buildLogTab(self):
581 """Build the log tab."""
582 mainBox = gtk.VBox()
583
584 (logWindow, self._log) = PIREPViewer.getTextWindow(heightRequest = -1)
585 addFaultTag(self._log.get_buffer())
586 mainBox.pack_start(logWindow, True, True, 0)
587
588 return mainBox
589
590#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.