source: src/mlx/gui/flight.py@ 96:aa6a0b79c073

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

The contents of log lines can be modified after they are written, and we are using it for Vref

File size: 76.4 KB
Line 
1# The flight handling "wizard"
2
3from mlx.gui.common import *
4
5import mlx.const as const
6import mlx.fs as fs
7from mlx.checks import PayloadChecker
8import mlx.util as util
9
10import datetime
11import time
12
13#------------------------------------------------------------------------------
14
15acftTypeNames = { const.AIRCRAFT_B736: "Boeing 737-600",
16 const.AIRCRAFT_B737: "Boeing 737-700",
17 const.AIRCRAFT_B738: "Boeing 737-800",
18 const.AIRCRAFT_DH8D: "Bombardier Dash 8-Q400",
19 const.AIRCRAFT_B733: "Boeing 737-300",
20 const.AIRCRAFT_B734: "Boeing 737-400",
21 const.AIRCRAFT_B735: "Boeing 737-500",
22 const.AIRCRAFT_B762: "Boeing 767-200",
23 const.AIRCRAFT_B763: "Boeing 767-300",
24 const.AIRCRAFT_CRJ2: "Bombardier CRJ200",
25 const.AIRCRAFT_F70: "Fokker 70",
26 const.AIRCRAFT_DC3: "Lisunov Li-2",
27 const.AIRCRAFT_T134: "Tupolev Tu-134",
28 const.AIRCRAFT_T154: "Tupolev Tu-154",
29 const.AIRCRAFT_YK40: "Yakovlev Yak-40" }
30
31#-----------------------------------------------------------------------------
32
33class Page(gtk.Alignment):
34 """A page in the flight wizard."""
35 def __init__(self, wizard, title, help, completedHelp = None):
36 """Construct the page."""
37 super(Page, self).__init__(xalign = 0.0, yalign = 0.0,
38 xscale = 1.0, yscale = 1.0)
39 self.set_padding(padding_top = 4, padding_bottom = 4,
40 padding_left = 12, padding_right = 12)
41
42 frame = gtk.Frame()
43 self.add(frame)
44
45 style = self.get_style() if pygobject else self.rc_get_style()
46
47 self._vbox = gtk.VBox()
48 self._vbox.set_homogeneous(False)
49 frame.add(self._vbox)
50
51 eventBox = gtk.EventBox()
52 eventBox.modify_bg(0, style.bg[3])
53
54 alignment = gtk.Alignment(xalign = 0.0, xscale = 0.0)
55
56 label = gtk.Label(title)
57 label.modify_fg(0, style.fg[3])
58 label.modify_font(pango.FontDescription("bold 24"))
59 alignment.set_padding(padding_top = 4, padding_bottom = 4,
60 padding_left = 6, padding_right = 0)
61
62 alignment.add(label)
63 eventBox.add(alignment)
64
65 self._vbox.pack_start(eventBox, False, False, 0)
66
67 mainBox = gtk.VBox()
68
69 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
70 xscale = 1.0, yscale = 1.0)
71 alignment.set_padding(padding_top = 16, padding_bottom = 16,
72 padding_left = 16, padding_right = 16)
73 alignment.add(mainBox)
74 self._vbox.pack_start(alignment, True, True, 0)
75
76 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
77 xscale = 0.0, yscale = 0.0)
78 alignment.set_padding(padding_top = 0, padding_bottom = 16,
79 padding_left = 0, padding_right = 0)
80
81 self._help = help
82 self._completedHelp = completedHelp
83
84 if self._completedHelp is None or \
85 len(help.splitlines())>=len(completedHelp.splitlines()):
86 longerHelp = help
87 else:
88 longerHelp = completedHelp
89
90 self._helpLabel = gtk.Label(completedHelp)
91 # FIXME: should be a constant in common
92 self._helpLabel.set_justify(gtk.Justification.CENTER if pygobject
93 else gtk.JUSTIFY_CENTER)
94 self._helpLabel.set_use_markup(True)
95 alignment.add(self._helpLabel)
96 mainBox.pack_start(alignment, False, False, 0)
97
98 self._mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
99 xscale = 1.0, yscale = 1.0)
100 mainBox.pack_start(self._mainAlignment, True, True, 0)
101
102 buttonAlignment = gtk.Alignment(xalign = 1.0, xscale=0.0, yscale = 0.0)
103 buttonAlignment.set_padding(padding_top = 4, padding_bottom = 10,
104 padding_left = 16, padding_right = 16)
105
106 self._buttonBox = gtk.HBox()
107 self._buttonBox.set_homogeneous(False)
108 self._defaultButton = None
109 buttonAlignment.add(self._buttonBox)
110
111 self._vbox.pack_start(buttonAlignment, False, False, 0)
112
113 self._wizard = wizard
114
115 self._completed = False
116 self._fromPage = None
117
118 def setMainWidget(self, widget):
119 """Set the given widget as the main one."""
120 self._mainAlignment.add(widget)
121
122 def addButton(self, label, default = False):
123 """Add a button with the given label.
124
125 Return the button object created."""
126 button = gtk.Button(label)
127 self._buttonBox.pack_start(button, False, False, 4)
128 button.set_use_underline(True)
129 if default:
130 button.set_can_default(True)
131 self._defaultButton = button
132 return button
133
134 def initialize(self):
135 """Initialize the page.
136
137 It sets up the primary help, and calls the activate() function."""
138 self._helpLabel.set_markup(self._help)
139 self._helpLabel.set_sensitive(True)
140 self.activate()
141
142 def activate(self):
143 """Called when this page becomes active.
144
145 This default implementation does nothing."""
146 pass
147
148 def complete(self):
149 """Called when the page is completed.
150
151 It greys out/changes the help text and then calls finalize()."""
152 self.finalize()
153 if self._completedHelp is None:
154 self._helpLabel.set_sensitive(False)
155 else:
156 self._helpLabel.set_markup(self._completedHelp)
157 self._completed = True
158
159 def finalize(self):
160 """Called when the page is finalized."""
161 pass
162
163 def grabDefault(self):
164 """If the page has a default button, make it the default one."""
165 if self._defaultButton is not None:
166 self._defaultButton.grab_default()
167
168 def reset(self):
169 """Reset the page if the wizard is reset."""
170 self._completed = False
171 self._fromPage = None
172
173 def goBack(self):
174 """Go to the page we were invoked from."""
175 assert self._fromPage is not None
176
177 self._wizard.setCurrentPage(self._fromPage, finalize = False)
178
179#-----------------------------------------------------------------------------
180
181class LoginPage(Page):
182 """The login page."""
183 def __init__(self, wizard):
184 """Construct the login page."""
185 help = "Enter your MAVA pilot's ID and password to\n" \
186 "log in to the MAVA website and download\n" \
187 "your booked flights."
188 super(LoginPage, self).__init__(wizard, "Login", help)
189
190 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
191 xscale = 0.0, yscale = 0.0)
192
193 table = gtk.Table(2, 3)
194 table.set_row_spacings(4)
195 table.set_col_spacings(32)
196 alignment.add(table)
197 self.setMainWidget(alignment)
198
199 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
200 label = gtk.Label("Pilot _ID:")
201 label.set_use_underline(True)
202 labelAlignment.add(label)
203 table.attach(labelAlignment, 0, 1, 0, 1)
204
205 self._pilotID = gtk.Entry()
206 self._pilotID.connect("changed", self._setLoginButton)
207 self._pilotID.set_tooltip_text("Enter your MAVA pilot's ID. This "
208 "usually starts with a "
209 "'P' followed by 3 digits.")
210 table.attach(self._pilotID, 1, 2, 0, 1)
211 label.set_mnemonic_widget(self._pilotID)
212
213 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
214 label = gtk.Label("_Password:")
215 label.set_use_underline(True)
216 labelAlignment.add(label)
217 table.attach(labelAlignment, 0, 1, 1, 2)
218
219 self._password = gtk.Entry()
220 self._password.set_visibility(False)
221 self._password.connect("changed", self._setLoginButton)
222 self._password.set_tooltip_text("Enter the password for your pilot's ID")
223 table.attach(self._password, 1, 2, 1, 2)
224 label.set_mnemonic_widget(self._password)
225
226 self._rememberButton = gtk.CheckButton("_Remember password")
227 self._rememberButton.set_use_underline(True)
228 self._rememberButton.set_tooltip_text("If checked, your password will "
229 "be stored, so that you should "
230 "not have to enter it every time. "
231 "Note, however, that the password "
232 "is stored as text, and anybody "
233 "who can access your files will "
234 "be able to read it.")
235 table.attach(self._rememberButton, 1, 2, 2, 3, ypadding = 8)
236
237 self._loginButton = self.addButton("_Login", default = True)
238 self._loginButton.set_sensitive(False)
239 self._loginButton.connect("clicked", self._loginClicked)
240 self._loginButton.set_tooltip_text("Click to log in.")
241
242 def activate(self):
243 """Activate the page."""
244 config = self._wizard.gui.config
245 self._pilotID.set_text(config.pilotID)
246 self._password.set_text(config.password)
247 self._rememberButton.set_active(config.rememberPassword)
248
249 def _setLoginButton(self, entry):
250 """Set the login button's sensitivity.
251
252 The button is sensitive only if both the pilot ID and the password
253 fields contain values."""
254 self._loginButton.set_sensitive(self._pilotID.get_text()!="" and
255 self._password.get_text()!="")
256
257 def _loginClicked(self, button):
258 """Called when the login button was clicked."""
259 self._loginButton.set_sensitive(False)
260 gui = self._wizard.gui
261 gui.beginBusy("Logging in...")
262 gui.webHandler.login(self._loginResultCallback,
263 self._pilotID.get_text(),
264 self._password.get_text())
265
266 def _loginResultCallback(self, returned, result):
267 """The login result callback, called in the web handler's thread."""
268 gobject.idle_add(self._handleLoginResult, returned, result)
269
270 def _handleLoginResult(self, returned, result):
271 """Handle the login result."""
272 self._wizard.gui.endBusy()
273 self._loginButton.set_sensitive(True)
274 if returned:
275 if result.loggedIn:
276 config = self._wizard.gui.config
277
278 config.pilotID = self._pilotID.get_text()
279
280 rememberPassword = self._rememberButton.get_active()
281 config.password = self._password.get_text() if rememberPassword \
282 else ""
283
284 config.rememberPassword = rememberPassword
285
286 config.save()
287 self._wizard._loginResult = result
288 self._wizard.nextPage()
289 else:
290 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
291 buttons = BUTTONSTYPE_OK,
292 message_format =
293 "Invalid pilot's ID or password.")
294 dialog.format_secondary_markup("Check the ID and try to reenter"
295 " the password.")
296 dialog.run()
297 dialog.hide()
298 else:
299 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
300 buttons = BUTTONSTYPE_OK,
301 message_format =
302 "Failed to connect to the MAVA website.")
303 dialog.format_secondary_markup("Try again in a few minutes.")
304 dialog.run()
305 dialog.hide()
306
307#-----------------------------------------------------------------------------
308
309class FlightSelectionPage(Page):
310 """The page to select the flight."""
311 def __init__(self, wizard):
312 """Construct the flight selection page."""
313 help = "Select the flight you want to perform."
314 completedHelp = "You have selected the flight highlighted below."
315 super(FlightSelectionPage, self).__init__(wizard, "Flight selection",
316 help, completedHelp = completedHelp)
317
318
319 self._listStore = gtk.ListStore(str, str, str, str)
320 self._flightList = gtk.TreeView(self._listStore)
321 column = gtk.TreeViewColumn("Flight no.", gtk.CellRendererText(),
322 text = 1)
323 column.set_expand(True)
324 self._flightList.append_column(column)
325 column = gtk.TreeViewColumn("Departure time [UTC]", gtk.CellRendererText(),
326 text = 0)
327 column.set_expand(True)
328 self._flightList.append_column(column)
329 column = gtk.TreeViewColumn("From", gtk.CellRendererText(),
330 text = 2)
331 column.set_expand(True)
332 self._flightList.append_column(column)
333 column = gtk.TreeViewColumn("To", gtk.CellRendererText(),
334 text = 3)
335 column.set_expand(True)
336 self._flightList.append_column(column)
337
338 flightSelection = self._flightList.get_selection()
339 flightSelection.connect("changed", self._selectionChanged)
340
341 scrolledWindow = gtk.ScrolledWindow()
342 scrolledWindow.add(self._flightList)
343 scrolledWindow.set_size_request(400, -1)
344 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
345 else gtk.POLICY_AUTOMATIC,
346 gtk.PolicyType.AUTOMATIC if pygobject
347 else gtk.POLICY_AUTOMATIC)
348 scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
349 else gtk.SHADOW_IN)
350
351 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 0.0, yscale = 1.0)
352 alignment.add(scrolledWindow)
353
354 self.setMainWidget(alignment)
355
356 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
357 self._button.set_use_stock(True)
358 self._button.set_sensitive(False)
359 self._button.connect("clicked", self._forwardClicked)
360
361 def activate(self):
362 """Fill the flight list."""
363 self._flightList.set_sensitive(True)
364 self._listStore.clear()
365 for flight in self._wizard.loginResult.flights:
366 self._listStore.append([str(flight.departureTime),
367 flight.callsign,
368 flight.departureICAO,
369 flight.arrivalICAO])
370
371 def finalize(self):
372 """Finalize the page."""
373 self._flightList.set_sensitive(False)
374
375 def _selectionChanged(self, selection):
376 """Called when the selection is changed."""
377 self._button.set_sensitive(selection.count_selected_rows()==1)
378
379 def _forwardClicked(self, button):
380 """Called when the forward button was clicked."""
381 if self._completed:
382 self._wizard.jumpPage(self._nextDistance, finalize = False)
383 else:
384 selection = self._flightList.get_selection()
385 (listStore, iter) = selection.get_selected()
386 path = listStore.get_path(iter)
387 [index] = path.get_indices() if pygobject else path
388
389 flight = self._wizard.loginResult.flights[index]
390 self._wizard._bookedFlight = flight
391 # FIXME: with PyGObject this call causes error messages to
392 # appear on the standard output
393 self._wizard.gui.enableFlightInfo()
394
395 self._updateDepartureGate()
396
397 def _updateDepartureGate(self):
398 """Update the departure gate for the booked flight."""
399 flight = self._wizard._bookedFlight
400 if flight.departureICAO=="LHBP":
401 self._wizard._getFleet(self._fleetRetrieved)
402 else:
403 self._nextDistance = 2
404 self._wizard.jumpPage(2)
405
406 def _fleetRetrieved(self, fleet):
407 """Called when the fleet has been retrieved."""
408 if fleet is None:
409 self._nextDistance = 2
410 self._wizard.jumpPage(2)
411 else:
412 plane = fleet[self._wizard._bookedFlight.tailNumber]
413 if plane is None:
414 self._nextDistance = 2
415 self._wizard.jumpPage(2)
416 elif plane.gateNumber is not None and \
417 not fleet.isGateConflicting(plane):
418 self._wizard._departureGate = plane.gateNumber
419 self._nextDistance = 2
420 self._wizard.jumpPage(2)
421 else:
422 self._nextDistance = 1
423 self._wizard.nextPage()
424
425#-----------------------------------------------------------------------------
426
427class GateSelectionPage(Page):
428 """Page to select a free gate at LHBP.
429
430 This page should be displayed only if we have fleet information!."""
431 def __init__(self, wizard):
432 """Construct the gate selection page."""
433 help = "The airplane's gate position is invalid.\n\n" \
434 "Select the gate from which you\n" \
435 "would like to begin the flight."
436 super(GateSelectionPage, self).__init__(wizard,
437 "LHBP gate selection",
438 help)
439
440 self._listStore = gtk.ListStore(str)
441 self._gateList = gtk.TreeView(self._listStore)
442 column = gtk.TreeViewColumn(None, gtk.CellRendererText(),
443 text = 0)
444 column.set_expand(True)
445 self._gateList.append_column(column)
446 self._gateList.set_headers_visible(False)
447
448 gateSelection = self._gateList.get_selection()
449 gateSelection.connect("changed", self._selectionChanged)
450
451 scrolledWindow = gtk.ScrolledWindow()
452 scrolledWindow.add(self._gateList)
453 scrolledWindow.set_size_request(50, -1)
454 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
455 else gtk.POLICY_AUTOMATIC,
456 gtk.PolicyType.AUTOMATIC if pygobject
457 else gtk.POLICY_AUTOMATIC)
458 scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
459 else gtk.SHADOW_IN)
460
461 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 0.0, yscale = 1.0)
462 alignment.add(scrolledWindow)
463
464 self.setMainWidget(alignment)
465
466 button = self.addButton(gtk.STOCK_GO_BACK)
467 button.set_use_stock(True)
468 button.connect("clicked", self._backClicked)
469
470 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
471 self._button.set_use_stock(True)
472 self._button.set_sensitive(False)
473 self._button.connect("clicked", self._forwardClicked)
474
475 def activate(self):
476 """Fill the gate list."""
477 self._listStore.clear()
478 self._gateList.set_sensitive(True)
479 occupiedGateNumbers = self._wizard._fleet.getOccupiedGateNumbers()
480 for gateNumber in const.lhbpGateNumbers:
481 if gateNumber not in occupiedGateNumbers:
482 self._listStore.append([gateNumber])
483
484 def finalize(self):
485 """Finalize the page."""
486 self._gateList.set_sensitive(False)
487
488 def _selectionChanged(self, selection):
489 """Called when the selection is changed."""
490 self._button.set_sensitive(selection.count_selected_rows()==1)
491
492 def _backClicked(self, button):
493 """Called when the Back button is pressed."""
494 self.goBack()
495
496 def _forwardClicked(self, button):
497 """Called when the forward button is clicked."""
498 if not self._completed:
499 selection = self._gateList.get_selection()
500 (listStore, iter) = selection.get_selected()
501 (gateNumber,) = listStore.get(iter, 0)
502
503 self._wizard._departureGate = gateNumber
504
505 #self._wizard._updatePlane(self._planeUpdated,
506 # self._wizard._bookedFlight.tailNumber,
507 # const.PLANE_HOME,
508 # gateNumber)
509
510 self._wizard.nextPage()
511
512 def _planeUpdated(self, success):
513 """Callback for the plane updating call."""
514 if success is None or success:
515 self._wizard.nextPage()
516 else:
517 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
518 buttons = BUTTONSTYPE_OK,
519 message_format = "Gate conflict detected again")
520 dialog.format_secondary_markup("Try to select a different gate.")
521 dialog.run()
522 dialog.hide()
523
524 self._wizard._getFleet(self._fleetRetrieved)
525
526 def _fleetRetrieved(self, fleet):
527 """Called when the fleet has been retrieved."""
528 if fleet is None:
529 self._wizard.nextPage()
530 else:
531 self.activate()
532
533#-----------------------------------------------------------------------------
534
535class ConnectPage(Page):
536 """Page which displays the departure airport and gate (if at LHBP)."""
537 def __init__(self, wizard):
538 """Construct the connect page."""
539 help = "Load the aircraft below into the simulator and park it\n" \
540 "at the given airport, at the gate below, if present.\n\n" \
541 "Then press the Connect button to connect to the simulator."
542 completedHelp = "The basic data of your flight can be read below."
543 super(ConnectPage, self).__init__(wizard,
544 "Connect to the simulator",
545 help, completedHelp = completedHelp)
546
547 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
548 xscale = 0.0, yscale = 0.0)
549
550 table = gtk.Table(5, 2)
551 table.set_row_spacings(4)
552 table.set_col_spacings(16)
553 table.set_homogeneous(True)
554 alignment.add(table)
555 self.setMainWidget(alignment)
556
557 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
558 label = gtk.Label("Flight number:")
559 labelAlignment.add(label)
560 table.attach(labelAlignment, 0, 1, 0, 1)
561
562 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
563 self._flightNumber = gtk.Label()
564 self._flightNumber.set_width_chars(7)
565 self._flightNumber.set_alignment(0.0, 0.5)
566 labelAlignment.add(self._flightNumber)
567 table.attach(labelAlignment, 1, 2, 0, 1)
568
569 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
570 label = gtk.Label("Aircraft:")
571 labelAlignment.add(label)
572 table.attach(labelAlignment, 0, 1, 1, 2)
573
574 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
575 self._aircraft = gtk.Label()
576 self._aircraft.set_width_chars(25)
577 self._aircraft.set_alignment(0.0, 0.5)
578 labelAlignment.add(self._aircraft)
579 table.attach(labelAlignment, 1, 2, 1, 2)
580
581 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
582 label = gtk.Label("Tail number:")
583 labelAlignment.add(label)
584 table.attach(labelAlignment, 0, 1, 2, 3)
585
586 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
587 self._tailNumber = gtk.Label()
588 self._tailNumber.set_width_chars(10)
589 self._tailNumber.set_alignment(0.0, 0.5)
590 labelAlignment.add(self._tailNumber)
591 table.attach(labelAlignment, 1, 2, 2, 3)
592
593 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
594 label = gtk.Label("Airport:")
595 labelAlignment.add(label)
596 table.attach(labelAlignment, 0, 1, 3, 4)
597
598 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
599 self._departureICAO = gtk.Label()
600 self._departureICAO.set_width_chars(6)
601 self._departureICAO.set_alignment(0.0, 0.5)
602 labelAlignment.add(self._departureICAO)
603 table.attach(labelAlignment, 1, 2, 3, 4)
604
605 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
606 label = gtk.Label("Gate:")
607 labelAlignment.add(label)
608 table.attach(labelAlignment, 0, 1, 4, 5)
609
610 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
611 self._departureGate = gtk.Label()
612 self._departureGate.set_width_chars(5)
613 self._departureGate.set_alignment(0.0, 0.5)
614 labelAlignment.add(self._departureGate)
615 table.attach(labelAlignment, 1, 2, 4, 5)
616
617 button = self.addButton(gtk.STOCK_GO_BACK)
618 button.set_use_stock(True)
619 button.connect("clicked", self._backClicked)
620
621 self._button = self.addButton("_Connect", default = True)
622 self._button.set_use_underline(True)
623 self._clickedID = self._button.connect("clicked", self._connectClicked)
624
625 def activate(self):
626 """Setup the departure information."""
627 self._button.set_label("_Connect")
628 self._button.set_use_underline(True)
629 self._button.disconnect(self._clickedID)
630 self._clickedID = self._button.connect("clicked", self._connectClicked)
631
632 bookedFlight = self._wizard._bookedFlight
633
634 self._flightNumber.set_markup("<b>" + bookedFlight.callsign + "</b>")
635
636 aircraftType = acftTypeNames[bookedFlight.aircraftType]
637 self._aircraft.set_markup("<b>" + aircraftType + "</b>")
638
639 self._tailNumber.set_markup("<b>" + bookedFlight.tailNumber + "</b>")
640
641 icao = bookedFlight.departureICAO
642 self._departureICAO.set_markup("<b>" + icao + "</b>")
643 gate = self._wizard._departureGate
644 if gate!="-":
645 gate = "<b>" + gate + "</b>"
646 self._departureGate.set_markup(gate)
647
648 def finalize(self):
649 """Finalize the page."""
650 self._button.set_label(gtk.STOCK_GO_FORWARD)
651 self._button.set_use_stock(True)
652 self._button.disconnect(self._clickedID)
653 self._clickedID = self._button.connect("clicked", self._forwardClicked)
654
655 def _backClicked(self, button):
656 """Called when the Back button is pressed."""
657 self.goBack()
658
659 def _connectClicked(self, button):
660 """Called when the Connect button is pressed."""
661 self._wizard._connectSimulator()
662
663 def _forwardClicked(self, button):
664 """Called when the Forward button is pressed."""
665 self._wizard.nextPage()
666
667#-----------------------------------------------------------------------------
668
669class PayloadPage(Page):
670 """Page to allow setting up the payload."""
671 def __init__(self, wizard):
672 """Construct the page."""
673 help = "The briefing contains the weights below.\n" \
674 "Setup the cargo weight here and the payload weight in the simulator.\n\n" \
675 "You can also check here what the simulator reports as ZFW."
676 completedHelp = "You can see the weights in the briefing\n" \
677 "and the cargo weight you have selected below.\n\n" \
678 "You can also query the ZFW reported by the simulator."
679 super(PayloadPage, self).__init__(wizard, "Payload", help,
680 completedHelp = completedHelp)
681
682 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
683 xscale = 0.0, yscale = 0.0)
684
685 table = gtk.Table(7, 3)
686 table.set_row_spacings(4)
687 table.set_col_spacings(16)
688 table.set_homogeneous(False)
689 alignment.add(table)
690 self.setMainWidget(alignment)
691
692 label = gtk.Label("Crew:")
693 label.set_alignment(0.0, 0.5)
694 table.attach(label, 0, 1, 0, 1)
695
696 self._numCrew = gtk.Label()
697 self._numCrew.set_width_chars(6)
698 self._numCrew.set_alignment(1.0, 0.5)
699 table.attach(self._numCrew, 1, 2, 0, 1)
700
701 label = gtk.Label("Passengers:")
702 label.set_alignment(0.0, 0.5)
703 table.attach(label, 0, 1, 1, 2)
704
705 self._numPassengers = gtk.Label()
706 self._numPassengers.set_width_chars(6)
707 self._numPassengers.set_alignment(1.0, 0.5)
708 table.attach(self._numPassengers, 1, 2, 1, 2)
709
710 label = gtk.Label("Baggage:")
711 label.set_alignment(0.0, 0.5)
712 table.attach(label, 0, 1, 2, 3)
713
714 self._bagWeight = gtk.Label()
715 self._bagWeight.set_width_chars(6)
716 self._bagWeight.set_alignment(1.0, 0.5)
717 table.attach(self._bagWeight, 1, 2, 2, 3)
718
719 table.attach(gtk.Label("kg"), 2, 3, 2, 3)
720
721 label = gtk.Label("_Cargo:")
722 label.set_use_underline(True)
723 label.set_alignment(0.0, 0.5)
724 table.attach(label, 0, 1, 3, 4)
725
726 self._cargoWeight = IntegerEntry(defaultValue = 0)
727 self._cargoWeight.set_width_chars(6)
728 self._cargoWeight.connect("integer-changed", self._cargoWeightChanged)
729 self._cargoWeight.set_tooltip_text("The weight of the cargo for your flight.")
730 table.attach(self._cargoWeight, 1, 2, 3, 4)
731 label.set_mnemonic_widget(self._cargoWeight)
732
733 table.attach(gtk.Label("kg"), 2, 3, 3, 4)
734
735 label = gtk.Label("Mail:")
736 label.set_alignment(0.0, 0.5)
737 table.attach(label, 0, 1, 4, 5)
738
739 self._mailWeight = gtk.Label()
740 self._mailWeight.set_width_chars(6)
741 self._mailWeight.set_alignment(1.0, 0.5)
742 table.attach(self._mailWeight, 1, 2, 4, 5)
743
744 table.attach(gtk.Label("kg"), 2, 3, 4, 5)
745
746 label = gtk.Label("<b>Calculated ZFW:</b>")
747 label.set_alignment(0.0, 0.5)
748 label.set_use_markup(True)
749 table.attach(label, 0, 1, 5, 6)
750
751 self._calculatedZFW = gtk.Label()
752 self._calculatedZFW.set_width_chars(6)
753 self._calculatedZFW.set_alignment(1.0, 0.5)
754 table.attach(self._calculatedZFW, 1, 2, 5, 6)
755
756 table.attach(gtk.Label("kg"), 2, 3, 5, 6)
757
758 self._zfwButton = gtk.Button("_ZFW from FS:")
759 self._zfwButton.set_use_underline(True)
760 self._zfwButton.connect("clicked", self._zfwRequested)
761 table.attach(self._zfwButton, 0, 1, 6, 7)
762
763 self._simulatorZFW = gtk.Label("-")
764 self._simulatorZFW.set_width_chars(6)
765 self._simulatorZFW.set_alignment(1.0, 0.5)
766 table.attach(self._simulatorZFW, 1, 2, 6, 7)
767 self._simulatorZFWValue = None
768
769 table.attach(gtk.Label("kg"), 2, 3, 6, 7)
770
771 self._backButton = self.addButton(gtk.STOCK_GO_BACK)
772 self._backButton.set_use_stock(True)
773 self._backButton.connect("clicked", self._backClicked)
774
775 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
776 self._button.set_use_stock(True)
777 self._button.connect("clicked", self._forwardClicked)
778
779 def activate(self):
780 """Setup the information."""
781 bookedFlight = self._wizard._bookedFlight
782 self._numCrew.set_text(str(bookedFlight.numCrew))
783 self._numPassengers.set_text(str(bookedFlight.numPassengers))
784 self._bagWeight.set_text(str(bookedFlight.bagWeight))
785 self._cargoWeight.set_int(bookedFlight.cargoWeight)
786 self._cargoWeight.set_sensitive(True)
787 self._mailWeight.set_text(str(bookedFlight.mailWeight))
788 self._simulatorZFW.set_text("-")
789 self._simulatorZFWValue = None
790 self._zfwButton.set_sensitive(True)
791 self._updateCalculatedZFW()
792
793 def finalize(self):
794 """Finalize the payload page."""
795 self._cargoWeight.set_sensitive(False)
796
797 def calculateZFW(self):
798 """Calculate the ZFW value."""
799 zfw = self._wizard.gui._flight.aircraft.dow
800 bookedFlight = self._wizard._bookedFlight
801 zfw += (bookedFlight.numCrew + bookedFlight.numPassengers) * 82
802 zfw += bookedFlight.bagWeight
803 zfw += self._cargoWeight.get_int()
804 zfw += bookedFlight.mailWeight
805 return zfw
806
807 def _updateCalculatedZFW(self):
808 """Update the calculated ZFW"""
809 zfw = self.calculateZFW()
810
811 markupBegin = "<b>"
812 markupEnd = "</b>"
813 if self._simulatorZFWValue is not None and \
814 PayloadChecker.isZFWFaulty(self._simulatorZFWValue, zfw):
815 markupBegin += '<span foreground="red">'
816 markupEnd = "</span>" + markupEnd
817 self._calculatedZFW.set_markup(markupBegin + str(zfw) + markupEnd)
818
819 def _cargoWeightChanged(self, entry, weight):
820 """Called when the cargo weight has changed."""
821 self._updateCalculatedZFW()
822
823 def _zfwRequested(self, button):
824 """Called when the ZFW is requested from the simulator."""
825 self._zfwButton.set_sensitive(False)
826 self._backButton.set_sensitive(False)
827 self._button.set_sensitive(False)
828 gui = self._wizard.gui
829 gui.beginBusy("Querying ZFW...")
830 gui.simulator.requestZFW(self._handleZFW)
831
832 def _handleZFW(self, zfw):
833 """Called when the ZFW value is retrieved."""
834 gobject.idle_add(self._processZFW, zfw)
835
836 def _processZFW(self, zfw):
837 """Process the given ZFW value received from the simulator."""
838 self._wizard.gui.endBusy()
839 self._zfwButton.set_sensitive(True)
840 self._backButton.set_sensitive(True)
841 self._button.set_sensitive(True)
842 self._simulatorZFWValue = zfw
843 self._simulatorZFW.set_text("%.0f" % (zfw,))
844 self._updateCalculatedZFW()
845
846 def _forwardClicked(self, button):
847 """Called when the forward button is clicked."""
848 self._wizard.nextPage()
849
850 def _backClicked(self, button):
851 """Called when the Back button is pressed."""
852 self.goBack()
853
854#-----------------------------------------------------------------------------
855
856class TimePage(Page):
857 """Page displaying the departure and arrival times and allows querying the
858 current time from the flight simulator."""
859 def __init__(self, wizard):
860 help = "The departure and arrival times are displayed below in UTC.\n\n" \
861 "You can also query the current UTC time from the simulator.\n" \
862 "Ensure that you have enough time to properly prepare for the flight."
863 completedHelp = "The departure and arrival times are displayed below in UTC.\n\n" \
864 "You can also query the current UTC time from the simulator.\n"
865 super(TimePage, self).__init__(wizard, "Time", help,
866 completedHelp = completedHelp)
867
868 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
869 xscale = 0.0, yscale = 0.0)
870
871 table = gtk.Table(3, 2)
872 table.set_row_spacings(4)
873 table.set_col_spacings(16)
874 table.set_homogeneous(False)
875 alignment.add(table)
876 self.setMainWidget(alignment)
877
878 label = gtk.Label("Departure:")
879 label.set_alignment(0.0, 0.5)
880 table.attach(label, 0, 1, 0, 1)
881
882 self._departure = gtk.Label()
883 self._departure.set_alignment(0.0, 0.5)
884 table.attach(self._departure, 1, 2, 0, 1)
885
886 label = gtk.Label("Arrival:")
887 label.set_alignment(0.0, 0.5)
888 table.attach(label, 0, 1, 1, 2)
889
890 self._arrival = gtk.Label()
891 self._arrival.set_alignment(0.0, 0.5)
892 table.attach(self._arrival, 1, 2, 1, 2)
893
894 self._timeButton = gtk.Button("_Time from FS:")
895 self._timeButton.set_use_underline(True)
896 self._timeButton.connect("clicked", self._timeRequested)
897 table.attach(self._timeButton, 0, 1, 2, 3)
898
899 self._simulatorTime = gtk.Label("-")
900 self._simulatorTime.set_alignment(0.0, 0.5)
901 table.attach(self._simulatorTime, 1, 2, 2, 3)
902
903 self._backButton = self.addButton(gtk.STOCK_GO_BACK)
904 self._backButton.set_use_stock(True)
905 self._backButton.connect("clicked", self._backClicked)
906
907 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
908 self._button.set_use_stock(True)
909 self._button.connect("clicked", self._forwardClicked)
910
911 def activate(self):
912 """Activate the page."""
913 self._timeButton.set_sensitive(True)
914 bookedFlight = self._wizard._bookedFlight
915 self._departure.set_text(str(bookedFlight.departureTime.time()))
916 self._arrival.set_text(str(bookedFlight.arrivalTime.time()))
917 self._simulatorTime.set_text("-")
918
919 def _timeRequested(self, button):
920 """Request the time from the simulator."""
921 self._timeButton.set_sensitive(False)
922 self._backButton.set_sensitive(False)
923 self._button.set_sensitive(False)
924 self._wizard.gui.beginBusy("Querying time...")
925 self._wizard.gui.simulator.requestTime(self._handleTime)
926
927 def _handleTime(self, timestamp):
928 """Handle the result of a time retrieval."""
929 gobject.idle_add(self._processTime, timestamp)
930
931 def _processTime(self, timestamp):
932 """Process the given time."""
933 self._wizard.gui.endBusy()
934 self._timeButton.set_sensitive(True)
935 self._backButton.set_sensitive(True)
936 self._button.set_sensitive(True)
937 tm = time.gmtime(timestamp)
938 t = datetime.time(tm.tm_hour, tm.tm_min, tm.tm_sec)
939 self._simulatorTime.set_text(str(t))
940
941 ts = tm.tm_hour * 3600 + tm.tm_min * 60 + tm.tm_sec
942 dt = self._wizard._bookedFlight.departureTime.time()
943 dts = dt.hour * 3600 + dt.minute * 60 + dt.second
944 diff = dts-ts
945
946 markupBegin = ""
947 markupEnd = ""
948 if diff < 0:
949 markupBegin = '<b><span foreground="red">'
950 markupEnd = '</span></b>'
951 elif diff < 3*60 or diff > 30*60:
952 markupBegin = '<b><span foreground="orange">'
953 markupEnd = '</span></b>'
954
955 self._departure.set_markup(markupBegin + str(dt) + markupEnd)
956
957 def _backClicked(self, button):
958 """Called when the Back button is pressed."""
959 self.goBack()
960
961 def _forwardClicked(self, button):
962 """Called when the forward button is clicked."""
963 self._wizard.nextPage()
964
965#-----------------------------------------------------------------------------
966
967class RoutePage(Page):
968 """The page containing the route and the flight level."""
969 def __init__(self, wizard):
970 help = "Set your cruise flight level below, and\n" \
971 "if necessary, edit the flight plan."
972 completedHelp = "If necessary, you can modify the cruise level and\n" \
973 "the flight plan below during flight.\n" \
974 "If so, please, add a comment on why " \
975 "the modification became necessary."
976 super(RoutePage, self).__init__(wizard, "Route", help,
977 completedHelp = completedHelp)
978
979 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
980 xscale = 0.0, yscale = 0.0)
981
982 mainBox = gtk.VBox()
983 alignment.add(mainBox)
984 self.setMainWidget(alignment)
985
986 levelBox = gtk.HBox()
987
988 label = gtk.Label("_Cruise level")
989 label.set_use_underline(True)
990 levelBox.pack_start(label, True, True, 0)
991
992 self._cruiseLevel = gtk.SpinButton()
993 self._cruiseLevel.set_increments(step = 10, page = 100)
994 self._cruiseLevel.set_range(min = 50, max = 500)
995 self._cruiseLevel.set_tooltip_text("The cruise flight level.")
996 self._cruiseLevel.set_numeric(True)
997 self._cruiseLevel.connect("value-changed", self._cruiseLevelChanged)
998 label.set_mnemonic_widget(self._cruiseLevel)
999
1000 levelBox.pack_start(self._cruiseLevel, False, False, 8)
1001
1002 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
1003 xscale = 0.0, yscale = 0.0)
1004 alignment.add(levelBox)
1005
1006 mainBox.pack_start(alignment, False, False, 0)
1007
1008
1009 routeBox = gtk.VBox()
1010
1011 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
1012 xscale = 0.0, yscale = 0.0)
1013 label = gtk.Label("_Route")
1014 label.set_use_underline(True)
1015 alignment.add(label)
1016 routeBox.pack_start(alignment, True, True, 0)
1017
1018 routeWindow = gtk.ScrolledWindow()
1019 routeWindow.set_size_request(400, 80)
1020 routeWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
1021 else gtk.SHADOW_IN)
1022 routeWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1023 else gtk.POLICY_AUTOMATIC,
1024 gtk.PolicyType.AUTOMATIC if pygobject
1025 else gtk.POLICY_AUTOMATIC)
1026
1027 self._route = gtk.TextView()
1028 self._route.set_tooltip_text("The planned flight route.")
1029 self._route.get_buffer().connect("changed", self._routeChanged)
1030 routeWindow.add(self._route)
1031
1032 label.set_mnemonic_widget(self._route)
1033 routeBox.pack_start(routeWindow, True, True, 0)
1034
1035 mainBox.pack_start(routeBox, True, True, 8)
1036
1037 self._backButton = self.addButton(gtk.STOCK_GO_BACK)
1038 self._backButton.set_use_stock(True)
1039 self._backButton.connect("clicked", self._backClicked)
1040
1041 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
1042 self._button.set_use_stock(True)
1043 self._button.connect("clicked", self._forwardClicked)
1044
1045 @property
1046 def cruiseLevel(self):
1047 """Get the cruise level."""
1048 return self._cruiseLevel.get_value_as_int()
1049
1050 def activate(self):
1051 """Setup the route from the booked flight."""
1052 self._cruiseLevel.set_value(240)
1053 self._route.get_buffer().set_text(self._wizard._bookedFlight.route)
1054 self._updateForwardButton()
1055
1056 def _getRoute(self):
1057 """Get the text of the route."""
1058 buffer = self._route.get_buffer()
1059 return buffer.get_text(buffer.get_start_iter(),
1060 buffer.get_end_iter(), True)
1061
1062 def _updateForwardButton(self):
1063 """Update the sensitivity of the forward button."""
1064 self._button.set_sensitive(self._cruiseLevel.get_value_as_int()>=50 and \
1065 self._getRoute()!="")
1066
1067 def _cruiseLevelChanged(self, spinButton):
1068 """Called when the cruise level has changed."""
1069 self._updateForwardButton()
1070
1071 def _routeChanged(self, textBuffer):
1072 """Called when the route has changed."""
1073 self._updateForwardButton()
1074
1075 def _backClicked(self, button):
1076 """Called when the Back button is pressed."""
1077 self.goBack()
1078
1079 def _forwardClicked(self, button):
1080 """Called when the Forward button is clicked."""
1081 if self._completed:
1082 self._wizard.nextPage()
1083 else:
1084 bookedFlight = self._wizard._bookedFlight
1085 self._wizard.gui.beginBusy("Downloading NOTAMs...")
1086 self._wizard.gui.webHandler.getNOTAMs(self._notamsCallback,
1087 bookedFlight.departureICAO,
1088 bookedFlight.arrivalICAO)
1089
1090 def _notamsCallback(self, returned, result):
1091 """Callback for the NOTAMs."""
1092 gobject.idle_add(self._handleNOTAMs, returned, result)
1093
1094 def _handleNOTAMs(self, returned, result):
1095 """Handle the NOTAMs."""
1096 if returned:
1097 self._wizard._departureNOTAMs = result.departureNOTAMs
1098 self._wizard._arrivalNOTAMs = result.arrivalNOTAMs
1099 else:
1100 self._wizard._departureNOTAMs = None
1101 self._wizard._arrivalNOTAMs = None
1102
1103 bookedFlight = self._wizard._bookedFlight
1104 self._wizard.gui.beginBusy("Downloading METARs...")
1105 self._wizard.gui.webHandler.getMETARs(self._metarsCallback,
1106 [bookedFlight.departureICAO,
1107 bookedFlight.arrivalICAO])
1108
1109 def _metarsCallback(self, returned, result):
1110 """Callback for the METARs."""
1111 gobject.idle_add(self._handleMETARs, returned, result)
1112
1113 def _handleMETARs(self, returned, result):
1114 """Handle the METARs."""
1115 self._wizard._departureMETAR = None
1116 self._wizard._arrivalMETAR = None
1117 bookedFlight = self._wizard._bookedFlight
1118 if returned:
1119 if bookedFlight.departureICAO in result.metars:
1120 self._wizard._departureMETAR = result.metars[bookedFlight.departureICAO]
1121 if bookedFlight.arrivalICAO in result.metars:
1122 self._wizard._arrivalMETAR = result.metars[bookedFlight.arrivalICAO]
1123
1124 self._wizard.gui.endBusy()
1125 self._backButton.set_sensitive(True)
1126 self._button.set_sensitive(True)
1127 self._wizard.nextPage()
1128
1129#-----------------------------------------------------------------------------
1130
1131class BriefingPage(Page):
1132 """Page for the briefing."""
1133 def __init__(self, wizard, departure):
1134 """Construct the briefing page."""
1135 self._departure = departure
1136
1137 title = "Briefing (%d/2): %s" % (1 if departure else 2,
1138 "departure" if departure
1139 else "arrival")
1140
1141 help = "Read carefully the NOTAMs and METAR below.\n\n" \
1142 "You can edit the METAR if your simulator or network\n" \
1143 "provides different weather."
1144 completedHelp = "If your simulator or network provides a different\n" \
1145 "weather, you can edit the METAR below."
1146 super(BriefingPage, self).__init__(wizard, title, help,
1147 completedHelp = completedHelp)
1148
1149 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1150 xscale = 1.0, yscale = 1.0)
1151
1152 mainBox = gtk.VBox()
1153 alignment.add(mainBox)
1154 self.setMainWidget(alignment)
1155
1156 self._notamsFrame = gtk.Frame()
1157 self._notamsFrame.set_label("LHBP NOTAMs")
1158 scrolledWindow = gtk.ScrolledWindow()
1159 scrolledWindow.set_size_request(-1, 128)
1160 # FIXME: these constants should be in common
1161 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1162 else gtk.POLICY_AUTOMATIC,
1163 gtk.PolicyType.AUTOMATIC if pygobject
1164 else gtk.POLICY_AUTOMATIC)
1165 self._notams = gtk.TextView()
1166 self._notams.set_editable(False)
1167 self._notams.set_accepts_tab(False)
1168 self._notams.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
1169 scrolledWindow.add(self._notams)
1170 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
1171 xscale = 1.0, yscale = 1.0)
1172 alignment.set_padding(padding_top = 4, padding_bottom = 0,
1173 padding_left = 0, padding_right = 0)
1174 alignment.add(scrolledWindow)
1175 self._notamsFrame.add(alignment)
1176 mainBox.pack_start(self._notamsFrame, True, True, 4)
1177
1178 self._metarFrame = gtk.Frame()
1179 self._metarFrame.set_label("LHBP METAR")
1180 scrolledWindow = gtk.ScrolledWindow()
1181 scrolledWindow.set_size_request(-1, 32)
1182 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1183 else gtk.POLICY_AUTOMATIC,
1184 gtk.PolicyType.AUTOMATIC if pygobject
1185 else gtk.POLICY_AUTOMATIC)
1186 self._metar = gtk.TextView()
1187 self._metar.set_accepts_tab(False)
1188 self._metar.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
1189 scrolledWindow.add(self._metar)
1190 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
1191 xscale = 1.0, yscale = 1.0)
1192 alignment.set_padding(padding_top = 4, padding_bottom = 0,
1193 padding_left = 0, padding_right = 0)
1194 alignment.add(scrolledWindow)
1195 self._metarFrame.add(alignment)
1196 mainBox.pack_start(self._metarFrame, True, True, 4)
1197
1198 button = self.addButton(gtk.STOCK_GO_BACK)
1199 button.set_use_stock(True)
1200 button.connect("clicked", self._backClicked)
1201
1202 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
1203 self._button.set_use_stock(True)
1204 self._button.connect("clicked", self._forwardClicked)
1205
1206 def activate(self):
1207 """Activate the page."""
1208 if not self._departure:
1209 self._button.set_label("I have read the briefing and am ready to fly!")
1210 self._button.set_use_stock(False)
1211
1212 bookedFlight = self._wizard._bookedFlight
1213
1214 icao = bookedFlight.departureICAO if self._departure \
1215 else bookedFlight.arrivalICAO
1216 notams = self._wizard._departureNOTAMs if self._departure \
1217 else self._wizard._arrivalNOTAMs
1218 metar = self._wizard._departureMETAR if self._departure \
1219 else self._wizard._arrivalMETAR
1220
1221 self._notamsFrame.set_label(icao + " NOTAMs")
1222 buffer = self._notams.get_buffer()
1223 if notams is None:
1224 buffer.set_text("Could not download NOTAMs")
1225 elif not notams:
1226 buffer.set_text("Could not download NOTAM for this airport")
1227 else:
1228 s = ""
1229 for notam in notams:
1230 s += str(notam.begin)
1231 if notam.end is not None:
1232 s += " - " + str(notam.end)
1233 elif notam.permanent:
1234 s += " - PERMANENT"
1235 s += "\n"
1236 if notam.repeatCycle:
1237 s += "Repeat cycle: " + notam.repeatCycle + "\n"
1238 s += notam.notice + "\n"
1239 s += "-------------------- * --------------------\n"
1240 buffer.set_text(s)
1241
1242 self._metarFrame.set_label(icao + " METAR")
1243 buffer = self._metar.get_buffer()
1244 if metar is None:
1245 buffer.set_text("Could not download METAR")
1246 else:
1247 buffer.set_text(metar)
1248
1249 def _backClicked(self, button):
1250 """Called when the Back button is pressed."""
1251 self.goBack()
1252
1253 def _forwardClicked(self, button):
1254 """Called when the forward button is clicked."""
1255 if not self._departure:
1256 if not self._completed:
1257 self._wizard.gui.startMonitoring()
1258 self._button.set_use_stock(True)
1259 self._button.set_label(gtk.STOCK_GO_FORWARD)
1260 self.complete()
1261
1262 self._wizard.nextPage()
1263
1264#-----------------------------------------------------------------------------
1265
1266class TakeoffPage(Page):
1267 """Page for entering the takeoff data."""
1268 def __init__(self, wizard):
1269 """Construct the takeoff page."""
1270 help = "Enter the runway and SID used, as well as the speeds."
1271 completedHelp = "The runway, SID and takeoff speeds logged can be seen below."
1272
1273 super(TakeoffPage, self).__init__(wizard, "Takeoff", help,
1274 completedHelp = completedHelp)
1275
1276 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1277 xscale = 0.0, yscale = 0.0)
1278
1279 table = gtk.Table(5, 4)
1280 table.set_row_spacings(4)
1281 table.set_col_spacings(16)
1282 table.set_homogeneous(False)
1283 alignment.add(table)
1284 self.setMainWidget(alignment)
1285
1286 label = gtk.Label("Run_way:")
1287 label.set_use_underline(True)
1288 label.set_alignment(0.0, 0.5)
1289 table.attach(label, 0, 1, 0, 1)
1290
1291 self._runway = gtk.Entry()
1292 self._runway.set_width_chars(10)
1293 self._runway.set_tooltip_text("The runway the takeoff is performed from.")
1294 table.attach(self._runway, 1, 3, 0, 1)
1295 label.set_mnemonic_widget(self._runway)
1296
1297 label = gtk.Label("_SID:")
1298 label.set_use_underline(True)
1299 label.set_alignment(0.0, 0.5)
1300 table.attach(label, 0, 1, 1, 2)
1301
1302 self._sid = gtk.Entry()
1303 self._sid.set_width_chars(10)
1304 self._sid.set_tooltip_text("The name of the Standard Instrument Deparature procedure followed.")
1305 table.attach(self._sid, 1, 3, 1, 2)
1306 label.set_mnemonic_widget(self._sid)
1307
1308 label = gtk.Label("V<sub>_1</sub>:")
1309 label.set_use_markup(True)
1310 label.set_use_underline(True)
1311 label.set_alignment(0.0, 0.5)
1312 table.attach(label, 0, 1, 2, 3)
1313
1314 self._v1 = IntegerEntry()
1315 self._v1.set_width_chars(4)
1316 self._v1.set_tooltip_markup("The takeoff decision speed in knots.")
1317 table.attach(self._v1, 2, 3, 2, 3)
1318 label.set_mnemonic_widget(self._v1)
1319
1320 table.attach(gtk.Label("knots"), 3, 4, 2, 3)
1321
1322 label = gtk.Label("V<sub>_R</sub>:")
1323 label.set_use_markup(True)
1324 label.set_use_underline(True)
1325 label.set_alignment(0.0, 0.5)
1326 table.attach(label, 0, 1, 3, 4)
1327
1328 self._vr = IntegerEntry()
1329 self._vr.set_width_chars(4)
1330 self._vr.set_tooltip_markup("The takeoff rotation speed in knots.")
1331 table.attach(self._vr, 2, 3, 3, 4)
1332 label.set_mnemonic_widget(self._vr)
1333
1334 table.attach(gtk.Label("knots"), 3, 4, 3, 4)
1335
1336 label = gtk.Label("V<sub>_2</sub>:")
1337 label.set_use_markup(True)
1338 label.set_use_underline(True)
1339 label.set_alignment(0.0, 0.5)
1340 table.attach(label, 0, 1, 4, 5)
1341
1342 self._v2 = IntegerEntry()
1343 self._v2.set_width_chars(4)
1344 self._v2.set_tooltip_markup("The takeoff safety speed in knots.")
1345 table.attach(self._v2, 2, 3, 4, 5)
1346 label.set_mnemonic_widget(self._v2)
1347
1348 table.attach(gtk.Label("knots"), 3, 4, 4, 5)
1349
1350 button = self.addButton(gtk.STOCK_GO_BACK)
1351 button.set_use_stock(True)
1352 button.connect("clicked", self._backClicked)
1353
1354 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
1355 self._button.set_use_stock(True)
1356 self._button.connect("clicked", self._forwardClicked)
1357
1358 @property
1359 def v1(self):
1360 """Get the v1 speed."""
1361 return self._v1.get_int()
1362
1363 @property
1364 def vr(self):
1365 """Get the vr speed."""
1366 return self._vr.get_int()
1367
1368 @property
1369 def v2(self):
1370 """Get the v2 speed."""
1371 return self._v2.get_int()
1372
1373 def activate(self):
1374 """Activate the page."""
1375 self._runway.set_text("")
1376 self._runway.set_sensitive(True)
1377 self._sid.set_text("")
1378 self._sid.set_sensitive(True)
1379 self._v1.set_int(None)
1380 self._v1.set_sensitive(True)
1381 self._vr.set_int(None)
1382 self._vr.set_sensitive(True)
1383 self._v2.set_int(None)
1384 self._v2.set_sensitive(True)
1385 self._button.set_sensitive(False)
1386
1387 def freezeValues(self):
1388 """Freeze the values on the page, and enable the forward button."""
1389 self._runway.set_sensitive(False)
1390 self._sid.set_sensitive(False)
1391 self._v1.set_sensitive(False)
1392 self._vr.set_sensitive(False)
1393 self._v2.set_sensitive(False)
1394 self._button.set_sensitive(True)
1395
1396 def _backClicked(self, button):
1397 """Called when the Back button is pressed."""
1398 self.goBack()
1399
1400 def _forwardClicked(self, button):
1401 """Called when the forward button is clicked."""
1402 self._wizard.nextPage()
1403
1404#-----------------------------------------------------------------------------
1405
1406class LandingPage(Page):
1407 """Page for entering landing data."""
1408 def __init__(self, wizard):
1409 """Construct the landing page."""
1410 help = "Enter the STAR and/or transition, runway,\n" \
1411 "approach type and V<sub>Ref</sub> used."
1412 completedHelp = "The STAR and/or transition, runway, approach\n" \
1413 "type and V<sub>Ref</sub> logged can be seen below."
1414
1415 super(LandingPage, self).__init__(wizard, "Landing", help,
1416 completedHelp = completedHelp)
1417
1418 self._flightEnded = False
1419
1420 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1421 xscale = 0.0, yscale = 0.0)
1422
1423 table = gtk.Table(5, 5)
1424 table.set_row_spacings(4)
1425 table.set_col_spacings(16)
1426 table.set_homogeneous(False)
1427 alignment.add(table)
1428 self.setMainWidget(alignment)
1429
1430 self._starButton = gtk.CheckButton()
1431 self._starButton.connect("clicked", self._starButtonClicked)
1432 table.attach(self._starButton, 0, 1, 0, 1)
1433
1434 label = gtk.Label("_STAR:")
1435 label.set_use_underline(True)
1436 label.set_alignment(0.0, 0.5)
1437 table.attach(label, 1, 2, 0, 1)
1438
1439 self._star = gtk.Entry()
1440 self._star.set_width_chars(10)
1441 self._star.set_tooltip_text("The name of Standard Terminal Arrival Route followed.")
1442 self._star.connect("changed", self._updateForwardButton)
1443 self._star.set_sensitive(False)
1444 table.attach(self._star, 2, 4, 0, 1)
1445 label.set_mnemonic_widget(self._starButton)
1446
1447 self._transitionButton = gtk.CheckButton()
1448 self._transitionButton.connect("clicked", self._transitionButtonClicked)
1449 table.attach(self._transitionButton, 0, 1, 1, 2)
1450
1451 label = gtk.Label("_Transition:")
1452 label.set_use_underline(True)
1453 label.set_alignment(0.0, 0.5)
1454 table.attach(label, 1, 2, 1, 2)
1455
1456 self._transition = gtk.Entry()
1457 self._transition.set_width_chars(10)
1458 self._transition.set_tooltip_text("The name of transition executed or VECTORS if vectored by ATC.")
1459 self._transition.connect("changed", self._updateForwardButton)
1460 self._transition.set_sensitive(False)
1461 table.attach(self._transition, 2, 4, 1, 2)
1462 label.set_mnemonic_widget(self._transitionButton)
1463
1464 label = gtk.Label("Run_way:")
1465 label.set_use_underline(True)
1466 label.set_alignment(0.0, 0.5)
1467 table.attach(label, 1, 2, 2, 3)
1468
1469 self._runway = gtk.Entry()
1470 self._runway.set_width_chars(10)
1471 self._runway.set_tooltip_text("The runway the landing is performed on.")
1472 self._runway.connect("changed", self._updateForwardButton)
1473 table.attach(self._runway, 2, 4, 2, 3)
1474 label.set_mnemonic_widget(self._runway)
1475
1476 label = gtk.Label("_Approach type:")
1477 label.set_use_underline(True)
1478 label.set_alignment(0.0, 0.5)
1479 table.attach(label, 1, 2, 3, 4)
1480
1481 self._approachType = gtk.Entry()
1482 self._approachType.set_width_chars(10)
1483 self._approachType.set_tooltip_text("The type of the approach, e.g. ILS or VISUAL.")
1484 self._approachType.connect("changed", self._updateForwardButton)
1485 table.attach(self._approachType, 2, 4, 3, 4)
1486 label.set_mnemonic_widget(self._approachType)
1487
1488 label = gtk.Label("V<sub>_Ref</sub>:")
1489 label.set_use_markup(True)
1490 label.set_use_underline(True)
1491 label.set_alignment(0.0, 0.5)
1492 table.attach(label, 1, 2, 5, 6)
1493
1494 self._vref = IntegerEntry()
1495 self._vref.set_width_chars(5)
1496 self._vref.set_tooltip_markup("The approach reference speed in knots.")
1497 self._vref.connect("integer-changed", self._vrefChanged)
1498 table.attach(self._vref, 3, 4, 5, 6)
1499 label.set_mnemonic_widget(self._vref)
1500
1501 table.attach(gtk.Label("knots"), 4, 5, 5, 6)
1502
1503 button = self.addButton(gtk.STOCK_GO_BACK)
1504 button.set_use_stock(True)
1505 button.connect("clicked", self._backClicked)
1506
1507 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
1508 self._button.set_use_stock(True)
1509 self._button.connect("clicked", self._forwardClicked)
1510
1511 # These are needed for correct size calculations
1512 self._starButton.set_active(True)
1513 self._transitionButton.set_active(True)
1514
1515 @property
1516 def vref(self):
1517 """Return the landing reference speed."""
1518 return self._vref.get_int()
1519
1520 def activate(self):
1521 """Called when the page is activated."""
1522 self._starButton.set_sensitive(True)
1523 self._starButton.set_active(False)
1524 self._star.set_text("")
1525
1526 self._transitionButton.set_sensitive(True)
1527 self._transitionButton.set_active(False)
1528 self._transition.set_text("")
1529
1530 self._runway.set_text("")
1531 self._runway.set_sensitive(True)
1532
1533 self._approachType.set_text("")
1534 self._approachType.set_sensitive(True)
1535
1536 self._vref.set_int(None)
1537 self._vref.set_sensitive(True)
1538
1539 self._updateForwardButton()
1540
1541 def flightEnded(self):
1542 """Called when the flight has ended."""
1543 self._flightEnded = True
1544 self._updateForwardButton()
1545
1546 def finalize(self):
1547 """Finalize the page."""
1548 self._starButton.set_sensitive(False)
1549 self._star.set_sensitive(False)
1550
1551 self._transitionButton.set_sensitive(False)
1552 self._transition.set_sensitive(False)
1553
1554 self._runway.set_sensitive(False)
1555
1556 self._approachType.set_sensitive(False)
1557
1558 self._vref.set_sensitive(False)
1559 self._wizard.gui.flight.aircraft.updateVRef()
1560 # FIXME: Perhaps a separate initialize() call which would set up
1561 # defaults? -> use reset()
1562 self._flightEnded = False
1563
1564 def _starButtonClicked(self, button):
1565 """Called when the STAR button is clicked."""
1566 active = button.get_active()
1567 self._star.set_sensitive(active)
1568 if active:
1569 self._star.grab_focus()
1570 self._updateForwardButton()
1571
1572 def _transitionButtonClicked(self, button):
1573 """Called when the Transition button is clicked."""
1574 active = button.get_active()
1575 self._transition.set_sensitive(active)
1576 if active:
1577 self._transition.grab_focus()
1578 self._updateForwardButton()
1579
1580 def _updateForwardButton(self, widget = None):
1581 """Update the sensitivity of the forward button."""
1582 sensitive = self._flightEnded and \
1583 (self._starButton.get_active() or \
1584 self._transitionButton.get_active()) and \
1585 (self._star.get_text()!="" or
1586 not self._starButton.get_active()) and \
1587 (self._transition.get_text()!="" or
1588 not self._transitionButton.get_active()) and \
1589 self._runway.get_text()!="" and \
1590 self._approachType.get_text()!="" and \
1591 self.vref is not None
1592 self._button.set_sensitive(sensitive)
1593
1594 def _vrefChanged(self, widget, value):
1595 """Called when the Vref has changed."""
1596 self._updateForwardButton()
1597
1598 def _backClicked(self, button):
1599 """Called when the Back button is pressed."""
1600 self.goBack()
1601
1602 def _forwardClicked(self, button):
1603 """Called when the forward button is clicked."""
1604 self._wizard.nextPage()
1605
1606#-----------------------------------------------------------------------------
1607
1608class FinishPage(Page):
1609 """Flight finish page."""
1610 def __init__(self, wizard):
1611 """Construct the finish page."""
1612 help = "There are some statistics about your flight below.\n\n" \
1613 "Review the data, also on earlier pages, and if you are\n" \
1614 "satisfied, you can save or send your PIREP."
1615
1616 super(FinishPage, self).__init__(wizard, "Finish", help)
1617
1618 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1619 xscale = 0.0, yscale = 0.0)
1620
1621 table = gtk.Table(7, 2)
1622 table.set_row_spacings(4)
1623 table.set_col_spacings(16)
1624 table.set_homogeneous(False)
1625 alignment.add(table)
1626 self.setMainWidget(alignment)
1627
1628 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1629 label = gtk.Label("Flight rating:")
1630 labelAlignment.add(label)
1631 table.attach(labelAlignment, 0, 1, 0, 1)
1632
1633 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1634 self._flightRating = gtk.Label()
1635 self._flightRating.set_width_chars(7)
1636 self._flightRating.set_alignment(0.0, 0.5)
1637 self._flightRating.set_use_markup(True)
1638 labelAlignment.add(self._flightRating)
1639 table.attach(labelAlignment, 1, 2, 0, 1)
1640
1641 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1642 label = gtk.Label("Flight time:")
1643 labelAlignment.add(label)
1644 table.attach(labelAlignment, 0, 1, 1, 2)
1645
1646 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1647 self._flightTime = gtk.Label()
1648 self._flightTime.set_width_chars(10)
1649 self._flightTime.set_alignment(0.0, 0.5)
1650 self._flightTime.set_use_markup(True)
1651 labelAlignment.add(self._flightTime)
1652 table.attach(labelAlignment, 1, 2, 1, 2)
1653
1654 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1655 label = gtk.Label("Block time:")
1656 labelAlignment.add(label)
1657 table.attach(labelAlignment, 0, 1, 2, 3)
1658
1659 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1660 self._blockTime = gtk.Label()
1661 self._blockTime.set_width_chars(10)
1662 self._blockTime.set_alignment(0.0, 0.5)
1663 self._blockTime.set_use_markup(True)
1664 labelAlignment.add(self._blockTime)
1665 table.attach(labelAlignment, 1, 2, 2, 3)
1666
1667 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1668 label = gtk.Label("Distance flown:")
1669 labelAlignment.add(label)
1670 table.attach(labelAlignment, 0, 1, 3, 4)
1671
1672 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1673 self._distanceFlown = gtk.Label()
1674 self._distanceFlown.set_width_chars(10)
1675 self._distanceFlown.set_alignment(0.0, 0.5)
1676 self._distanceFlown.set_use_markup(True)
1677 labelAlignment.add(self._distanceFlown)
1678 table.attach(labelAlignment, 1, 2, 3, 4)
1679
1680 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1681 label = gtk.Label("Fuel used:")
1682 labelAlignment.add(label)
1683 table.attach(labelAlignment, 0, 1, 4, 5)
1684
1685 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1686 self._fuelUsed = gtk.Label()
1687 self._fuelUsed.set_width_chars(10)
1688 self._fuelUsed.set_alignment(0.0, 0.5)
1689 self._fuelUsed.set_use_markup(True)
1690 labelAlignment.add(self._fuelUsed)
1691 table.attach(labelAlignment, 1, 2, 4, 5)
1692
1693 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1694 label = gtk.Label("_Type:")
1695 label.set_use_underline(True)
1696 labelAlignment.add(label)
1697 table.attach(labelAlignment, 0, 1, 5, 6)
1698
1699 flightTypeModel = gtk.ListStore(str, int)
1700 index = 1
1701 for type in ["scheduled", "old-timer", "VIP", "charter"]:
1702 flightTypeModel.append([type, index])
1703 index += 1
1704
1705 self._flightType = gtk.ComboBox(model = flightTypeModel)
1706 renderer = gtk.CellRendererText()
1707 self._flightType.pack_start(renderer, True)
1708 self._flightType.add_attribute(renderer, "text", 0)
1709 self._flightType.set_tooltip_text("Select the type of the flight.")
1710 self._flightType.set_active(0)
1711 self._flightType.connect("changed", self._flightTypeChanged)
1712 flightTypeAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1713 flightTypeAlignment.add(self._flightType)
1714 table.attach(flightTypeAlignment, 1, 2, 5, 6)
1715 label.set_mnemonic_widget(self._flightType)
1716
1717 self._onlineFlight = gtk.CheckButton("_Online flight")
1718 self._onlineFlight.set_use_underline(True)
1719 self._onlineFlight.set_tooltip_text("Check if your flight was online, uncheck otherwise.")
1720 onlineFlightAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1721 onlineFlightAlignment.add(self._onlineFlight)
1722 table.attach(onlineFlightAlignment, 1, 2, 6, 7)
1723
1724 button = self.addButton(gtk.STOCK_GO_BACK)
1725 button.set_use_stock(True)
1726 button.connect("clicked", self._backClicked)
1727
1728 self._saveButton = self.addButton("S_ave PIREP...")
1729 self._saveButton.set_use_underline(True)
1730 self._saveButton.set_sensitive(False)
1731 #self._saveButton.connect("clicked", self._saveClicked)
1732
1733 self._sendButton = self.addButton("_Send PIREP...", True)
1734 self._sendButton.set_use_underline(True)
1735 self._sendButton.set_sensitive(False)
1736 #self._sendButton.connect("clicked", self._sendClicked)
1737
1738 def activate(self):
1739 """Activate the page."""
1740 flight = self._wizard.gui._flight
1741 rating = flight.logger.getRating()
1742 if rating<0:
1743 self._flightRating.set_markup('<b><span foreground="red">NO GO</span></b>')
1744 else:
1745 self._flightRating.set_markup("<b>%.1f %%</b>" % (rating,))
1746
1747 flightLength = flight.flightTimeEnd - flight.flightTimeStart
1748 self._flightTime.set_markup("<b>%s</b>" % \
1749 (util.getTimeIntervalString(flightLength),))
1750
1751 blockLength = flight.blockTimeEnd - flight.blockTimeStart
1752 self._blockTime.set_markup("<b>%s</b>" % \
1753 (util.getTimeIntervalString(blockLength),))
1754
1755 self._distanceFlown.set_markup("<b>%.2f NM</b>" % \
1756 (flight.flownDistance,))
1757
1758 self._fuelUsed.set_markup("<b>%.0f kg</b>" % \
1759 (flight.endFuel - flight.startFuel,))
1760
1761 self._flightType.set_active(-1)
1762 self._onlineFlight.set_active(True)
1763
1764 def _backClicked(self, button):
1765 """Called when the Back button is pressed."""
1766 self.goBack()
1767
1768 def _flightTypeChanged(self, comboBox):
1769 """Called when the flight type has changed."""
1770 index = self._flightType.get_active()
1771 flightTypeIsValid = index>=0
1772 self._saveButton.set_sensitive(flightTypeIsValid)
1773 self._sendButton.set_sensitive(flightTypeIsValid)
1774
1775#-----------------------------------------------------------------------------
1776
1777class Wizard(gtk.VBox):
1778 """The flight wizard."""
1779 def __init__(self, gui):
1780 """Construct the wizard."""
1781 super(Wizard, self).__init__()
1782
1783 self.gui = gui
1784
1785 self._pages = []
1786 self._currentPage = None
1787
1788 self._pages.append(LoginPage(self))
1789 self._pages.append(FlightSelectionPage(self))
1790 self._pages.append(GateSelectionPage(self))
1791 self._pages.append(ConnectPage(self))
1792 self._payloadPage = PayloadPage(self)
1793 self._pages.append(self._payloadPage)
1794 self._pages.append(TimePage(self))
1795 self._routePage = RoutePage(self)
1796 self._pages.append(self._routePage)
1797 self._pages.append(BriefingPage(self, True))
1798 self._pages.append(BriefingPage(self, False))
1799 self._takeoffPage = TakeoffPage(self)
1800 self._pages.append(self._takeoffPage)
1801 self._landingPage = LandingPage(self)
1802 self._pages.append(self._landingPage)
1803 self._pages.append(FinishPage(self))
1804
1805 maxWidth = 0
1806 maxHeight = 0
1807 for page in self._pages:
1808 page.show_all()
1809 pageSizeRequest = page.size_request()
1810 width = pageSizeRequest.width if pygobject else pageSizeRequest[0]
1811 height = pageSizeRequest.height if pygobject else pageSizeRequest[1]
1812 maxWidth = max(maxWidth, width)
1813 maxHeight = max(maxHeight, height)
1814 maxWidth += 16
1815 maxHeight += 32
1816 self.set_size_request(maxWidth, maxHeight)
1817
1818 self._initialize()
1819
1820 @property
1821 def loginResult(self):
1822 """Get the login result."""
1823 return self._loginResult
1824
1825 def setCurrentPage(self, index, finalize = False):
1826 """Set the current page to the one with the given index."""
1827 assert index < len(self._pages)
1828
1829 fromPage = self._currentPage
1830 if fromPage is not None:
1831 page = self._pages[fromPage]
1832 if finalize and not page._completed:
1833 page.complete()
1834 self.remove(page)
1835
1836 self._currentPage = index
1837 page = self._pages[index]
1838 self.add(page)
1839 if page._fromPage is None:
1840 page._fromPage = fromPage
1841 page.initialize()
1842 self.show_all()
1843 if fromPage is not None:
1844 self.grabDefault()
1845
1846 @property
1847 def zfw(self):
1848 """Get the calculated ZFW value."""
1849 return 0 if self._bookedFlight is None \
1850 else self._payloadPage.calculateZFW()
1851
1852 @property
1853 def cruiseAltitude(self):
1854 """Get the cruise altitude."""
1855 return self._routePage.cruiseLevel * 100
1856
1857 @property
1858 def v1(self):
1859 """Get the V1 speed."""
1860 return self._takeoffPage.v1
1861
1862 @property
1863 def vr(self):
1864 """Get the Vr speed."""
1865 return self._takeoffPage.vr
1866
1867 @property
1868 def v2(self):
1869 """Get the V2 speed."""
1870 return self._takeoffPage.v2
1871
1872 @property
1873 def vref(self):
1874 """Get the Vref speed."""
1875 return self._landingPage.vref
1876
1877 def nextPage(self, finalize = True):
1878 """Go to the next page."""
1879 self.jumpPage(1, finalize)
1880
1881 def jumpPage(self, count, finalize = True):
1882 """Go to the page which is 'count' pages after the current one."""
1883 self.setCurrentPage(self._currentPage + count, finalize = finalize)
1884
1885 def grabDefault(self):
1886 """Make the default button of the current page the default."""
1887 self._pages[self._currentPage].grabDefault()
1888
1889 def connected(self, fsType, descriptor):
1890 """Called when the connection could be made to the simulator."""
1891 self.nextPage()
1892
1893 def reset(self):
1894 """Resets the wizard to go back to the login page."""
1895 self._initialize()
1896
1897 def setStage(self, stage):
1898 """Set the flight stage to the given one."""
1899 if stage==const.STAGE_TAKEOFF:
1900 self._takeoffPage.freezeValues()
1901 elif stage==const.STAGE_END:
1902 self._landingPage.flightEnded()
1903
1904 def _initialize(self):
1905 """Initialize the wizard."""
1906 self._fleet = None
1907 self._fleetCallback = None
1908 self._updatePlaneCallback = None
1909
1910 self._loginResult = None
1911 self._bookedFlight = None
1912 self._departureGate = "-"
1913 self._departureNOTAMs = None
1914 self._departureMETAR = None
1915 self._arrivalNOTAMs = None
1916 self._arrivalMETAR = None
1917
1918 for page in self._pages:
1919 page.reset()
1920
1921 self.setCurrentPage(0)
1922
1923 def _getFleet(self, callback, force = False):
1924 """Get the fleet, if needed.
1925
1926 callback is function that will be called, when the feet is retrieved,
1927 or the retrieval fails. It should have a single argument that will
1928 receive the fleet object on success, None otherwise.
1929 """
1930 if self._fleet is not None and not force:
1931 callback(self._fleet)
1932
1933 self.gui.beginBusy("Retrieving fleet...")
1934 self._fleetCallback = callback
1935 self.gui.webHandler.getFleet(self._fleetResultCallback)
1936
1937 def _fleetResultCallback(self, returned, result):
1938 """Called when the fleet has been queried."""
1939 gobject.idle_add(self._handleFleetResult, returned, result)
1940
1941 def _handleFleetResult(self, returned, result):
1942 """Handle the fleet result."""
1943 self.gui.endBusy()
1944 if returned:
1945 self._fleet = result.fleet
1946 else:
1947 self._fleet = None
1948
1949 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
1950 buttons = BUTTONSTYPE_OK,
1951 message_format =
1952 "Failed to retrieve the information on "
1953 "the fleet.")
1954 dialog.run()
1955 dialog.hide()
1956
1957 self._fleetCallback(self._fleet)
1958
1959 def _updatePlane(self, callback, tailNumber, status, gateNumber = None):
1960 """Update the given plane's gate information."""
1961 self.gui.beginBusy("Updating plane status...")
1962 self._updatePlaneCallback = callback
1963 self.gui.webHandler.updatePlane(self._updatePlaneResultCallback,
1964 tailNumber, status, gateNumber)
1965
1966 def _updatePlaneResultCallback(self, returned, result):
1967 """Callback for the plane updating operation."""
1968 gobject.idle_add(self._handleUpdatePlaneResult, returned, result)
1969
1970 def _handleUpdatePlaneResult(self, returned, result):
1971 """Handle the result of a plane update operation."""
1972 self.gui.endBusy()
1973 if returned:
1974 success = result.success
1975 else:
1976 success = None
1977
1978 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
1979 buttons = BUTTONSTYPE_OK,
1980 message_format =
1981 "Failed to update the statuis of "
1982 "the airplane.")
1983 dialog.run()
1984 dialog.hide()
1985
1986 self._updatePlaneCallback(success)
1987
1988 def _connectSimulator(self):
1989 """Connect to the simulator."""
1990 self.gui.connectSimulator(self._bookedFlight.aircraftType)
1991
1992#-----------------------------------------------------------------------------
1993
Note: See TracBrowser for help on using the repository browser.