source: src/mlx/gui/flight.py@ 91:c3fc045d7aeb

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

Reworked the GUI reset

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