source: src/mlx/gui/pirep.py@ 852:fff6327db8e6

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

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

File size: 52.5 KB
Line 
1
2from common import *
3from dcdata import getTable
4from info import FlightInfo
5from flight import comboModel
6
7from mlx.pirep import PIREP
8from mlx.flight import Flight
9from mlx.const import *
10
11import time
12import re
13
14#------------------------------------------------------------------------------
15
16## @package mlx.gui.pirep
17#
18# The detailed PIREP viewer and editor windows.
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
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
36 contents.
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)
50
51 return (frame, box)
52
53 @staticmethod
54 def getLabel(text, extraText = ""):
55 """Get a bold label with the given text."""
56 label = gtk.Label("<b>" + text + "</b>" + extraText)
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
71 def getTextWindow(heightRequest = 40, editable = False):
72 """Get a scrollable text window.
73
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)
83 textView.set_editable(editable)
84 textView.set_cursor_visible(editable)
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
94 table.
95
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)
102
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.
112
113 Returns the data label."""
114 label = PIREPViewer.getLabel(labelText)
115 hBox.pack_start(label, False, False, 0)
116
117 dataLabel = PIREPViewer.getDataLabel(width = width)
118 hBox.pack_start(dataLabel, False, False, dataPadding)
119
120 return dataLabel
121
122 @staticmethod
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
131 def addVFiller(vBox, height = 4):
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)
135 filler.set_size_request(-1, height)
136 vBox.pack_start(filler, False, False, 0)
137
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)
151
152 self.set_resizable(False)
153
154 self._gui = gui
155
156 contentArea = self.get_content_area()
157
158 self._notebook = gtk.Notebook()
159 contentArea.pack_start(self._notebook, False, False, 4)
160
161 dataTab = self._buildDataTab()
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)
166
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)
172
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)
178
179 self._okButton = self.add_button(xstr("button_ok"), RESPONSETYPE_OK)
180 self._okButton.set_can_default(True)
181
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)
190
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))
206
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)
233
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
243 self._flownNumCrew.set_text("%d" % (pirep.numCrew,))
244 self._flownNumPassengers.set_text("%d" % (pirep.numPassengers,))
245 self._flownBagWeight.set_text("%.0f" % (pirep.bagWeight,))
246 self._flownCargoWeight.set_text("%.0f" % (pirep.cargoWeight,))
247 self._flownMailWeight.set_text("%.0f" % (pirep.mailWeight,))
248 self._flightType.set_text(xstr("flighttype_" +
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 += ", "
256 delayCodes += code
257
258 self._delayCodes.get_buffer().set_text(delayCodes)
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("")
265 lineIndex = 0
266 for (timeStr, line) in pirep.logLines:
267 isFault = lineIndex in pirep.faultLineIndexes
268 appendTextBuffer(logBuffer,
269 formatFlightLogLine(timeStr, line),
270 isFault = isFault)
271 lineIndex += 1
272
273 self._notebook.set_current_page(0)
274 self._okButton.grab_default()
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)
285
286 box2 = gtk.VBox()
287 table.attach(box2, 1, 2, 0, 1)
288
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."""
311
312 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_flight"))
313
314 dataBox = gtk.HBox()
315 mainBox.pack_start(dataBox, False, False, 0)
316
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)
342 table.set_col_spacings(8)
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)
367 table.set_col_spacings(8)
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 = \
380 PIREPViewer.tableAttach(table, 0, 1,
381 xstr("pirepView_bagWeight"),
382 width = 5)
383
384 self._cargoWeight = \
385 PIREPViewer.tableAttach(table, 1, 1,
386 xstr("pirepView_cargoWeight"),
387 width = 5)
388
389 self._mailWeight = \
390 PIREPViewer.tableAttach(table, 2, 1,
391 xstr("pirepView_mailWeight"),
392 width = 5)
393
394 PIREPViewer.addVFiller(mainBox)
395
396 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_route")),
397 False, False, 0)
398
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."""
407
408 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_route"))
409
410 levelBox = gtk.HBox()
411 mainBox.pack_start(levelBox, False, False, 0)
412
413 self._filedCruiseLevel = \
414 PIREPViewer.addLabeledData(levelBox,
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):
431 """Build the frame for the departure data."""
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)
444
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
456
457 def _buildArrivalFrame(self):
458 """Build the frame for the arrival data."""
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)
472 table.set_col_spacings(8)
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)
483
484 self._approachType = \
485 PIREPViewer.tableAttach(table, 0, 1,
486 xstr("pirepView_approachType"),
487 width = 7)
488
489 self._arrivalRunway = \
490 PIREPViewer.tableAttach(table, 1, 1,
491 xstr("pirepView_runway"),
492 width = 5)
493
494 return frame
495
496 def _buildStatisticsFrame(self):
497 """Build the frame for the statistics data."""
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)
504 table.set_homogeneous(False)
505
506 self._blockTimeStart = \
507 PIREPViewer.tableAttach(table, 0, 0,
508 xstr("pirepView_blockTimeStart"),
509 width = 6)
510
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)
520
521 self._flightTimeEnd = \
522 PIREPViewer.tableAttach(table, 1, 1,
523 xstr("pirepView_flightTimeEnd"),
524 width = 6)
525
526 self._flownDistance = \
527 PIREPViewer.tableAttach(table, 0, 2,
528 xstr("pirepView_flownDistance"),
529 width = 8)
530
531 self._fuelUsed = \
532 PIREPViewer.tableAttach(table, 1, 2,
533 xstr("pirepView_fuelUsed"),
534 width = 6)
535
536 self._rating = \
537 PIREPViewer.tableAttach(table, 0, 3,
538 xstr("pirepView_rating"),
539 width = 7)
540 return frame
541
542 def _buildMiscellaneousFrame(self):
543 """Build the frame for the miscellaneous data."""
544 (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_miscellaneous"))
545
546 table = gtk.Table(3, 2)
547 mainBox.pack_start(table, False, False, 0)
548 table.set_row_spacings(4)
549 table.set_col_spacings(8)
550
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
566 self._flownCargoWeight = \
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)
575
576 self._flightType = \
577 PIREPViewer.tableAttach(table, 0, 2,
578 xstr("pirepView_flightType"),
579 width = 15)
580
581 self._online = \
582 PIREPViewer.tableAttach(table, 1, 2,
583 xstr("pirepView_online"),
584 width = 5)
585
586 PIREPViewer.addVFiller(mainBox)
587
588 mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_delayCodes")),
589 False, False, 0)
590
591 (textWindow, self._delayCodes) = PIREPViewer.getTextWindow()
592 mainBox.pack_start(textWindow, False, False, 0)
593
594 return frame
595
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)
616
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)
624 addFaultTag(self._log.get_buffer())
625 mainBox.pack_start(logWindow, True, True, 0)
626
627 return mainBox
628
629#------------------------------------------------------------------------------
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
695 self._pirep = None
696
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
720 self.add_button(xstr("button_cancel"), RESPONSETYPE_CANCEL)
721
722 self._okButton = self.add_button(xstr("button_save"), RESPONSETYPE_OK)
723 self._okButton.set_can_default(True)
724 self._modified = False
725
726 def setPIREP(self, pirep):
727 """Setup the data in the dialog from the given PIREP."""
728 self._pirep = pirep
729
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
845 self._modified = False
846 self._updateButtons()
847 self._modified = True
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
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)
1004 self._filedCruiseLevel.set_tooltip_text(xstr("route_level_tooltip"))
1005 self._filedCruiseLevel.set_numeric(True)
1006 self._filedCruiseLevel.connect("value-changed", self._updateButtons)
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)
1019 self._modifiedCruiseLevel.set_tooltip_text(xstr("pirepEdit_modified_route_level_tooltip"))
1020 self._modifiedCruiseLevel.set_numeric(True)
1021 self._modifiedCruiseLevel.connect("value-changed", self._updateButtons)
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)
1030 self._userRoute.get_buffer().connect("changed", self._updateButtons)
1031 self._userRoute.set_tooltip_text(xstr("route_route_tooltip"))
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)
1044 self._departureMETAR.get_buffer().connect("changed", self._updateButtons)
1045 self._departureMETAR.set_tooltip_text(xstr("takeoff_metar_tooltip"))
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)
1093 self._arrivalMETAR.get_buffer().connect("changed", self._updateButtons)
1094 self._arrivalMETAR.set_tooltip_text(xstr("landing_metar_tooltip"))
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"))
1170 self._blockTimeStart.connect("changed", self._updateButtons)
1171 self._blockTimeStart.set_tooltip_text(xstr("pirepEdit_block_time_start_tooltip"))
1172
1173 self._blockTimeEnd = \
1174 PIREPEditor.tableAttachTimeEntry(table, 2, 0,
1175 xstr("pirepView_blockTimeEnd"))
1176 self._blockTimeEnd.connect("changed", self._updateButtons)
1177 self._blockTimeEnd.set_tooltip_text(xstr("pirepEdit_block_time_end_tooltip"))
1178
1179 self._flightTimeStart = \
1180 PIREPEditor.tableAttachTimeEntry(table, 0, 1,
1181 xstr("pirepView_flightTimeStart"))
1182 self._flightTimeStart.connect("changed", self._updateButtons)
1183 self._flightTimeStart.set_tooltip_text(xstr("pirepEdit_flight_time_start_tooltip"))
1184
1185 self._flightTimeEnd = \
1186 PIREPEditor.tableAttachTimeEntry(table, 2, 1,
1187 xstr("pirepView_flightTimeEnd"))
1188 self._flightTimeEnd.connect("changed", self._updateButtons)
1189 self._flightTimeEnd.set_tooltip_text(xstr("pirepEdit_flight_time_end_tooltip"))
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)
1200 self._fuelUsed.connect("value-changed", self._updateButtons)
1201 self._fuelUsed.set_tooltip_text(xstr("pirepEdit_fuel_used_tooltip"))
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)
1223 self._flownNumPassengers.connect("value-changed", self._updateButtons)
1224 self._flownNumPassengers.set_tooltip_text(xstr("payload_pax_tooltip"))
1225
1226 self._flownNumCrew = \
1227 PIREPEditor.tableAttachSpinButton(table, 2, 0,
1228 xstr("pirepView_numCrew"),
1229 10)
1230 self._flownNumCrew.connect("value-changed", self._updateButtons)
1231 self._flownNumCrew.set_tooltip_text(xstr("payload_crew_tooltip"))
1232
1233 self._flownBagWeight = \
1234 PIREPEditor.tableAttachSpinButton(table, 0, 1,
1235 xstr("pirepView_bagWeight"),
1236 100000, width = 6)
1237 self._flownBagWeight.connect("value-changed", self._updateButtons)
1238 self._flownBagWeight.set_tooltip_text(xstr("payload_bag_tooltip"))
1239
1240 self._flownCargoWeight = \
1241 PIREPEditor.tableAttachSpinButton(table, 2, 1,
1242 xstr("pirepView_cargoWeight"),
1243 100000, width = 6)
1244 self._flownCargoWeight.connect("value-changed", self._updateButtons)
1245 self._flownCargoWeight.set_tooltip_text(xstr("payload_cargo_tooltip"))
1246
1247 self._flownMailWeight = \
1248 PIREPEditor.tableAttachSpinButton(table, 4, 1,
1249 xstr("pirepView_mailWeight"),
1250 100000, width = 6)
1251 self._flownMailWeight.connect("value-changed", self._updateButtons)
1252 self._flownMailWeight.set_tooltip_text(xstr("payload_mail_tooltip"))
1253
1254 self._flightType = createFlightTypeComboBox()
1255 PIREPEditor.tableAttachWidget(table, 0, 2,
1256 xstr("pirepView_flightType"),
1257 self._flightType)
1258 self._flightType.connect("changed", self._updateButtons)
1259 self._flightType.set_tooltip_text(xstr("pirepEdit_flight_type_tooltip"))
1260
1261 self._online = gtk.CheckButton(xstr("pirepEdit_online"))
1262 table.attach(self._online, 2, 3, 2, 3)
1263 self._online.connect("toggled", self._updateButtons)
1264 self._online.set_tooltip_text(xstr("pirepEdit_online_tooltip"))
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)
1273 self._delayCodes.set_tooltip_text(xstr("pirepEdit_delayCodes_tooltip"))
1274
1275 return frame
1276
1277 def _buildCommentsTab(self):
1278 """Build the tab with the comments and flight defects."""
1279 return FlightInfo(self._gui, callbackObject = self)
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())
1295 self._updateButtons()
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())
1303 self._updateButtons()
1304 #self._valueChanged(entry)
1305
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
1350 self._okButton.set_sensitive(self._modified and timesOK and
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
1365#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.