source: src/mlx/gui/flight.py@ 92:1ca250ec2aa0

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

Further work on the reset

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