source: src/mlx/gui/pirep.py@ 854:3e7dca86c1ed

Last change on this file since 854:3e7dca86c1ed was 853:28eb49544c0f, checked in by István Váradi <ivaradi@…>, 7 years ago

PIREP modifications can be saved (re #307)

File size: 54.9 KB
RevLine 
[220]1
2from common import *
[845]3from dcdata import getTable
4from info import FlightInfo
5from flight import comboModel
[220]6
[236]7from mlx.pirep import PIREP
[846]8from mlx.flight import Flight
[220]9from mlx.const import *
10
11import time
[845]12import re
[220]13
14#------------------------------------------------------------------------------
15
[300]16## @package mlx.gui.pirep
17#
[845]18# The detailed PIREP viewer and editor windows.
[300]19#
20# The \ref PIREPViewer class is a dialog displaying all information found in a
21# PIREP. It consists of three tabs. The Data tab displays the simple,
22# itemizable data. The Comments & defects tab contains the flight comments and
23# defects, while the Log tab contains the flight log collected by the
24# \ref mlx.logger.Logger "logger".
25
26#------------------------------------------------------------------------------
27
[220]28class PIREPViewer(gtk.Dialog):
29 """The dialog for PIREP viewing."""
30 @staticmethod
31 def createFrame(label):
32 """Create a frame with the given label.
33
34 The frame will contain an alignment to properly distance the
35 insides. The alignment will contain a VBox to contain the real
[831]36 contents.
[220]37
38 The function returns a tuple with the following items:
39 - the frame,
40 - the inner VBox."""
41 frame = gtk.Frame(label = label)
42
43 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
44 xscale = 1.0, yscale = 1.0)
45 frame.add(alignment)
46 alignment.set_padding(padding_top = 4, padding_bottom = 4,
47 padding_left = 4, padding_right = 4)
48 box = gtk.VBox()
49 alignment.add(box)
[831]50
[220]51 return (frame, box)
52
53 @staticmethod
[845]54 def getLabel(text, extraText = ""):
[220]55 """Get a bold label with the given text."""
[845]56 label = gtk.Label("<b>" + text + "</b>" + extraText)
[220]57 label.set_use_markup(True)
58 label.set_alignment(0.0, 0.5)
59 return label
60
61 @staticmethod
62 def getDataLabel(width = None, xAlignment = 0.0):
63 """Get a bold label with the given text."""
64 label = gtk.Label()
65 if width is not None:
66 label.set_width_chars(width)
67 label.set_alignment(xAlignment, 0.5)
68 return label
69
70 @staticmethod
[845]71 def getTextWindow(heightRequest = 40, editable = False):
[220]72 """Get a scrollable text window.
[831]73
[220]74 Returns a tuple of the following items:
75 - the window,
76 - the text view."""
77 scrolledWindow = gtk.ScrolledWindow()
78 scrolledWindow.set_shadow_type(SHADOW_IN)
79 scrolledWindow.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
80
81 textView = gtk.TextView()
82 textView.set_wrap_mode(WRAP_WORD)
[845]83 textView.set_editable(editable)
84 textView.set_cursor_visible(editable)
[220]85 textView.set_size_request(-1, heightRequest)
86 scrolledWindow.add(textView)
87
88 return (scrolledWindow, textView)
89
90 @staticmethod
91 def tableAttach(table, column, row, labelText, width = None,
92 dataLabelXAlignment = 0.0):
93 """Attach a labeled data to the given column and row of the
[831]94 table.
95
[220]96 If width is given, that will be the width of the data
97 label.
98
99 Returns the data label attached."""
100 dataBox = gtk.HBox()
101 table.attach(dataBox, column, column+1, row, row+1)
[831]102
[220]103 dataLabel = PIREPViewer.addLabeledData(dataBox, labelText,
104 width = width)
105 dataLabel.set_alignment(dataLabelXAlignment, 0.5)
106
107 return dataLabel
108
109 @staticmethod
110 def addLabeledData(hBox, labelText, width = None, dataPadding = 8):
111 """Add a label and a data label to the given HBox.
[831]112
[845]113 Returns the data label."""
[220]114 label = PIREPViewer.getLabel(labelText)
115 hBox.pack_start(label, False, False, 0)
[831]116
[220]117 dataLabel = PIREPViewer.getDataLabel(width = width)
118 hBox.pack_start(dataLabel, False, False, dataPadding)
119
120 return dataLabel
121
122 @staticmethod
[845]123 def addHFiller(hBox, width = 8):
124 """Add a filler to the given horizontal box."""
125 filler = gtk.Alignment(xalign = 0.0, yalign = 0.0,
126 xscale = 1.0, yscale = 1.0)
127 filler.set_size_request(width, -1)
128 hBox.pack_start(filler, False, False, 0)
129
130 @staticmethod
[220]131 def addVFiller(vBox, height = 4):
[238]132 """Add a filler to the given vertical box."""
133 filler = gtk.Alignment(xalign = 0.0, yalign = 0.0,
134 xscale = 1.0, yscale = 1.0)
[220]135 filler.set_size_request(-1, height)
136 vBox.pack_start(filler, False, False, 0)
[831]137
[220]138 @staticmethod
139 def timestamp2text(label, timestamp):
140 """Convert the given timestamp into a text containing the hour
141 and minute in UTC and put that text into the given label."""
142 tm = time.gmtime(timestamp)
143 label.set_text("%02d:%02d" % (tm.tm_hour, tm.tm_min))
144
145 def __init__(self, gui):
146 """Construct the PIREP viewer."""
147 super(PIREPViewer, self).__init__(title = WINDOW_TITLE_BASE +
148 " - " +
149 xstr("pirepView_title"),
150 parent = gui.mainWindow)
[831]151
[220]152 self.set_resizable(False)
153
154 self._gui = gui
[831]155
[220]156 contentArea = self.get_content_area()
[221]157
158 self._notebook = gtk.Notebook()
159 contentArea.pack_start(self._notebook, False, False, 4)
[831]160
[220]161 dataTab = self._buildDataTab()
[221]162 label = gtk.Label(xstr("pirepView_tab_data"))
163 label.set_use_underline(True)
164 label.set_tooltip_text(xstr("pirepView_tab_data_tooltip"))
165 self._notebook.append_page(dataTab, label)
[831]166
[221]167 commentsTab = self._buildCommentsTab()
168 label = gtk.Label(xstr("pirepView_tab_comments"))
169 label.set_use_underline(True)
170 label.set_tooltip_text(xstr("pirepView_tab_comments_tooltip"))
171 self._notebook.append_page(commentsTab, label)
[831]172
[221]173 logTab = self._buildLogTab()
174 label = gtk.Label(xstr("pirepView_tab_log"))
175 label.set_use_underline(True)
176 label.set_tooltip_text(xstr("pirepView_tab_log_tooltip"))
177 self._notebook.append_page(logTab, label)
[224]178
179 self._okButton = self.add_button(xstr("button_ok"), RESPONSETYPE_OK)
180 self._okButton.set_can_default(True)
[831]181
[220]182 def setPIREP(self, pirep):
183 """Setup the data in the dialog from the given PIREP."""
184 bookedFlight = pirep.bookedFlight
185
186 self._callsign.set_text(bookedFlight.callsign)
187 self._tailNumber.set_text(bookedFlight.tailNumber)
188 aircraftType = xstr("aircraft_" + icaoCodes[bookedFlight.aircraftType].lower())
189 self._aircraftType.set_text(aircraftType)
[831]190
[220]191 self._departureICAO.set_text(bookedFlight.departureICAO)
192 self._departureTime.set_text("%02d:%02d" % \
193 (bookedFlight.departureTime.hour,
194 bookedFlight.departureTime.minute))
195
196 self._arrivalICAO.set_text(bookedFlight.arrivalICAO)
197 self._arrivalTime.set_text("%02d:%02d" % \
198 (bookedFlight.arrivalTime.hour,
199 bookedFlight.arrivalTime.minute))
200
201 self._numPassengers.set_text(str(bookedFlight.numPassengers))
202 self._numCrew.set_text(str(bookedFlight.numCrew))
203 self._bagWeight.set_text(str(bookedFlight.bagWeight))
204 self._cargoWeight.set_text(str(bookedFlight.cargoWeight))
205 self._mailWeight.set_text(str(bookedFlight.mailWeight))
[831]206
[220]207 self._route.get_buffer().set_text(bookedFlight.route)
208
209 self._filedCruiseLevel.set_text("FL" + str(pirep.filedCruiseAltitude/100))
210
211 if pirep.cruiseAltitude != pirep.filedCruiseAltitude:
212 self._modifiedCruiseLevel.set_text("FL" + str(pirep.cruiseAltitude/100))
213 else:
214 self._modifiedCruiseLevel.set_text("-")
215
216 self._userRoute.get_buffer().set_text(pirep.route)
217
218 self._departureMETAR.get_buffer().set_text(pirep.departureMETAR)
219
220 self._arrivalMETAR.get_buffer().set_text(pirep.arrivalMETAR)
221 self._departureRunway.set_text(pirep.departureRunway)
222 self._sid.set_text(pirep.sid)
223
224 self._star.set_text("-" if pirep.star is None else pirep.star)
225 self._transition.set_text("-" if pirep.transition is None else pirep.transition)
226 self._approachType.set_text(pirep.approachType)
227 self._arrivalRunway.set_text(pirep.arrivalRunway)
228
229 PIREPViewer.timestamp2text(self._blockTimeStart, pirep.blockTimeStart)
230 PIREPViewer.timestamp2text(self._blockTimeEnd, pirep.blockTimeEnd)
231 PIREPViewer.timestamp2text(self._flightTimeStart, pirep.flightTimeStart)
232 PIREPViewer.timestamp2text(self._flightTimeEnd, pirep.flightTimeEnd)
[831]233
[220]234 self._flownDistance.set_text("%.1f" % (pirep.flownDistance,))
235 self._fuelUsed.set_text("%.0f" % (pirep.fuelUsed,))
236
237 rating = pirep.rating
238 if rating<0:
239 self._rating.set_markup('<b><span foreground="red">NO GO</span></b>')
240 else:
241 self._rating.set_text("%.1f %%" % (rating,))
242
[303]243 self._flownNumCrew.set_text("%d" % (pirep.numCrew,))
244 self._flownNumPassengers.set_text("%d" % (pirep.numPassengers,))
245 self._flownBagWeight.set_text("%.0f" % (pirep.bagWeight,))
[223]246 self._flownCargoWeight.set_text("%.0f" % (pirep.cargoWeight,))
[303]247 self._flownMailWeight.set_text("%.0f" % (pirep.mailWeight,))
[831]248 self._flightType.set_text(xstr("flighttype_" +
[220]249 flightType2string(pirep.flightType)))
250 self._online.set_text(xstr("pirepView_" +
251 ("yes" if pirep.online else "no")))
252
253 delayCodes = ""
254 for code in pirep.delayCodes:
255 if delayCodes: delayCodes += ", "
[437]256 delayCodes += code
[831]257
258 self._delayCodes.get_buffer().set_text(delayCodes)
[221]259
260 self._comments.get_buffer().set_text(pirep.comments)
261 self._flightDefects.get_buffer().set_text(pirep.flightDefects)
262
263 logBuffer = self._log.get_buffer()
264 logBuffer.set_text("")
[225]265 lineIndex = 0
[221]266 for (timeStr, line) in pirep.logLines:
[225]267 isFault = lineIndex in pirep.faultLineIndexes
[226]268 appendTextBuffer(logBuffer,
269 formatFlightLogLine(timeStr, line),
270 isFault = isFault)
[225]271 lineIndex += 1
[221]272
273 self._notebook.set_current_page(0)
[224]274 self._okButton.grab_default()
[220]275
276 def _buildDataTab(self):
277 """Build the data tab of the viewer."""
278 table = gtk.Table(1, 2)
279 table.set_row_spacings(4)
280 table.set_col_spacings(16)
281 table.set_homogeneous(True)
282
283 box1 = gtk.VBox()
284 table.attach(box1, 0, 1, 0, 1)
[831]285
[220]286 box2 = gtk.VBox()
287 table.attach(box2, 1, 2, 0, 1)
[831]288
[220]289 flightFrame = self._buildFlightFrame()
290 box1.pack_start(flightFrame, False, False, 4)
291
292 routeFrame = self._buildRouteFrame()
293 box1.pack_start(routeFrame, False, False, 4)
294
295 departureFrame = self._buildDepartureFrame()
296 box2.pack_start(departureFrame, True, True, 4)
297
298 arrivalFrame = self._buildArrivalFrame()
299 box2.pack_start(arrivalFrame, True, True, 4)
300
301 statisticsFrame = self._buildStatisticsFrame()
302 box2.pack_start(statisticsFrame, False, False, 4)
303
304 miscellaneousFrame = self._buildMiscellaneousFrame()
305 box1.pack_start(miscellaneousFrame, False, False, 4)
306
307 return table
308
309 def _buildFlightFrame(self):
310 """Build the frame for the flight data."""
[831]311
[220]312 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_flight"))
[831]313
[220]314 dataBox = gtk.HBox()
315 mainBox.pack_start(dataBox, False, False, 0)
[831]316
[220]317 self._callsign = \
318 PIREPViewer.addLabeledData(dataBox,
319 xstr("pirepView_callsign"),
320 width = 8)
321
322 self._tailNumber = \
323 PIREPViewer.addLabeledData(dataBox,
324 xstr("pirepView_tailNumber"),
325 width = 7)
326
327 PIREPViewer.addVFiller(mainBox)
328
329 dataBox = gtk.HBox()
330 mainBox.pack_start(dataBox, False, False, 0)
331
332 self._aircraftType = \
333 PIREPViewer.addLabeledData(dataBox,
334 xstr("pirepView_aircraftType"),
335 width = 25)
336
337 PIREPViewer.addVFiller(mainBox)
338
339 table = gtk.Table(3, 2)
340 mainBox.pack_start(table, False, False, 0)
341 table.set_row_spacings(4)
[831]342 table.set_col_spacings(8)
[220]343
344 self._departureICAO = \
345 PIREPViewer.tableAttach(table, 0, 0,
346 xstr("pirepView_departure"),
347 width = 5)
348
349 self._departureTime = \
350 PIREPViewer.tableAttach(table, 1, 0,
351 xstr("pirepView_departure_time"),
352 width = 6)
353
354 self._arrivalICAO = \
355 PIREPViewer.tableAttach(table, 0, 1,
356 xstr("pirepView_arrival"),
357 width = 5)
358
359 self._arrivalTime = \
360 PIREPViewer.tableAttach(table, 1, 1,
361 xstr("pirepView_arrival_time"),
362 width = 6)
363
364 table = gtk.Table(3, 2)
365 mainBox.pack_start(table, False, False, 0)
366 table.set_row_spacings(4)
[831]367 table.set_col_spacings(8)
[220]368
369 self._numPassengers = \
370 PIREPViewer.tableAttach(table, 0, 0,
371 xstr("pirepView_numPassengers"),
372 width = 4)
373
374 self._numCrew = \
375 PIREPViewer.tableAttach(table, 1, 0,
376 xstr("pirepView_numCrew"),
377 width = 3)
378
379 self._bagWeight = \
[831]380 PIREPViewer.tableAttach(table, 0, 1,
[220]381 xstr("pirepView_bagWeight"),
382 width = 5)
383
384 self._cargoWeight = \
[831]385 PIREPViewer.tableAttach(table, 1, 1,
[220]386 xstr("pirepView_cargoWeight"),
387 width = 5)
388
389 self._mailWeight = \
[831]390 PIREPViewer.tableAttach(table, 2, 1,
[220]391 xstr("pirepView_mailWeight"),
392 width = 5)
[831]393
[220]394 PIREPViewer.addVFiller(mainBox)
395
396 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_route")),
397 False, False, 0)
[831]398
[220]399 (routeWindow, self._route) = PIREPViewer.getTextWindow()
400 mainBox.pack_start(routeWindow, False, False, 0)
401
402 return frame
403
404 def _buildRouteFrame(self):
405 """Build the frame for the user-specified route and flight
406 level."""
[831]407
[220]408 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_route"))
409
410 levelBox = gtk.HBox()
411 mainBox.pack_start(levelBox, False, False, 0)
[831]412
[220]413 self._filedCruiseLevel = \
[831]414 PIREPViewer.addLabeledData(levelBox,
[220]415 xstr("pirepView_filedCruiseLevel"),
416 width = 6)
417
418 self._modifiedCruiseLevel = \
419 PIREPViewer.addLabeledData(levelBox,
420 xstr("pirepView_modifiedCruiseLevel"),
421 width = 6)
422
423 PIREPViewer.addVFiller(mainBox)
424
425 (routeWindow, self._userRoute) = PIREPViewer.getTextWindow()
426 mainBox.pack_start(routeWindow, False, False, 0)
427
428 return frame
429
430 def _buildDepartureFrame(self):
[831]431 """Build the frame for the departure data."""
[220]432 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_departure"))
433
434 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
435 False, False, 0)
436 (metarWindow, self._departureMETAR) = \
437 PIREPViewer.getTextWindow(heightRequest = -1)
438 mainBox.pack_start(metarWindow, True, True, 0)
439
440 PIREPViewer.addVFiller(mainBox)
441
442 dataBox = gtk.HBox()
443 mainBox.pack_start(dataBox, False, False, 0)
[831]444
[220]445 self._departureRunway = \
446 PIREPViewer.addLabeledData(dataBox,
447 xstr("pirepView_runway"),
448 width = 5)
449
450 self._sid = \
451 PIREPViewer.addLabeledData(dataBox,
452 xstr("pirepView_sid"),
453 width = 12)
454
455 return frame
[831]456
[220]457 def _buildArrivalFrame(self):
[831]458 """Build the frame for the arrival data."""
[220]459 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_arrival"))
460
461 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
462 False, False, 0)
463 (metarWindow, self._arrivalMETAR) = \
464 PIREPViewer.getTextWindow(heightRequest = -1)
465 mainBox.pack_start(metarWindow, True, True, 0)
466
467 PIREPViewer.addVFiller(mainBox)
468
469 table = gtk.Table(2, 2)
470 mainBox.pack_start(table, False, False, 0)
471 table.set_row_spacings(4)
[831]472 table.set_col_spacings(8)
[220]473
474 self._star = \
475 PIREPViewer.tableAttach(table, 0, 0,
476 xstr("pirepView_star"),
477 width = 12)
478
479 self._transition = \
480 PIREPViewer.tableAttach(table, 1, 0,
481 xstr("pirepView_transition"),
482 width = 12)
[831]483
[220]484 self._approachType = \
485 PIREPViewer.tableAttach(table, 0, 1,
486 xstr("pirepView_approachType"),
487 width = 7)
[831]488
[220]489 self._arrivalRunway = \
[831]490 PIREPViewer.tableAttach(table, 1, 1,
[220]491 xstr("pirepView_runway"),
492 width = 5)
[831]493
[220]494 return frame
495
496 def _buildStatisticsFrame(self):
[831]497 """Build the frame for the statistics data."""
[220]498 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_statistics"))
499
500 table = gtk.Table(4, 2)
501 mainBox.pack_start(table, False, False, 0)
502 table.set_row_spacings(4)
503 table.set_col_spacings(8)
[221]504 table.set_homogeneous(False)
[831]505
[220]506 self._blockTimeStart = \
507 PIREPViewer.tableAttach(table, 0, 0,
508 xstr("pirepView_blockTimeStart"),
509 width = 6)
[831]510
[220]511 self._blockTimeEnd = \
512 PIREPViewer.tableAttach(table, 1, 0,
513 xstr("pirepView_blockTimeEnd"),
514 width = 8)
515
516 self._flightTimeStart = \
517 PIREPViewer.tableAttach(table, 0, 1,
518 xstr("pirepView_flightTimeStart"),
519 width = 6)
[831]520
[220]521 self._flightTimeEnd = \
[831]522 PIREPViewer.tableAttach(table, 1, 1,
[220]523 xstr("pirepView_flightTimeEnd"),
524 width = 6)
525
526 self._flownDistance = \
527 PIREPViewer.tableAttach(table, 0, 2,
528 xstr("pirepView_flownDistance"),
529 width = 8)
[831]530
[220]531 self._fuelUsed = \
532 PIREPViewer.tableAttach(table, 1, 2,
533 xstr("pirepView_fuelUsed"),
534 width = 6)
[831]535
[220]536 self._rating = \
537 PIREPViewer.tableAttach(table, 0, 3,
538 xstr("pirepView_rating"),
539 width = 7)
540 return frame
541
542 def _buildMiscellaneousFrame(self):
[831]543 """Build the frame for the miscellaneous data."""
[220]544 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_miscellaneous"))
[303]545
546 table = gtk.Table(3, 2)
547 mainBox.pack_start(table, False, False, 0)
548 table.set_row_spacings(4)
[831]549 table.set_col_spacings(8)
550
[303]551 self._flownNumPassengers = \
552 PIREPViewer.tableAttach(table, 0, 0,
553 xstr("pirepView_numPassengers"),
554 width = 4)
555
556 self._flownNumCrew = \
557 PIREPViewer.tableAttach(table, 1, 0,
558 xstr("pirepView_numCrew"),
559 width = 3)
560
561 self._flownBagWeight = \
562 PIREPViewer.tableAttach(table, 0, 1,
563 xstr("pirepView_bagWeight"),
564 width = 5)
565
[223]566 self._flownCargoWeight = \
[303]567 PIREPViewer.tableAttach(table, 1, 1,
568 xstr("pirepView_cargoWeight"),
569 width = 6)
570
571 self._flownMailWeight = \
572 PIREPViewer.tableAttach(table, 2, 1,
573 xstr("pirepView_mailWeight"),
574 width = 5)
[223]575
[220]576 self._flightType = \
[303]577 PIREPViewer.tableAttach(table, 0, 2,
578 xstr("pirepView_flightType"),
579 width = 15)
[831]580
[220]581 self._online = \
[303]582 PIREPViewer.tableAttach(table, 1, 2,
583 xstr("pirepView_online"),
584 width = 5)
[220]585
586 PIREPViewer.addVFiller(mainBox)
587
588 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_delayCodes")),
589 False, False, 0)
[831]590
[220]591 (textWindow, self._delayCodes) = PIREPViewer.getTextWindow()
592 mainBox.pack_start(textWindow, False, False, 0)
593
[831]594 return frame
[220]595
[221]596 def _buildCommentsTab(self):
597 """Build the tab with the comments and flight defects."""
598 table = gtk.Table(2, 1)
599 table.set_col_spacings(16)
600
601 (frame, commentsBox) = \
602 PIREPViewer.createFrame(xstr("pirepView_comments"))
603 table.attach(frame, 0, 1, 0, 1)
604
605 (commentsWindow, self._comments) = \
606 PIREPViewer.getTextWindow(heightRequest = -1)
607 commentsBox.pack_start(commentsWindow, True, True, 0)
608
609 (frame, flightDefectsBox) = \
610 PIREPViewer.createFrame(xstr("pirepView_flightDefects"))
611 table.attach(frame, 1, 2, 0, 1)
612
613 (flightDefectsWindow, self._flightDefects) = \
614 PIREPViewer.getTextWindow(heightRequest = -1)
615 flightDefectsBox.pack_start(flightDefectsWindow, True, True, 0)
[831]616
[221]617 return table
618
619 def _buildLogTab(self):
620 """Build the log tab."""
621 mainBox = gtk.VBox()
622
623 (logWindow, self._log) = PIREPViewer.getTextWindow(heightRequest = -1)
[226]624 addFaultTag(self._log.get_buffer())
[221]625 mainBox.pack_start(logWindow, True, True, 0)
[831]626
[221]627 return mainBox
[831]628
[220]629#------------------------------------------------------------------------------
[845]630
631class PIREPEditor(gtk.Dialog):
632 """A PIREP editor dialog."""
633 _delayCodeRE = re.compile("([0-9]{2,3})( \([^\)]*\))")
634
635 @staticmethod
636 def tableAttachWidget(table, column, row, labelText, widget):
637 """Attach the given widget with the given label to the given table.
638
639 The label will got to cell (column, row), the widget to cell
640 (column+1, row)."""
641 label = gtk.Label("<b>" + labelText + "</b>")
642 label.set_use_markup(True)
643 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
644 xscale = 0.0, yscale = 0.0)
645 alignment.add(label)
646 table.attach(alignment, column, column + 1, row, row + 1)
647
648 table.attach(widget, column + 1, column + 2, row, row + 1)
649
650 @staticmethod
651 def tableAttachSpinButton(table, column, row, labelText, maxValue,
652 minValue = 0, stepIncrement = 1,
653 pageIncrement = 10, numeric = True,
654 width = 3):
655 """Attach a spin button with the given label to the given table.
656
657 The label will got to cell (column, row), the spin button to cell
658 (column+1, row)."""
659 button = gtk.SpinButton()
660 button.set_range(min = minValue, max = maxValue)
661 button.set_increments(step = stepIncrement, page = pageIncrement)
662 button.set_numeric(True)
663 button.set_width_chars(width)
664 button.set_alignment(1.0)
665
666 PIREPEditor.tableAttachWidget(table, column, row, labelText, button)
667
668 return button
669
670 @staticmethod
671 def tableAttachTimeEntry(table, column, row, labelText):
672 """Attach a time entry widget with the given label to the given table.
673
674 The label will got to cell (column, row), the spin button to cell
675 (column+1, row)."""
676 entry = TimeEntry()
677 entry.set_width_chars(5)
678 entry.set_alignment(1.0)
679
680 PIREPEditor.tableAttachWidget(table, column, row, labelText, entry)
681
682 return entry
683
684 def __init__(self, gui):
685 """Construct the PIREP viewer."""
686 super(PIREPEditor, self).__init__(title = WINDOW_TITLE_BASE +
687 " - " +
688 xstr("pirepEdit_title"),
689 parent = gui.mainWindow)
690
691 self.set_resizable(False)
692
693 self._gui = gui
694
[846]695 self._pirep = None
696
[845]697 contentArea = self.get_content_area()
698
699 self._notebook = gtk.Notebook()
700 contentArea.pack_start(self._notebook, False, False, 4)
701
702 dataTab = self._buildDataTab()
703 label = gtk.Label(xstr("pirepView_tab_data"))
704 label.set_use_underline(True)
705 label.set_tooltip_text(xstr("pirepView_tab_data_tooltip"))
706 self._notebook.append_page(dataTab, label)
707
708 self._flightInfo = self._buildCommentsTab()
709 label = gtk.Label(xstr("pirepView_tab_comments"))
710 label.set_use_underline(True)
711 label.set_tooltip_text(xstr("pirepView_tab_comments_tooltip"))
712 self._notebook.append_page(self._flightInfo, label)
713
714 logTab = self._buildLogTab()
715 label = gtk.Label(xstr("pirepView_tab_log"))
716 label.set_use_underline(True)
717 label.set_tooltip_text(xstr("pirepView_tab_log_tooltip"))
718 self._notebook.append_page(logTab, label)
719
[846]720 self.add_button(xstr("button_cancel"), RESPONSETYPE_CANCEL)
721
[853]722 self._okButton = self.add_button(xstr("button_save"), RESPONSETYPE_NONE)
723 self._okButton.connect("clicked", self._okClicked)
[845]724 self._okButton.set_can_default(True)
[849]725 self._modified = False
[853]726 self._toSave = False
[845]727
728 def setPIREP(self, pirep):
729 """Setup the data in the dialog from the given PIREP."""
[846]730 self._pirep = pirep
731
[845]732 bookedFlight = pirep.bookedFlight
733
734 self._callsign.set_text(bookedFlight.callsign)
735 self._tailNumber.set_text(bookedFlight.tailNumber)
736 aircraftType = xstr("aircraft_" + icaoCodes[bookedFlight.aircraftType].lower())
737 self._aircraftType.set_text(aircraftType)
738
739 self._departureICAO.set_text(bookedFlight.departureICAO)
740 self._departureTime.set_text("%02d:%02d" % \
741 (bookedFlight.departureTime.hour,
742 bookedFlight.departureTime.minute))
743
744 self._arrivalICAO.set_text(bookedFlight.arrivalICAO)
745 self._arrivalTime.set_text("%02d:%02d" % \
746 (bookedFlight.arrivalTime.hour,
747 bookedFlight.arrivalTime.minute))
748
749 self._numPassengers.set_text(str(bookedFlight.numPassengers))
750 self._numCrew.set_text(str(bookedFlight.numCrew))
751 self._bagWeight.set_text(str(bookedFlight.bagWeight))
752 self._cargoWeight.set_text(str(bookedFlight.cargoWeight))
753 self._mailWeight.set_text(str(bookedFlight.mailWeight))
754
755 self._route.get_buffer().set_text(bookedFlight.route)
756
757 self._filedCruiseLevel.set_value(pirep.filedCruiseAltitude/100)
758 self._modifiedCruiseLevel.set_value(pirep.cruiseAltitude/100)
759
760 self._userRoute.get_buffer().set_text(pirep.route)
761
762 self._departureMETAR.get_buffer().set_text(pirep.departureMETAR)
763
764 self._arrivalMETAR.get_buffer().set_text(pirep.arrivalMETAR)
765 self._departureRunway.set_text(pirep.departureRunway)
766 self._sid.get_child().set_text(pirep.sid)
767
768 if not pirep.star:
769 self._star.set_active(0)
770 else:
771 self._star.get_child().set_text(pirep.star)
772
773 if not pirep.transition:
774 self._transition.set_active(0)
775 else:
776 self._transition.get_child().set_text(pirep.transition)
777 self._approachType.set_text(pirep.approachType)
778 self._arrivalRunway.set_text(pirep.arrivalRunway)
779
780 self._blockTimeStart.setTimestamp(pirep.blockTimeStart)
781 self._blockTimeEnd.setTimestamp(pirep.blockTimeEnd)
782 self._flightTimeStart.setTimestamp(pirep.flightTimeStart)
783 self._flightTimeEnd.setTimestamp(pirep.flightTimeEnd)
784
785 self._flownDistance.set_text("%.1f" % (pirep.flownDistance,))
786 self._fuelUsed.set_value(int(pirep.fuelUsed))
787
788 rating = pirep.rating
789 if rating<0:
790 self._rating.set_markup('<b><span foreground="red">NO GO</span></b>')
791 else:
792 self._rating.set_text("%.1f %%" % (rating,))
793
794 self._flownNumCrew.set_value(pirep.numCrew)
795 self._flownNumPassengers.set_value(pirep.numPassengers)
796 self._flownBagWeight.set_value(pirep.bagWeight)
797 self._flownCargoWeight.set_value(pirep.cargoWeight)
798 self._flownMailWeight.set_value(pirep.mailWeight)
799 self._flightType.set_active(flightType2index(pirep.flightType))
800 self._online.set_active(pirep.online)
801
802 self._flightInfo.reset()
803 self._flightInfo.enable(bookedFlight.aircraftType)
804
805 delayCodes = ""
806 for code in pirep.delayCodes:
807 if delayCodes: delayCodes += ", "
808 delayCodes += code
809 m = PIREPEditor._delayCodeRE.match(code)
810 if m:
811 self._flightInfo.activateDelayCode(m.group(1))
812
813 self._delayCodes.get_buffer().set_text(delayCodes)
814
815 self._flightInfo.comments = pirep.comments
816 if pirep.flightDefects.find("<br/></b>")!=-1:
817 flightDefects = pirep.flightDefects.split("<br/></b>")
818 caption = flightDefects[0]
819 index = 0
820 for defect in flightDefects[1:]:
821 if defect.find("<b>")!=-1:
822 (explanation, nextCaption) = defect.split("<b>")
823 else:
824 explanation = defect
825 nextCaption = None
826 self._flightInfo.addFault(index, caption)
827 self._flightInfo.setExplanation(index, explanation)
828 index += 1
829 caption = nextCaption
830
831 # self._comments.get_buffer().set_text(pirep.comments)
832 # self._flightDefects.get_buffer().set_text(pirep.flightDefects)
833
834 logBuffer = self._log.get_buffer()
835 logBuffer.set_text("")
836 lineIndex = 0
837 for (timeStr, line) in pirep.logLines:
838 isFault = lineIndex in pirep.faultLineIndexes
839 appendTextBuffer(logBuffer,
840 formatFlightLogLine(timeStr, line),
841 isFault = isFault)
842 lineIndex += 1
843
844 self._notebook.set_current_page(0)
845 self._okButton.grab_default()
846
[849]847 self._modified = False
[846]848 self._updateButtons()
[849]849 self._modified = True
[853]850 self._toSave = False
[846]851
852 def delayCodesChanged(self):
853 """Called when the delay codes have changed."""
854 self._updateButtons()
855
856 def commentsChanged(self):
857 """Called when the comments have changed."""
858 self._updateButtons()
859
860 def faultExplanationsChanged(self):
861 """Called when the fault explanations have changed."""
862 self._updateButtons()
863
[845]864 def _buildDataTab(self):
865 """Build the data tab of the viewer."""
866 table = gtk.Table(1, 2)
867 table.set_row_spacings(4)
868 table.set_col_spacings(16)
869 table.set_homogeneous(True)
870
871 box1 = gtk.VBox()
872 table.attach(box1, 0, 1, 0, 1)
873
874 box2 = gtk.VBox()
875 table.attach(box2, 1, 2, 0, 1)
876
877 flightFrame = self._buildFlightFrame()
878 box1.pack_start(flightFrame, False, False, 4)
879
880 routeFrame = self._buildRouteFrame()
881 box1.pack_start(routeFrame, False, False, 4)
882
883 departureFrame = self._buildDepartureFrame()
884 box2.pack_start(departureFrame, True, True, 4)
885
886 arrivalFrame = self._buildArrivalFrame()
887 box2.pack_start(arrivalFrame, True, True, 4)
888
889 statisticsFrame = self._buildStatisticsFrame()
890 box2.pack_start(statisticsFrame, False, False, 4)
891
892 miscellaneousFrame = self._buildMiscellaneousFrame()
893 box1.pack_start(miscellaneousFrame, False, False, 4)
894
895 return table
896
897 def _buildFlightFrame(self):
898 """Build the frame for the flight data."""
899
900 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_flight"))
901
902 dataBox = gtk.HBox()
903 mainBox.pack_start(dataBox, False, False, 0)
904
905 self._callsign = \
906 PIREPViewer.addLabeledData(dataBox,
907 xstr("pirepView_callsign"),
908 width = 8)
909
910 self._tailNumber = \
911 PIREPViewer.addLabeledData(dataBox,
912 xstr("pirepView_tailNumber"),
913 width = 7)
914
915 PIREPViewer.addVFiller(mainBox)
916
917 dataBox = gtk.HBox()
918 mainBox.pack_start(dataBox, False, False, 0)
919
920 self._aircraftType = \
921 PIREPViewer.addLabeledData(dataBox,
922 xstr("pirepView_aircraftType"),
923 width = 25)
924
925 PIREPViewer.addVFiller(mainBox)
926
927 table = gtk.Table(3, 2)
928 mainBox.pack_start(table, False, False, 0)
929 table.set_row_spacings(4)
930 table.set_col_spacings(8)
931
932 self._departureICAO = \
933 PIREPViewer.tableAttach(table, 0, 0,
934 xstr("pirepView_departure"),
935 width = 5)
936
937 self._departureTime = \
938 PIREPViewer.tableAttach(table, 1, 0,
939 xstr("pirepView_departure_time"),
940 width = 6)
941
942 self._arrivalICAO = \
943 PIREPViewer.tableAttach(table, 0, 1,
944 xstr("pirepView_arrival"),
945 width = 5)
946
947 self._arrivalTime = \
948 PIREPViewer.tableAttach(table, 1, 1,
949 xstr("pirepView_arrival_time"),
950 width = 6)
951
952 table = gtk.Table(3, 2)
953 mainBox.pack_start(table, False, False, 0)
954 table.set_row_spacings(4)
955 table.set_col_spacings(8)
956
957 self._numPassengers = \
958 PIREPViewer.tableAttach(table, 0, 0,
959 xstr("pirepView_numPassengers"),
960 width = 4)
961 self._numCrew = \
962 PIREPViewer.tableAttach(table, 1, 0,
963 xstr("pirepView_numCrew"),
964 width = 3)
965
966 self._bagWeight = \
967 PIREPViewer.tableAttach(table, 0, 1,
968 xstr("pirepView_bagWeight"),
969 width = 5)
970
971 self._cargoWeight = \
972 PIREPViewer.tableAttach(table, 1, 1,
973 xstr("pirepView_cargoWeight"),
974 width = 5)
975
976 self._mailWeight = \
977 PIREPViewer.tableAttach(table, 2, 1,
978 xstr("pirepView_mailWeight"),
979 width = 5)
980
981 PIREPViewer.addVFiller(mainBox)
982
983 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_route")),
984 False, False, 0)
985
986 (routeWindow, self._route) = PIREPViewer.getTextWindow()
987 mainBox.pack_start(routeWindow, False, False, 0)
988
989 return frame
990
991 def _buildRouteFrame(self):
992 """Build the frame for the user-specified route and flight
993 level."""
994
995 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_route"))
996
997 levelBox = gtk.HBox()
998 mainBox.pack_start(levelBox, False, False, 0)
999
1000 label = PIREPViewer.getLabel(xstr("pirepView_filedCruiseLevel"),
1001 xstr("pirepEdit_FL"))
1002 levelBox.pack_start(label, False, False, 0)
1003
1004 self._filedCruiseLevel = gtk.SpinButton()
1005 self._filedCruiseLevel.set_increments(step = 10, page = 100)
1006 self._filedCruiseLevel.set_range(min = 0, max = 500)
[847]1007 self._filedCruiseLevel.set_tooltip_text(xstr("route_level_tooltip"))
[845]1008 self._filedCruiseLevel.set_numeric(True)
[846]1009 self._filedCruiseLevel.connect("value-changed", self._updateButtons)
[845]1010
1011 levelBox.pack_start(self._filedCruiseLevel, False, False, 0)
1012
1013 PIREPViewer.addHFiller(levelBox)
1014
1015 label = PIREPViewer.getLabel(xstr("pirepView_modifiedCruiseLevel"),
1016 xstr("pirepEdit_FL"))
1017 levelBox.pack_start(label, False, False, 0)
1018
1019 self._modifiedCruiseLevel = gtk.SpinButton()
1020 self._modifiedCruiseLevel.set_increments(step = 10, page = 100)
1021 self._modifiedCruiseLevel.set_range(min = 0, max = 500)
[847]1022 self._modifiedCruiseLevel.set_tooltip_text(xstr("pirepEdit_modified_route_level_tooltip"))
[845]1023 self._modifiedCruiseLevel.set_numeric(True)
[846]1024 self._modifiedCruiseLevel.connect("value-changed", self._updateButtons)
[845]1025
1026 levelBox.pack_start(self._modifiedCruiseLevel, False, False, 0)
1027
1028 PIREPViewer.addVFiller(mainBox)
1029
1030 (routeWindow, self._userRoute) = \
1031 PIREPViewer.getTextWindow(editable = True)
1032 mainBox.pack_start(routeWindow, False, False, 0)
[846]1033 self._userRoute.get_buffer().connect("changed", self._updateButtons)
[847]1034 self._userRoute.set_tooltip_text(xstr("route_route_tooltip"))
[845]1035
1036 return frame
1037
1038 def _buildDepartureFrame(self):
1039 """Build the frame for the departure data."""
1040 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_departure"))
1041
1042 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
1043 False, False, 0)
1044 (metarWindow, self._departureMETAR) = \
1045 PIREPViewer.getTextWindow(heightRequest = -1,
1046 editable = True)
[846]1047 self._departureMETAR.get_buffer().connect("changed", self._updateButtons)
[847]1048 self._departureMETAR.set_tooltip_text(xstr("takeoff_metar_tooltip"))
[845]1049 mainBox.pack_start(metarWindow, True, True, 0)
1050
1051 PIREPViewer.addVFiller(mainBox)
1052
1053 dataBox = gtk.HBox()
1054 mainBox.pack_start(dataBox, False, False, 0)
1055
1056 label = gtk.Label("<b>" + xstr("pirepView_runway") + "</b>")
1057 label.set_use_markup(True)
1058 dataBox.pack_start(label, False, False, 0)
1059
1060 # FIXME: quite the same as the runway entry boxes in the wizard
1061 self._departureRunway = gtk.Entry()
1062 self._departureRunway.set_width_chars(5)
1063 self._departureRunway.set_tooltip_text(xstr("takeoff_runway_tooltip"))
1064 self._departureRunway.connect("changed", self._upperChanged)
1065 dataBox.pack_start(self._departureRunway, False, False, 8)
1066
1067 label = gtk.Label("<b>" + xstr("pirepView_sid") + "</b>")
1068 label.set_use_markup(True)
1069 dataBox.pack_start(label, False, False, 0)
1070
1071 # FIXME: quite the same as the SID combo box in
1072 # the flight wizard
1073 if pygobject:
1074 self._sid = gtk.ComboBox.new_with_model_and_entry(comboModel)
1075 else:
1076 self._sid = gtk.ComboBoxEntry(comboModel)
1077
1078 self._sid.set_entry_text_column(0)
1079 self._sid.get_child().set_width_chars(10)
1080 self._sid.set_tooltip_text(xstr("takeoff_sid_tooltip"))
1081 self._sid.connect("changed", self._upperChangedComboBox)
1082
1083 dataBox.pack_start(self._sid, False, False, 8)
1084
1085 return frame
1086
1087 def _buildArrivalFrame(self):
1088 """Build the frame for the arrival data."""
1089 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_arrival"))
1090
1091 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
1092 False, False, 0)
1093 (metarWindow, self._arrivalMETAR) = \
1094 PIREPViewer.getTextWindow(heightRequest = -1,
1095 editable = True)
[846]1096 self._arrivalMETAR.get_buffer().connect("changed", self._updateButtons)
[847]1097 self._arrivalMETAR.set_tooltip_text(xstr("landing_metar_tooltip"))
[845]1098 mainBox.pack_start(metarWindow, True, True, 0)
1099
1100 PIREPViewer.addVFiller(mainBox)
1101
1102 table = gtk.Table(2, 4)
1103 mainBox.pack_start(table, False, False, 0)
1104 table.set_row_spacings(4)
1105 table.set_col_spacings(8)
1106
1107 # FIXME: quite the same as in the wizard
1108 if pygobject:
1109 self._star = gtk.ComboBox.new_with_model_and_entry(comboModel)
1110 else:
1111 self._star = gtk.ComboBoxEntry(comboModel)
1112
1113 self._star.set_entry_text_column(0)
1114 self._star.get_child().set_width_chars(10)
1115 self._star.set_tooltip_text(xstr("landing_star_tooltip"))
1116 self._star.connect("changed", self._upperChangedComboBox)
1117
1118 PIREPEditor.tableAttachWidget(table, 0, 0,
1119 xstr("pirepView_star"),
1120 self._star)
1121
1122 # FIXME: quite the same as in the wizard
1123 if pygobject:
1124 self._transition = gtk.ComboBox.new_with_model_and_entry(comboModel)
1125 else:
1126 self._transition = gtk.ComboBoxEntry(comboModel)
1127
1128 self._transition.set_entry_text_column(0)
1129 self._transition.get_child().set_width_chars(10)
1130 self._transition.set_tooltip_text(xstr("landing_transition_tooltip"))
1131 self._transition.connect("changed", self._upperChangedComboBox)
1132
1133 PIREPEditor.tableAttachWidget(table, 2, 0,
1134 xstr("pirepView_transition"),
1135 self._transition)
1136
1137
1138 # FIXME: quite the same as in the wizard
1139 self._approachType = gtk.Entry()
1140 self._approachType.set_width_chars(10)
1141 self._approachType.set_tooltip_text(xstr("landing_approach_tooltip"))
1142 self._approachType.connect("changed", self._upperChanged)
1143
1144 PIREPEditor.tableAttachWidget(table, 0, 1,
1145 xstr("pirepView_approachType"),
1146 self._approachType)
1147
1148 # FIXME: quite the same as in the wizard
1149 self._arrivalRunway = gtk.Entry()
1150 self._arrivalRunway.set_width_chars(10)
1151 self._arrivalRunway.set_tooltip_text(xstr("landing_runway_tooltip"))
1152 self._arrivalRunway.connect("changed", self._upperChanged)
1153
1154 PIREPEditor.tableAttachWidget(table, 2, 1,
1155 xstr("pirepView_runway"),
1156 self._arrivalRunway)
1157
1158 return frame
1159
1160 def _buildStatisticsFrame(self):
1161 """Build the frame for the statistics data."""
1162 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_statistics"))
1163
1164 table = gtk.Table(4, 4)
1165 mainBox.pack_start(table, False, False, 0)
1166 table.set_row_spacings(4)
1167 table.set_col_spacings(8)
1168 table.set_homogeneous(False)
1169
1170 self._blockTimeStart = \
1171 PIREPEditor.tableAttachTimeEntry(table, 0, 0,
1172 xstr("pirepView_blockTimeStart"))
[846]1173 self._blockTimeStart.connect("changed", self._updateButtons)
[847]1174 self._blockTimeStart.set_tooltip_text(xstr("pirepEdit_block_time_start_tooltip"))
[845]1175
1176 self._blockTimeEnd = \
1177 PIREPEditor.tableAttachTimeEntry(table, 2, 0,
1178 xstr("pirepView_blockTimeEnd"))
[846]1179 self._blockTimeEnd.connect("changed", self._updateButtons)
[847]1180 self._blockTimeEnd.set_tooltip_text(xstr("pirepEdit_block_time_end_tooltip"))
[845]1181
1182 self._flightTimeStart = \
1183 PIREPEditor.tableAttachTimeEntry(table, 0, 1,
1184 xstr("pirepView_flightTimeStart"))
[846]1185 self._flightTimeStart.connect("changed", self._updateButtons)
[847]1186 self._flightTimeStart.set_tooltip_text(xstr("pirepEdit_flight_time_start_tooltip"))
[845]1187
1188 self._flightTimeEnd = \
1189 PIREPEditor.tableAttachTimeEntry(table, 2, 1,
1190 xstr("pirepView_flightTimeEnd"))
[846]1191 self._flightTimeEnd.connect("changed", self._updateButtons)
[847]1192 self._flightTimeEnd.set_tooltip_text(xstr("pirepEdit_flight_time_end_tooltip"))
[845]1193
1194 self._flownDistance = PIREPViewer.getDataLabel(width = 3)
1195 PIREPEditor.tableAttachWidget(table, 0, 2,
1196 xstr("pirepView_flownDistance"),
1197 self._flownDistance)
1198
1199 self._fuelUsed = \
1200 PIREPEditor.tableAttachSpinButton(table, 2, 2,
1201 xstr("pirepView_fuelUsed"),
1202 1000000)
[846]1203 self._fuelUsed.connect("value-changed", self._updateButtons)
[847]1204 self._fuelUsed.set_tooltip_text(xstr("pirepEdit_fuel_used_tooltip"))
[845]1205
1206 self._rating = PIREPViewer.getDataLabel(width = 3)
1207 PIREPEditor.tableAttachWidget(table, 0, 3,
1208 xstr("pirepView_rating"),
1209 self._rating)
1210 return frame
1211
1212 def _buildMiscellaneousFrame(self):
1213 """Build the frame for the miscellaneous data."""
1214 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_miscellaneous"))
1215
1216 table = gtk.Table(6, 2)
1217 mainBox.pack_start(table, False, False, 0)
1218 table.set_row_spacings(4)
1219 table.set_col_spacings(8)
1220 table.set_homogeneous(False)
1221
1222 self._flownNumPassengers = \
1223 PIREPEditor.tableAttachSpinButton(table, 0, 0,
1224 xstr("pirepView_numPassengers"),
1225 300)
[846]1226 self._flownNumPassengers.connect("value-changed", self._updateButtons)
[847]1227 self._flownNumPassengers.set_tooltip_text(xstr("payload_pax_tooltip"))
[845]1228
1229 self._flownNumCrew = \
1230 PIREPEditor.tableAttachSpinButton(table, 2, 0,
1231 xstr("pirepView_numCrew"),
1232 10)
[846]1233 self._flownNumCrew.connect("value-changed", self._updateButtons)
[847]1234 self._flownNumCrew.set_tooltip_text(xstr("payload_crew_tooltip"))
[845]1235
1236 self._flownBagWeight = \
1237 PIREPEditor.tableAttachSpinButton(table, 0, 1,
1238 xstr("pirepView_bagWeight"),
1239 100000, width = 6)
[849]1240 self._flownBagWeight.connect("value-changed", self._updateButtons)
[847]1241 self._flownBagWeight.set_tooltip_text(xstr("payload_bag_tooltip"))
[845]1242
1243 self._flownCargoWeight = \
1244 PIREPEditor.tableAttachSpinButton(table, 2, 1,
1245 xstr("pirepView_cargoWeight"),
1246 100000, width = 6)
[849]1247 self._flownCargoWeight.connect("value-changed", self._updateButtons)
[847]1248 self._flownCargoWeight.set_tooltip_text(xstr("payload_cargo_tooltip"))
[845]1249
1250 self._flownMailWeight = \
1251 PIREPEditor.tableAttachSpinButton(table, 4, 1,
1252 xstr("pirepView_mailWeight"),
1253 100000, width = 6)
[849]1254 self._flownMailWeight.connect("value-changed", self._updateButtons)
[847]1255 self._flownMailWeight.set_tooltip_text(xstr("payload_mail_tooltip"))
[845]1256
1257 self._flightType = createFlightTypeComboBox()
1258 PIREPEditor.tableAttachWidget(table, 0, 2,
1259 xstr("pirepView_flightType"),
1260 self._flightType)
[849]1261 self._flightType.connect("changed", self._updateButtons)
[847]1262 self._flightType.set_tooltip_text(xstr("pirepEdit_flight_type_tooltip"))
[845]1263
[847]1264 self._online = gtk.CheckButton(xstr("pirepEdit_online"))
[845]1265 table.attach(self._online, 2, 3, 2, 3)
[849]1266 self._online.connect("toggled", self._updateButtons)
[847]1267 self._online.set_tooltip_text(xstr("pirepEdit_online_tooltip"))
[845]1268
1269 PIREPViewer.addVFiller(mainBox)
1270
1271 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_delayCodes")),
1272 False, False, 0)
1273
1274 (textWindow, self._delayCodes) = PIREPViewer.getTextWindow()
1275 mainBox.pack_start(textWindow, False, False, 0)
[847]1276 self._delayCodes.set_tooltip_text(xstr("pirepEdit_delayCodes_tooltip"))
[845]1277
1278 return frame
1279
1280 def _buildCommentsTab(self):
1281 """Build the tab with the comments and flight defects."""
[846]1282 return FlightInfo(self._gui, callbackObject = self)
[845]1283
1284 def _buildLogTab(self):
1285 """Build the log tab."""
1286 mainBox = gtk.VBox()
1287
1288 (logWindow, self._log) = PIREPViewer.getTextWindow(heightRequest = -1)
1289 addFaultTag(self._log.get_buffer())
1290 mainBox.pack_start(logWindow, True, True, 0)
1291
1292 return mainBox
1293
1294 def _upperChanged(self, entry, arg = None):
1295 """Called when the value of some entry widget has changed and the value
1296 should be converted to uppercase."""
1297 entry.set_text(entry.get_text().upper())
[846]1298 self._updateButtons()
[845]1299 #self._valueChanged(entry, arg)
1300
1301 def _upperChangedComboBox(self, comboBox):
1302 """Called for combo box widgets that must be converted to uppercase."""
1303 entry = comboBox.get_child()
1304 if comboBox.get_active()==-1:
1305 entry.set_text(entry.get_text().upper())
[846]1306 self._updateButtons()
[845]1307 #self._valueChanged(entry)
1308
[846]1309 def _updateButtons(self, *kwargs):
1310 """Update the activity state of the buttons."""
1311 pirep = self._pirep
1312 bookedFlight = pirep.bookedFlight
1313
1314 departureMinutes = \
1315 bookedFlight.departureTime.hour*60 + bookedFlight.departureTime.minute
1316 departureDifference = abs(Flight.getMinutesDifference(self._blockTimeStart.minutes,
1317 departureMinutes))
1318 flightStartDifference = \
1319 Flight.getMinutesDifference(self._flightTimeStart.minutes,
1320 self._blockTimeStart.minutes)
1321 arrivalMinutes = \
1322 bookedFlight.arrivalTime.hour*60 + bookedFlight.arrivalTime.minute
1323 arrivalDifference = abs(Flight.getMinutesDifference(self._blockTimeEnd.minutes,
1324 arrivalMinutes))
1325 flightEndDifference = \
1326 Flight.getMinutesDifference(self._blockTimeEnd.minutes,
1327 self._flightTimeEnd.minutes)
1328
1329 timesOK = self._flightInfo.hasComments or \
1330 self._flightInfo.hasDelayCode or \
1331 (departureDifference<=Flight.TIME_ERROR_DIFFERENCE and
1332 arrivalDifference<=Flight.TIME_ERROR_DIFFERENCE and
1333 flightStartDifference>=0 and flightStartDifference<30 and
1334 flightEndDifference>=0 and flightEndDifference<30)
1335
1336 text = self._sid.get_child().get_text()
1337 sid = text if self._sid.get_active()!=0 and text and text!="N/A" \
1338 else None
1339
1340 text = self._star.get_child().get_text()
1341 star = text if self._star.get_active()!=0 and text and text!="N/A" \
1342 else None
1343
1344 text = self._transition.get_child().get_text()
1345 transition = text if self._transition.get_active()!=0 \
1346 and text and text!="N/A" else None
1347
1348
1349 buffer = self._userRoute.get_buffer()
1350 route = buffer.get_text(buffer.get_start_iter(),
1351 buffer.get_end_iter(), True)
1352
[849]1353 self._okButton.set_sensitive(self._modified and timesOK and
[846]1354 self._flightInfo.faultsFullyExplained and
1355 self._flownNumPassengers.get_value_as_int()>0 and
1356 self._flownNumCrew.get_value_as_int()>2 and
1357 self._fuelUsed.get_value_as_int()>0 and
1358 self._departureRunway.get_text_length()>0 and
1359 self._arrivalRunway.get_text_length()>0 and
1360 self._departureMETAR.get_buffer().get_char_count()>0 and
1361 self._arrivalMETAR.get_buffer().get_char_count()>0 and
1362 self._filedCruiseLevel.get_value_as_int()>=50 and
1363 self._modifiedCruiseLevel.get_value_as_int()>=50 and
1364 sid is not None and (star is not None or
1365 transition is not None) and route!="" and
1366 self._approachType.get_text()!="")
1367
[853]1368 def _okClicked(self, button):
1369 """Called when the OK button has been clicked.
1370
1371 The PIREP is updated from the data in the window."""
1372 if not askYesNo(xstr("pirepEdit_save_question"), parent = self):
1373 self.response(RESPONSETYPE_CANCEL)
1374
1375 pirep = self._pirep
1376
1377 pirep.filedCruiseAltitude = \
1378 self._filedCruiseLevel.get_value_as_int() * 100
1379 pirep.cruiseAltitude = \
1380 self._modifiedCruiseLevel.get_value_as_int() * 100
1381
1382 pirep.route = getTextViewText(self._userRoute)
1383
1384 pirep.departureMETAR = getTextViewText(self._departureMETAR)
1385 pirep.departureRunway = self._departureRunway.get_text()
1386 pirep.sid = self._sid.get_child().get_text()
1387
1388 pirep.arrivalMETAR = getTextViewText(self._arrivalMETAR)
1389 pirep.star = None if self._star.get_active()==0 \
1390 else self._star.get_child().get_text()
1391 pirep.transition = None if self._transition.get_active()==0 \
1392 else self._transition.get_child().get_text()
1393 pirep.approachType = self._approachType.get_text()
1394 pirep.arrivalRunway = self._arrivalRunway.get_text()
1395
1396 pirep.blockTimeStart = \
1397 self._blockTimeStart.getTimestampFrom(pirep.blockTimeStart)
1398 pirep.blockTimeEnd = \
1399 self._blockTimeEnd.getTimestampFrom(pirep.blockTimeEnd)
1400 pirep.flightTimeStart = \
1401 self._flightTimeStart.getTimestampFrom(pirep.flightTimeStart)
1402 pirep.flightTimeEnd = \
1403 self._flightTimeEnd.getTimestampFrom(pirep.flightTimeEnd)
1404
1405 pirep.fuelUsed = self._fuelUsed.get_value()
1406
1407 pirep.numCrew = self._flownNumCrew.get_value()
1408 pirep.numPassengers = self._flownNumPassengers.get_value()
1409 pirep.bagWeight = self._flownBagWeight.get_value()
1410 pirep.cargoWeight = self._flownCargoWeight.get_value()
1411 pirep.mailWeight = self._flownMailWeight.get_value()
1412
1413 pirep.flightType = flightTypes[self._flightType.get_active()]
1414 pirep.online = self._online.get_active()
1415
1416 pirep.delayCodes = self._flightInfo.delayCodes
1417 pirep.comments = self._flightInfo.comments
1418 pirep.flightDefects = self._flightInfo.faultsAndExplanations
1419
1420 self.response(RESPONSETYPE_OK)
1421
1422
[845]1423#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.