source: src/mlx/gui/pirep.py@ 249:d055e454a7ea

Last change on this file since 249:d055e454a7ea was 238:022e80d18d2c, checked in by István Váradi <ivaradi@…>, 12 years ago

Minor cosmetic changes to the PIREP viewer

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