source: src/mlx/gui/pirep.py@ 849:7edb1f4cd12a

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

The Save button of the PIREP Editor becomes active only after the first modification (re #307)

File size: 52.5 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
[848]722 self._okButton = self.add_button(xstr("button_save"), RESPONSETYPE_OK)
[845]723 self._okButton.set_can_default(True)
[849]724 self._modified = False
[845]725
726 def setPIREP(self, pirep):
727 """Setup the data in the dialog from the given PIREP."""
[846]728 self._pirep = pirep
729
[845]730 bookedFlight = pirep.bookedFlight
731
732 self._callsign.set_text(bookedFlight.callsign)
733 self._tailNumber.set_text(bookedFlight.tailNumber)
734 aircraftType = xstr("aircraft_" + icaoCodes[bookedFlight.aircraftType].lower())
735 self._aircraftType.set_text(aircraftType)
736
737 self._departureICAO.set_text(bookedFlight.departureICAO)
738 self._departureTime.set_text("%02d:%02d" % \
739 (bookedFlight.departureTime.hour,
740 bookedFlight.departureTime.minute))
741
742 self._arrivalICAO.set_text(bookedFlight.arrivalICAO)
743 self._arrivalTime.set_text("%02d:%02d" % \
744 (bookedFlight.arrivalTime.hour,
745 bookedFlight.arrivalTime.minute))
746
747 self._numPassengers.set_text(str(bookedFlight.numPassengers))
748 self._numCrew.set_text(str(bookedFlight.numCrew))
749 self._bagWeight.set_text(str(bookedFlight.bagWeight))
750 self._cargoWeight.set_text(str(bookedFlight.cargoWeight))
751 self._mailWeight.set_text(str(bookedFlight.mailWeight))
752
753 self._route.get_buffer().set_text(bookedFlight.route)
754
755 self._filedCruiseLevel.set_value(pirep.filedCruiseAltitude/100)
756 self._modifiedCruiseLevel.set_value(pirep.cruiseAltitude/100)
757
758 self._userRoute.get_buffer().set_text(pirep.route)
759
760 self._departureMETAR.get_buffer().set_text(pirep.departureMETAR)
761
762 self._arrivalMETAR.get_buffer().set_text(pirep.arrivalMETAR)
763 self._departureRunway.set_text(pirep.departureRunway)
764 self._sid.get_child().set_text(pirep.sid)
765
766 if not pirep.star:
767 self._star.set_active(0)
768 else:
769 self._star.get_child().set_text(pirep.star)
770
771 if not pirep.transition:
772 self._transition.set_active(0)
773 else:
774 self._transition.get_child().set_text(pirep.transition)
775 self._approachType.set_text(pirep.approachType)
776 self._arrivalRunway.set_text(pirep.arrivalRunway)
777
778 self._blockTimeStart.setTimestamp(pirep.blockTimeStart)
779 self._blockTimeEnd.setTimestamp(pirep.blockTimeEnd)
780 self._flightTimeStart.setTimestamp(pirep.flightTimeStart)
781 self._flightTimeEnd.setTimestamp(pirep.flightTimeEnd)
782
783 self._flownDistance.set_text("%.1f" % (pirep.flownDistance,))
784 self._fuelUsed.set_value(int(pirep.fuelUsed))
785
786 rating = pirep.rating
787 if rating<0:
788 self._rating.set_markup('<b><span foreground="red">NO GO</span></b>')
789 else:
790 self._rating.set_text("%.1f %%" % (rating,))
791
792 self._flownNumCrew.set_value(pirep.numCrew)
793 self._flownNumPassengers.set_value(pirep.numPassengers)
794 self._flownBagWeight.set_value(pirep.bagWeight)
795 self._flownCargoWeight.set_value(pirep.cargoWeight)
796 self._flownMailWeight.set_value(pirep.mailWeight)
797 self._flightType.set_active(flightType2index(pirep.flightType))
798 self._online.set_active(pirep.online)
799
800 self._flightInfo.reset()
801 self._flightInfo.enable(bookedFlight.aircraftType)
802
803 delayCodes = ""
804 for code in pirep.delayCodes:
805 if delayCodes: delayCodes += ", "
806 delayCodes += code
807 m = PIREPEditor._delayCodeRE.match(code)
808 if m:
809 self._flightInfo.activateDelayCode(m.group(1))
810
811 self._delayCodes.get_buffer().set_text(delayCodes)
812
813 self._flightInfo.comments = pirep.comments
814 if pirep.flightDefects.find("<br/></b>")!=-1:
815 flightDefects = pirep.flightDefects.split("<br/></b>")
816 caption = flightDefects[0]
817 index = 0
818 for defect in flightDefects[1:]:
819 if defect.find("<b>")!=-1:
820 (explanation, nextCaption) = defect.split("<b>")
821 else:
822 explanation = defect
823 nextCaption = None
824 self._flightInfo.addFault(index, caption)
825 self._flightInfo.setExplanation(index, explanation)
826 index += 1
827 caption = nextCaption
828
829 # self._comments.get_buffer().set_text(pirep.comments)
830 # self._flightDefects.get_buffer().set_text(pirep.flightDefects)
831
832 logBuffer = self._log.get_buffer()
833 logBuffer.set_text("")
834 lineIndex = 0
835 for (timeStr, line) in pirep.logLines:
836 isFault = lineIndex in pirep.faultLineIndexes
837 appendTextBuffer(logBuffer,
838 formatFlightLogLine(timeStr, line),
839 isFault = isFault)
840 lineIndex += 1
841
842 self._notebook.set_current_page(0)
843 self._okButton.grab_default()
844
[849]845 self._modified = False
[846]846 self._updateButtons()
[849]847 self._modified = True
[846]848
849 def delayCodesChanged(self):
850 """Called when the delay codes have changed."""
851 self._updateButtons()
852
853 def commentsChanged(self):
854 """Called when the comments have changed."""
855 self._updateButtons()
856
857 def faultExplanationsChanged(self):
858 """Called when the fault explanations have changed."""
859 self._updateButtons()
860
[845]861 def _buildDataTab(self):
862 """Build the data tab of the viewer."""
863 table = gtk.Table(1, 2)
864 table.set_row_spacings(4)
865 table.set_col_spacings(16)
866 table.set_homogeneous(True)
867
868 box1 = gtk.VBox()
869 table.attach(box1, 0, 1, 0, 1)
870
871 box2 = gtk.VBox()
872 table.attach(box2, 1, 2, 0, 1)
873
874 flightFrame = self._buildFlightFrame()
875 box1.pack_start(flightFrame, False, False, 4)
876
877 routeFrame = self._buildRouteFrame()
878 box1.pack_start(routeFrame, False, False, 4)
879
880 departureFrame = self._buildDepartureFrame()
881 box2.pack_start(departureFrame, True, True, 4)
882
883 arrivalFrame = self._buildArrivalFrame()
884 box2.pack_start(arrivalFrame, True, True, 4)
885
886 statisticsFrame = self._buildStatisticsFrame()
887 box2.pack_start(statisticsFrame, False, False, 4)
888
889 miscellaneousFrame = self._buildMiscellaneousFrame()
890 box1.pack_start(miscellaneousFrame, False, False, 4)
891
892 return table
893
894 def _buildFlightFrame(self):
895 """Build the frame for the flight data."""
896
897 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_flight"))
898
899 dataBox = gtk.HBox()
900 mainBox.pack_start(dataBox, False, False, 0)
901
902 self._callsign = \
903 PIREPViewer.addLabeledData(dataBox,
904 xstr("pirepView_callsign"),
905 width = 8)
906
907 self._tailNumber = \
908 PIREPViewer.addLabeledData(dataBox,
909 xstr("pirepView_tailNumber"),
910 width = 7)
911
912 PIREPViewer.addVFiller(mainBox)
913
914 dataBox = gtk.HBox()
915 mainBox.pack_start(dataBox, False, False, 0)
916
917 self._aircraftType = \
918 PIREPViewer.addLabeledData(dataBox,
919 xstr("pirepView_aircraftType"),
920 width = 25)
921
922 PIREPViewer.addVFiller(mainBox)
923
924 table = gtk.Table(3, 2)
925 mainBox.pack_start(table, False, False, 0)
926 table.set_row_spacings(4)
927 table.set_col_spacings(8)
928
929 self._departureICAO = \
930 PIREPViewer.tableAttach(table, 0, 0,
931 xstr("pirepView_departure"),
932 width = 5)
933
934 self._departureTime = \
935 PIREPViewer.tableAttach(table, 1, 0,
936 xstr("pirepView_departure_time"),
937 width = 6)
938
939 self._arrivalICAO = \
940 PIREPViewer.tableAttach(table, 0, 1,
941 xstr("pirepView_arrival"),
942 width = 5)
943
944 self._arrivalTime = \
945 PIREPViewer.tableAttach(table, 1, 1,
946 xstr("pirepView_arrival_time"),
947 width = 6)
948
949 table = gtk.Table(3, 2)
950 mainBox.pack_start(table, False, False, 0)
951 table.set_row_spacings(4)
952 table.set_col_spacings(8)
953
954 self._numPassengers = \
955 PIREPViewer.tableAttach(table, 0, 0,
956 xstr("pirepView_numPassengers"),
957 width = 4)
958 self._numCrew = \
959 PIREPViewer.tableAttach(table, 1, 0,
960 xstr("pirepView_numCrew"),
961 width = 3)
962
963 self._bagWeight = \
964 PIREPViewer.tableAttach(table, 0, 1,
965 xstr("pirepView_bagWeight"),
966 width = 5)
967
968 self._cargoWeight = \
969 PIREPViewer.tableAttach(table, 1, 1,
970 xstr("pirepView_cargoWeight"),
971 width = 5)
972
973 self._mailWeight = \
974 PIREPViewer.tableAttach(table, 2, 1,
975 xstr("pirepView_mailWeight"),
976 width = 5)
977
978 PIREPViewer.addVFiller(mainBox)
979
980 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_route")),
981 False, False, 0)
982
983 (routeWindow, self._route) = PIREPViewer.getTextWindow()
984 mainBox.pack_start(routeWindow, False, False, 0)
985
986 return frame
987
988 def _buildRouteFrame(self):
989 """Build the frame for the user-specified route and flight
990 level."""
991
992 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_route"))
993
994 levelBox = gtk.HBox()
995 mainBox.pack_start(levelBox, False, False, 0)
996
997 label = PIREPViewer.getLabel(xstr("pirepView_filedCruiseLevel"),
998 xstr("pirepEdit_FL"))
999 levelBox.pack_start(label, False, False, 0)
1000
1001 self._filedCruiseLevel = gtk.SpinButton()
1002 self._filedCruiseLevel.set_increments(step = 10, page = 100)
1003 self._filedCruiseLevel.set_range(min = 0, max = 500)
[847]1004 self._filedCruiseLevel.set_tooltip_text(xstr("route_level_tooltip"))
[845]1005 self._filedCruiseLevel.set_numeric(True)
[846]1006 self._filedCruiseLevel.connect("value-changed", self._updateButtons)
[845]1007
1008 levelBox.pack_start(self._filedCruiseLevel, False, False, 0)
1009
1010 PIREPViewer.addHFiller(levelBox)
1011
1012 label = PIREPViewer.getLabel(xstr("pirepView_modifiedCruiseLevel"),
1013 xstr("pirepEdit_FL"))
1014 levelBox.pack_start(label, False, False, 0)
1015
1016 self._modifiedCruiseLevel = gtk.SpinButton()
1017 self._modifiedCruiseLevel.set_increments(step = 10, page = 100)
1018 self._modifiedCruiseLevel.set_range(min = 0, max = 500)
[847]1019 self._modifiedCruiseLevel.set_tooltip_text(xstr("pirepEdit_modified_route_level_tooltip"))
[845]1020 self._modifiedCruiseLevel.set_numeric(True)
[846]1021 self._modifiedCruiseLevel.connect("value-changed", self._updateButtons)
[845]1022
1023 levelBox.pack_start(self._modifiedCruiseLevel, False, False, 0)
1024
1025 PIREPViewer.addVFiller(mainBox)
1026
1027 (routeWindow, self._userRoute) = \
1028 PIREPViewer.getTextWindow(editable = True)
1029 mainBox.pack_start(routeWindow, False, False, 0)
[846]1030 self._userRoute.get_buffer().connect("changed", self._updateButtons)
[847]1031 self._userRoute.set_tooltip_text(xstr("route_route_tooltip"))
[845]1032
1033 return frame
1034
1035 def _buildDepartureFrame(self):
1036 """Build the frame for the departure data."""
1037 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_departure"))
1038
1039 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
1040 False, False, 0)
1041 (metarWindow, self._departureMETAR) = \
1042 PIREPViewer.getTextWindow(heightRequest = -1,
1043 editable = True)
[846]1044 self._departureMETAR.get_buffer().connect("changed", self._updateButtons)
[847]1045 self._departureMETAR.set_tooltip_text(xstr("takeoff_metar_tooltip"))
[845]1046 mainBox.pack_start(metarWindow, True, True, 0)
1047
1048 PIREPViewer.addVFiller(mainBox)
1049
1050 dataBox = gtk.HBox()
1051 mainBox.pack_start(dataBox, False, False, 0)
1052
1053 label = gtk.Label("<b>" + xstr("pirepView_runway") + "</b>")
1054 label.set_use_markup(True)
1055 dataBox.pack_start(label, False, False, 0)
1056
1057 # FIXME: quite the same as the runway entry boxes in the wizard
1058 self._departureRunway = gtk.Entry()
1059 self._departureRunway.set_width_chars(5)
1060 self._departureRunway.set_tooltip_text(xstr("takeoff_runway_tooltip"))
1061 self._departureRunway.connect("changed", self._upperChanged)
1062 dataBox.pack_start(self._departureRunway, False, False, 8)
1063
1064 label = gtk.Label("<b>" + xstr("pirepView_sid") + "</b>")
1065 label.set_use_markup(True)
1066 dataBox.pack_start(label, False, False, 0)
1067
1068 # FIXME: quite the same as the SID combo box in
1069 # the flight wizard
1070 if pygobject:
1071 self._sid = gtk.ComboBox.new_with_model_and_entry(comboModel)
1072 else:
1073 self._sid = gtk.ComboBoxEntry(comboModel)
1074
1075 self._sid.set_entry_text_column(0)
1076 self._sid.get_child().set_width_chars(10)
1077 self._sid.set_tooltip_text(xstr("takeoff_sid_tooltip"))
1078 self._sid.connect("changed", self._upperChangedComboBox)
1079
1080 dataBox.pack_start(self._sid, False, False, 8)
1081
1082 return frame
1083
1084 def _buildArrivalFrame(self):
1085 """Build the frame for the arrival data."""
1086 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_arrival"))
1087
1088 mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
1089 False, False, 0)
1090 (metarWindow, self._arrivalMETAR) = \
1091 PIREPViewer.getTextWindow(heightRequest = -1,
1092 editable = True)
[846]1093 self._arrivalMETAR.get_buffer().connect("changed", self._updateButtons)
[847]1094 self._arrivalMETAR.set_tooltip_text(xstr("landing_metar_tooltip"))
[845]1095 mainBox.pack_start(metarWindow, True, True, 0)
1096
1097 PIREPViewer.addVFiller(mainBox)
1098
1099 table = gtk.Table(2, 4)
1100 mainBox.pack_start(table, False, False, 0)
1101 table.set_row_spacings(4)
1102 table.set_col_spacings(8)
1103
1104 # FIXME: quite the same as in the wizard
1105 if pygobject:
1106 self._star = gtk.ComboBox.new_with_model_and_entry(comboModel)
1107 else:
1108 self._star = gtk.ComboBoxEntry(comboModel)
1109
1110 self._star.set_entry_text_column(0)
1111 self._star.get_child().set_width_chars(10)
1112 self._star.set_tooltip_text(xstr("landing_star_tooltip"))
1113 self._star.connect("changed", self._upperChangedComboBox)
1114
1115 PIREPEditor.tableAttachWidget(table, 0, 0,
1116 xstr("pirepView_star"),
1117 self._star)
1118
1119 # FIXME: quite the same as in the wizard
1120 if pygobject:
1121 self._transition = gtk.ComboBox.new_with_model_and_entry(comboModel)
1122 else:
1123 self._transition = gtk.ComboBoxEntry(comboModel)
1124
1125 self._transition.set_entry_text_column(0)
1126 self._transition.get_child().set_width_chars(10)
1127 self._transition.set_tooltip_text(xstr("landing_transition_tooltip"))
1128 self._transition.connect("changed", self._upperChangedComboBox)
1129
1130 PIREPEditor.tableAttachWidget(table, 2, 0,
1131 xstr("pirepView_transition"),
1132 self._transition)
1133
1134
1135 # FIXME: quite the same as in the wizard
1136 self._approachType = gtk.Entry()
1137 self._approachType.set_width_chars(10)
1138 self._approachType.set_tooltip_text(xstr("landing_approach_tooltip"))
1139 self._approachType.connect("changed", self._upperChanged)
1140
1141 PIREPEditor.tableAttachWidget(table, 0, 1,
1142 xstr("pirepView_approachType"),
1143 self._approachType)
1144
1145 # FIXME: quite the same as in the wizard
1146 self._arrivalRunway = gtk.Entry()
1147 self._arrivalRunway.set_width_chars(10)
1148 self._arrivalRunway.set_tooltip_text(xstr("landing_runway_tooltip"))
1149 self._arrivalRunway.connect("changed", self._upperChanged)
1150
1151 PIREPEditor.tableAttachWidget(table, 2, 1,
1152 xstr("pirepView_runway"),
1153 self._arrivalRunway)
1154
1155 return frame
1156
1157 def _buildStatisticsFrame(self):
1158 """Build the frame for the statistics data."""
1159 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_statistics"))
1160
1161 table = gtk.Table(4, 4)
1162 mainBox.pack_start(table, False, False, 0)
1163 table.set_row_spacings(4)
1164 table.set_col_spacings(8)
1165 table.set_homogeneous(False)
1166
1167 self._blockTimeStart = \
1168 PIREPEditor.tableAttachTimeEntry(table, 0, 0,
1169 xstr("pirepView_blockTimeStart"))
[846]1170 self._blockTimeStart.connect("changed", self._updateButtons)
[847]1171 self._blockTimeStart.set_tooltip_text(xstr("pirepEdit_block_time_start_tooltip"))
[845]1172
1173 self._blockTimeEnd = \
1174 PIREPEditor.tableAttachTimeEntry(table, 2, 0,
1175 xstr("pirepView_blockTimeEnd"))
[846]1176 self._blockTimeEnd.connect("changed", self._updateButtons)
[847]1177 self._blockTimeEnd.set_tooltip_text(xstr("pirepEdit_block_time_end_tooltip"))
[845]1178
1179 self._flightTimeStart = \
1180 PIREPEditor.tableAttachTimeEntry(table, 0, 1,
1181 xstr("pirepView_flightTimeStart"))
[846]1182 self._flightTimeStart.connect("changed", self._updateButtons)
[847]1183 self._flightTimeStart.set_tooltip_text(xstr("pirepEdit_flight_time_start_tooltip"))
[845]1184
1185 self._flightTimeEnd = \
1186 PIREPEditor.tableAttachTimeEntry(table, 2, 1,
1187 xstr("pirepView_flightTimeEnd"))
[846]1188 self._flightTimeEnd.connect("changed", self._updateButtons)
[847]1189 self._flightTimeEnd.set_tooltip_text(xstr("pirepEdit_flight_time_end_tooltip"))
[845]1190
1191 self._flownDistance = PIREPViewer.getDataLabel(width = 3)
1192 PIREPEditor.tableAttachWidget(table, 0, 2,
1193 xstr("pirepView_flownDistance"),
1194 self._flownDistance)
1195
1196 self._fuelUsed = \
1197 PIREPEditor.tableAttachSpinButton(table, 2, 2,
1198 xstr("pirepView_fuelUsed"),
1199 1000000)
[846]1200 self._fuelUsed.connect("value-changed", self._updateButtons)
[847]1201 self._fuelUsed.set_tooltip_text(xstr("pirepEdit_fuel_used_tooltip"))
[845]1202
1203 self._rating = PIREPViewer.getDataLabel(width = 3)
1204 PIREPEditor.tableAttachWidget(table, 0, 3,
1205 xstr("pirepView_rating"),
1206 self._rating)
1207 return frame
1208
1209 def _buildMiscellaneousFrame(self):
1210 """Build the frame for the miscellaneous data."""
1211 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_miscellaneous"))
1212
1213 table = gtk.Table(6, 2)
1214 mainBox.pack_start(table, False, False, 0)
1215 table.set_row_spacings(4)
1216 table.set_col_spacings(8)
1217 table.set_homogeneous(False)
1218
1219 self._flownNumPassengers = \
1220 PIREPEditor.tableAttachSpinButton(table, 0, 0,
1221 xstr("pirepView_numPassengers"),
1222 300)
[846]1223 self._flownNumPassengers.connect("value-changed", self._updateButtons)
[847]1224 self._flownNumPassengers.set_tooltip_text(xstr("payload_pax_tooltip"))
[845]1225
1226 self._flownNumCrew = \
1227 PIREPEditor.tableAttachSpinButton(table, 2, 0,
1228 xstr("pirepView_numCrew"),
1229 10)
[846]1230 self._flownNumCrew.connect("value-changed", self._updateButtons)
[847]1231 self._flownNumCrew.set_tooltip_text(xstr("payload_crew_tooltip"))
[845]1232
1233 self._flownBagWeight = \
1234 PIREPEditor.tableAttachSpinButton(table, 0, 1,
1235 xstr("pirepView_bagWeight"),
1236 100000, width = 6)
[849]1237 self._flownBagWeight.connect("value-changed", self._updateButtons)
[847]1238 self._flownBagWeight.set_tooltip_text(xstr("payload_bag_tooltip"))
[845]1239
1240 self._flownCargoWeight = \
1241 PIREPEditor.tableAttachSpinButton(table, 2, 1,
1242 xstr("pirepView_cargoWeight"),
1243 100000, width = 6)
[849]1244 self._flownCargoWeight.connect("value-changed", self._updateButtons)
[847]1245 self._flownCargoWeight.set_tooltip_text(xstr("payload_cargo_tooltip"))
[845]1246
1247 self._flownMailWeight = \
1248 PIREPEditor.tableAttachSpinButton(table, 4, 1,
1249 xstr("pirepView_mailWeight"),
1250 100000, width = 6)
[849]1251 self._flownMailWeight.connect("value-changed", self._updateButtons)
[847]1252 self._flownMailWeight.set_tooltip_text(xstr("payload_mail_tooltip"))
[845]1253
1254 self._flightType = createFlightTypeComboBox()
1255 PIREPEditor.tableAttachWidget(table, 0, 2,
1256 xstr("pirepView_flightType"),
1257 self._flightType)
[849]1258 self._flightType.connect("changed", self._updateButtons)
[847]1259 self._flightType.set_tooltip_text(xstr("pirepEdit_flight_type_tooltip"))
[845]1260
[847]1261 self._online = gtk.CheckButton(xstr("pirepEdit_online"))
[845]1262 table.attach(self._online, 2, 3, 2, 3)
[849]1263 self._online.connect("toggled", self._updateButtons)
[847]1264 self._online.set_tooltip_text(xstr("pirepEdit_online_tooltip"))
[845]1265
1266 PIREPViewer.addVFiller(mainBox)
1267
1268 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_delayCodes")),
1269 False, False, 0)
1270
1271 (textWindow, self._delayCodes) = PIREPViewer.getTextWindow()
1272 mainBox.pack_start(textWindow, False, False, 0)
[847]1273 self._delayCodes.set_tooltip_text(xstr("pirepEdit_delayCodes_tooltip"))
[845]1274
1275 return frame
1276
1277 def _buildCommentsTab(self):
1278 """Build the tab with the comments and flight defects."""
[846]1279 return FlightInfo(self._gui, callbackObject = self)
[845]1280
1281 def _buildLogTab(self):
1282 """Build the log tab."""
1283 mainBox = gtk.VBox()
1284
1285 (logWindow, self._log) = PIREPViewer.getTextWindow(heightRequest = -1)
1286 addFaultTag(self._log.get_buffer())
1287 mainBox.pack_start(logWindow, True, True, 0)
1288
1289 return mainBox
1290
1291 def _upperChanged(self, entry, arg = None):
1292 """Called when the value of some entry widget has changed and the value
1293 should be converted to uppercase."""
1294 entry.set_text(entry.get_text().upper())
[846]1295 self._updateButtons()
[845]1296 #self._valueChanged(entry, arg)
1297
1298 def _upperChangedComboBox(self, comboBox):
1299 """Called for combo box widgets that must be converted to uppercase."""
1300 entry = comboBox.get_child()
1301 if comboBox.get_active()==-1:
1302 entry.set_text(entry.get_text().upper())
[846]1303 self._updateButtons()
[845]1304 #self._valueChanged(entry)
1305
[846]1306 def _updateButtons(self, *kwargs):
1307 """Update the activity state of the buttons."""
1308 pirep = self._pirep
1309 bookedFlight = pirep.bookedFlight
1310
1311 departureMinutes = \
1312 bookedFlight.departureTime.hour*60 + bookedFlight.departureTime.minute
1313 departureDifference = abs(Flight.getMinutesDifference(self._blockTimeStart.minutes,
1314 departureMinutes))
1315 flightStartDifference = \
1316 Flight.getMinutesDifference(self._flightTimeStart.minutes,
1317 self._blockTimeStart.minutes)
1318 arrivalMinutes = \
1319 bookedFlight.arrivalTime.hour*60 + bookedFlight.arrivalTime.minute
1320 arrivalDifference = abs(Flight.getMinutesDifference(self._blockTimeEnd.minutes,
1321 arrivalMinutes))
1322 flightEndDifference = \
1323 Flight.getMinutesDifference(self._blockTimeEnd.minutes,
1324 self._flightTimeEnd.minutes)
1325
1326 timesOK = self._flightInfo.hasComments or \
1327 self._flightInfo.hasDelayCode or \
1328 (departureDifference<=Flight.TIME_ERROR_DIFFERENCE and
1329 arrivalDifference<=Flight.TIME_ERROR_DIFFERENCE and
1330 flightStartDifference>=0 and flightStartDifference<30 and
1331 flightEndDifference>=0 and flightEndDifference<30)
1332
1333 text = self._sid.get_child().get_text()
1334 sid = text if self._sid.get_active()!=0 and text and text!="N/A" \
1335 else None
1336
1337 text = self._star.get_child().get_text()
1338 star = text if self._star.get_active()!=0 and text and text!="N/A" \
1339 else None
1340
1341 text = self._transition.get_child().get_text()
1342 transition = text if self._transition.get_active()!=0 \
1343 and text and text!="N/A" else None
1344
1345
1346 buffer = self._userRoute.get_buffer()
1347 route = buffer.get_text(buffer.get_start_iter(),
1348 buffer.get_end_iter(), True)
1349
[849]1350 self._okButton.set_sensitive(self._modified and timesOK and
[846]1351 self._flightInfo.faultsFullyExplained and
1352 self._flownNumPassengers.get_value_as_int()>0 and
1353 self._flownNumCrew.get_value_as_int()>2 and
1354 self._fuelUsed.get_value_as_int()>0 and
1355 self._departureRunway.get_text_length()>0 and
1356 self._arrivalRunway.get_text_length()>0 and
1357 self._departureMETAR.get_buffer().get_char_count()>0 and
1358 self._arrivalMETAR.get_buffer().get_char_count()>0 and
1359 self._filedCruiseLevel.get_value_as_int()>=50 and
1360 self._modifiedCruiseLevel.get_value_as_int()>=50 and
1361 sid is not None and (star is not None or
1362 transition is not None) and route!="" and
1363 self._approachType.get_text()!="")
1364
[845]1365#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.