source: src/mlx/gui/pirep.py@ 919:2ce8ca39525b

python3
Last change on this file since 919:2ce8ca39525b was 919:2ce8ca39525b, checked in by István Váradi <ivaradi@…>, 5 years ago

Ran 2to3

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