source: src/mlx/gui/flight.py@ 93:fbcbfa72cdb2

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

Implemented the beginnings of the main menu and the separate debug log tab

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