source: src/mlx/gui/flight.py@ 141:3172532920ad

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

Fuel loading works

File size: 96.2 KB
Line 
1# The flight handling "wizard"
2
3from mlx.gui.common import *
4
5import mlx.const as const
6import mlx.fs as fs
7import mlx.acft as acft
8from mlx.checks import PayloadChecker
9import mlx.util as util
10from mlx.pirep import PIREP
11from mlx.i18n import xstr
12
13import datetime
14import time
15
16#------------------------------------------------------------------------------
17
18acftTypeNames = { const.AIRCRAFT_B736: "Boeing 737-600",
19 const.AIRCRAFT_B737: "Boeing 737-700",
20 const.AIRCRAFT_B738: "Boeing 737-800",
21 const.AIRCRAFT_DH8D: "Bombardier Dash 8-Q400",
22 const.AIRCRAFT_B733: "Boeing 737-300",
23 const.AIRCRAFT_B734: "Boeing 737-400",
24 const.AIRCRAFT_B735: "Boeing 737-500",
25 const.AIRCRAFT_B762: "Boeing 767-200",
26 const.AIRCRAFT_B763: "Boeing 767-300",
27 const.AIRCRAFT_CRJ2: "Bombardier CRJ200",
28 const.AIRCRAFT_F70: "Fokker 70",
29 const.AIRCRAFT_DC3: "Lisunov Li-2",
30 const.AIRCRAFT_T134: "Tupolev Tu-134",
31 const.AIRCRAFT_T154: "Tupolev Tu-154",
32 const.AIRCRAFT_YK40: "Yakovlev Yak-40" }
33
34#-----------------------------------------------------------------------------
35
36class Page(gtk.Alignment):
37 """A page in the flight wizard."""
38 def __init__(self, wizard, title, help, completedHelp = None):
39 """Construct the page."""
40 super(Page, self).__init__(xalign = 0.0, yalign = 0.0,
41 xscale = 1.0, yscale = 1.0)
42 self.set_padding(padding_top = 4, padding_bottom = 4,
43 padding_left = 12, padding_right = 12)
44
45 frame = gtk.Frame()
46 self.add(frame)
47
48 style = self.get_style() if pygobject else self.rc_get_style()
49
50 self._vbox = gtk.VBox()
51 self._vbox.set_homogeneous(False)
52 frame.add(self._vbox)
53
54 eventBox = gtk.EventBox()
55 eventBox.modify_bg(0, style.bg[3])
56
57 alignment = gtk.Alignment(xalign = 0.0, xscale = 0.0)
58
59 label = gtk.Label(title)
60 label.modify_fg(0, style.fg[3])
61 label.modify_font(pango.FontDescription("bold 24"))
62 alignment.set_padding(padding_top = 4, padding_bottom = 4,
63 padding_left = 6, padding_right = 0)
64
65 alignment.add(label)
66 eventBox.add(alignment)
67
68 self._vbox.pack_start(eventBox, False, False, 0)
69
70 mainBox = gtk.VBox()
71
72 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
73 xscale = 1.0, yscale = 1.0)
74 alignment.set_padding(padding_top = 16, padding_bottom = 16,
75 padding_left = 16, padding_right = 16)
76 alignment.add(mainBox)
77 self._vbox.pack_start(alignment, True, True, 0)
78
79 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
80 xscale = 0.0, yscale = 0.0)
81 alignment.set_padding(padding_top = 0, padding_bottom = 16,
82 padding_left = 0, padding_right = 0)
83
84 self._help = help
85 self._completedHelp = completedHelp
86
87 if self._completedHelp is None or \
88 len(help.splitlines())>=len(completedHelp.splitlines()):
89 longerHelp = help
90 else:
91 longerHelp = completedHelp
92
93 self._helpLabel = gtk.Label(completedHelp)
94 # FIXME: should be a constant in common
95 self._helpLabel.set_justify(gtk.Justification.CENTER if pygobject
96 else gtk.JUSTIFY_CENTER)
97 self._helpLabel.set_use_markup(True)
98 alignment.add(self._helpLabel)
99 mainBox.pack_start(alignment, False, False, 0)
100
101 self._mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
102 xscale = 1.0, yscale = 1.0)
103 mainBox.pack_start(self._mainAlignment, True, True, 0)
104
105 buttonAlignment = gtk.Alignment(xalign = 1.0, xscale=0.0, yscale = 0.0)
106 buttonAlignment.set_padding(padding_top = 4, padding_bottom = 10,
107 padding_left = 16, padding_right = 16)
108
109 self._buttonBox = gtk.HBox()
110 self._buttonBox.set_homogeneous(False)
111 self._defaultButton = None
112 buttonAlignment.add(self._buttonBox)
113
114 self._vbox.pack_start(buttonAlignment, False, False, 0)
115
116 self._wizard = wizard
117
118 self._completed = False
119 self._fromPage = None
120
121 def setMainWidget(self, widget):
122 """Set the given widget as the main one."""
123 self._mainAlignment.add(widget)
124
125 def addButton(self, label, default = False, sensitive = True,
126 tooltip = None, clicked = None):
127 """Add a button with the given label.
128
129 Return the button object created."""
130 button = gtk.Button(label)
131 self._buttonBox.pack_start(button, False, False, 4)
132 button.set_use_underline(True)
133 if default:
134 button.set_can_default(True)
135 self._defaultButton = button
136 button.set_sensitive(sensitive)
137 if tooltip is not None:
138 button.set_tooltip_text(tooltip)
139 if clicked is not None:
140 button.connect("clicked", clicked)
141 return button
142
143 def addPreviousButton(self, sensitive = True, clicked = None):
144 """Add the 'Next' button to the page."""
145 return self.addButton(xstr("button_previous"),
146 sensitive = sensitive,
147 tooltip = xstr("button_previous_tooltip"),
148 clicked = clicked)
149
150 def addNextButton(self, default = True, sensitive = True,
151 clicked = None):
152 """Add the 'Next' button to the page."""
153 return self.addButton(xstr("button_next"),
154 default = default,
155 sensitive = sensitive,
156 tooltip = xstr("button_next_tooltip"),
157 clicked = clicked)
158
159 def initialize(self):
160 """Initialize the page.
161
162 It sets up the primary help, and calls the activate() function."""
163 self._helpLabel.set_markup(self._help)
164 self._helpLabel.set_sensitive(True)
165 self.activate()
166
167 def activate(self):
168 """Called when this page becomes active.
169
170 This default implementation does nothing."""
171 pass
172
173 def complete(self):
174 """Called when the page is completed.
175
176 It greys out/changes the help text and then calls finalize()."""
177 self.finalize()
178 if self._completedHelp is None:
179 self._helpLabel.set_sensitive(False)
180 else:
181 self._helpLabel.set_markup(self._completedHelp)
182 self._completed = True
183
184 def finalize(self):
185 """Called when the page is finalized."""
186 pass
187
188 def grabDefault(self):
189 """If the page has a default button, make it the default one."""
190 if self._defaultButton is not None:
191 self._defaultButton.grab_default()
192
193 def reset(self):
194 """Reset the page if the wizard is reset."""
195 self._completed = False
196 self._fromPage = None
197
198 def goBack(self):
199 """Go to the page we were invoked from."""
200 assert self._fromPage is not None
201
202 self._wizard.setCurrentPage(self._fromPage, finalize = False)
203
204#-----------------------------------------------------------------------------
205
206class LoginPage(Page):
207 """The login page."""
208 def __init__(self, wizard):
209 """Construct the login page."""
210 super(LoginPage, self).__init__(wizard, xstr("login"),
211 xstr("loginHelp"))
212
213 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
214 xscale = 0.0, yscale = 0.0)
215
216 table = gtk.Table(2, 3)
217 table.set_row_spacings(4)
218 table.set_col_spacings(32)
219 alignment.add(table)
220 self.setMainWidget(alignment)
221
222 labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
223 xscale = 0.0, yscale = 0.0)
224 label = gtk.Label(xstr("label_pilotID"))
225 label.set_use_underline(True)
226 labelAlignment.add(label)
227 table.attach(labelAlignment, 0, 1, 0, 1)
228
229 self._pilotID = gtk.Entry()
230 self._pilotID.connect("changed", self._setLoginButton)
231 self._pilotID.set_tooltip_text(xstr("login_pilotID_tooltip"))
232 table.attach(self._pilotID, 1, 2, 0, 1)
233 label.set_mnemonic_widget(self._pilotID)
234
235 labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
236 xscale = 0.0, yscale = 0.0)
237 label = gtk.Label(xstr("label_password"))
238 label.set_use_underline(True)
239 labelAlignment.add(label)
240 table.attach(labelAlignment, 0, 1, 1, 2)
241
242 self._password = gtk.Entry()
243 self._password.set_visibility(False)
244 self._password.connect("changed", self._setLoginButton)
245 self._password.set_tooltip_text(xstr("login_password_tooltip"))
246 table.attach(self._password, 1, 2, 1, 2)
247 label.set_mnemonic_widget(self._password)
248
249 self._rememberButton = gtk.CheckButton(xstr("remember_password"))
250 self._rememberButton.set_use_underline(True)
251 self._rememberButton.set_tooltip_text(xstr("login_remember_tooltip"))
252 table.attach(self._rememberButton, 1, 2, 2, 3, ypadding = 8)
253
254 self._loginButton = self.addButton(xstr("button_login"), default = True)
255 self._loginButton.set_sensitive(False)
256 self._loginButton.connect("clicked", self._loginClicked)
257 self._loginButton.set_tooltip_text(xstr("login_button_tooltip"))
258
259 def activate(self):
260 """Activate the page."""
261 config = self._wizard.gui.config
262 self._pilotID.set_text(config.pilotID)
263 self._password.set_text(config.password)
264 self._rememberButton.set_active(config.rememberPassword)
265
266 def _setLoginButton(self, entry):
267 """Set the login button's sensitivity.
268
269 The button is sensitive only if both the pilot ID and the password
270 fields contain values."""
271 self._loginButton.set_sensitive(self._pilotID.get_text()!="" and
272 self._password.get_text()!="")
273
274 def _loginClicked(self, button):
275 """Called when the login button was clicked."""
276 self._loginButton.set_sensitive(False)
277 gui = self._wizard.gui
278 gui.beginBusy(xstr("login_busy"))
279 gui.webHandler.login(self._loginResultCallback,
280 self._pilotID.get_text(),
281 self._password.get_text())
282
283 def _loginResultCallback(self, returned, result):
284 """The login result callback, called in the web handler's thread."""
285 gobject.idle_add(self._handleLoginResult, returned, result)
286
287 def _handleLoginResult(self, returned, result):
288 """Handle the login result."""
289 self._wizard.gui.endBusy()
290 self._loginButton.set_sensitive(True)
291 if returned:
292 if result.loggedIn:
293 config = self._wizard.gui.config
294
295 config.pilotID = self._pilotID.get_text()
296
297 rememberPassword = self._rememberButton.get_active()
298 config.password = self._password.get_text() if rememberPassword \
299 else ""
300
301 config.rememberPassword = rememberPassword
302
303 config.save()
304 self._wizard._loginResult = result
305 self._wizard.nextPage()
306 else:
307 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
308 type = MESSAGETYPE_ERROR,
309 message_format = xstr("login_invalid"))
310 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
311 dialog.set_title(WINDOW_TITLE_BASE)
312 dialog.format_secondary_markup(xstr("login_invalid_sec"))
313 dialog.run()
314 dialog.hide()
315 else:
316 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
317 type = MESSAGETYPE_ERROR,
318 message_format = xstr("login_failconn"))
319 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
320 dialog.set_title(WINDOW_TITLE_BASE)
321 dialog.format_secondary_markup(xstr("login_failconn_sec"))
322
323 dialog.run()
324 dialog.hide()
325
326#-----------------------------------------------------------------------------
327
328class FlightSelectionPage(Page):
329 """The page to select the flight."""
330 def __init__(self, wizard):
331 """Construct the flight selection page."""
332 help = xstr("flightsel_help")
333 completedHelp = xstr("flightsel_chelp")
334 super(FlightSelectionPage, self).__init__(wizard, xstr("flightsel_title"),
335 help, completedHelp = completedHelp)
336
337
338 self._listStore = gtk.ListStore(str, str, str, str)
339 self._flightList = gtk.TreeView(self._listStore)
340 column = gtk.TreeViewColumn(xstr("flightsel_no"), gtk.CellRendererText(),
341 text = 1)
342 column.set_expand(True)
343 self._flightList.append_column(column)
344 column = gtk.TreeViewColumn(xstr("flightsel_deptime"), gtk.CellRendererText(),
345 text = 0)
346 column.set_expand(True)
347 self._flightList.append_column(column)
348 column = gtk.TreeViewColumn(xstr("flightsel_from"), gtk.CellRendererText(),
349 text = 2)
350 column.set_expand(True)
351 self._flightList.append_column(column)
352 column = gtk.TreeViewColumn(xstr("flightsel_to"), gtk.CellRendererText(),
353 text = 3)
354 column.set_expand(True)
355 self._flightList.append_column(column)
356
357 flightSelection = self._flightList.get_selection()
358 flightSelection.connect("changed", self._selectionChanged)
359
360 scrolledWindow = gtk.ScrolledWindow()
361 scrolledWindow.add(self._flightList)
362 scrolledWindow.set_size_request(400, -1)
363 # FIXME: these should be constants in common.py
364 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
365 else gtk.POLICY_AUTOMATIC,
366 gtk.PolicyType.AUTOMATIC if pygobject
367 else gtk.POLICY_AUTOMATIC)
368 scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
369 else gtk.SHADOW_IN)
370
371 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 0.0, yscale = 1.0)
372 alignment.add(scrolledWindow)
373
374 self.setMainWidget(alignment)
375
376 self._button = self.addNextButton(sensitive = False,
377 clicked = self._forwardClicked)
378
379 def activate(self):
380 """Fill the flight list."""
381 self._flightList.set_sensitive(True)
382 self._listStore.clear()
383 for flight in self._wizard.loginResult.flights:
384 self._listStore.append([str(flight.departureTime),
385 flight.callsign,
386 flight.departureICAO,
387 flight.arrivalICAO])
388
389 def finalize(self):
390 """Finalize the page."""
391 self._flightList.set_sensitive(False)
392
393 def _selectionChanged(self, selection):
394 """Called when the selection is changed."""
395 self._button.set_sensitive(selection.count_selected_rows()==1)
396
397 def _forwardClicked(self, button):
398 """Called when the forward button was clicked."""
399 if self._completed:
400 self._wizard.jumpPage(self._nextDistance, finalize = False)
401 else:
402 selection = self._flightList.get_selection()
403 (listStore, iter) = selection.get_selected()
404 path = listStore.get_path(iter)
405 [index] = path.get_indices() if pygobject else path
406
407 flight = self._wizard.loginResult.flights[index]
408 self._wizard._bookedFlight = flight
409 self._wizard.gui.enableFlightInfo()
410
411 self._updateDepartureGate()
412
413 def _updateDepartureGate(self):
414 """Update the departure gate for the booked flight."""
415 flight = self._wizard._bookedFlight
416 if self._wizard.gui.config.onlineGateSystem:
417 if flight.departureICAO=="LHBP":
418 self._wizard.getFleet(self._fleetRetrieved)
419 else:
420 self._wizard.updatePlane(self._planeUpdated,
421 flight.tailNumber,
422 const.PLANE_AWAY)
423 else:
424 self._nextDistance = 2
425 self._wizard.jumpPage(2)
426
427 def _fleetRetrieved(self, fleet):
428 """Called when the fleet has been retrieved."""
429 if fleet is None:
430 self._nextDistance = 2
431 self._wizard.jumpPage(2)
432 else:
433 plane = fleet[self._wizard._bookedFlight.tailNumber]
434 if plane is None:
435 self._nextDistance = 2
436 self._wizard.jumpPage(2)
437 elif plane.gateNumber is not None and \
438 not fleet.isGateConflicting(plane):
439 self._wizard._departureGate = plane.gateNumber
440 self._nextDistance = 2
441 self._wizard.jumpPage(2)
442 else:
443 self._nextDistance = 1
444 self._wizard.nextPage()
445
446 def _planeUpdated(self, success):
447 """Callback for the plane updating."""
448 self._nextDistance = 2
449 self._wizard.jumpPage(2)
450
451#-----------------------------------------------------------------------------
452
453class GateSelectionPage(Page):
454 """Page to select a free gate at LHBP.
455 This page should be displayed only if we have fleet information!."""
456 def __init__(self, wizard):
457 """Construct the gate selection page."""
458 super(GateSelectionPage, self).__init__(wizard, xstr("gatesel_title"),
459 xstr("gatesel_help"))
460
461 self._listStore = gtk.ListStore(str)
462 self._gateList = gtk.TreeView(self._listStore)
463 column = gtk.TreeViewColumn(None, gtk.CellRendererText(),
464 text = 0)
465 column.set_expand(True)
466 self._gateList.append_column(column)
467 self._gateList.set_headers_visible(False)
468
469 gateSelection = self._gateList.get_selection()
470 gateSelection.connect("changed", self._selectionChanged)
471
472 scrolledWindow = gtk.ScrolledWindow()
473 scrolledWindow.add(self._gateList)
474 scrolledWindow.set_size_request(50, -1)
475 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
476 else gtk.POLICY_AUTOMATIC,
477 gtk.PolicyType.AUTOMATIC if pygobject
478 else gtk.POLICY_AUTOMATIC)
479 scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
480 else gtk.SHADOW_IN)
481
482 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 0.0, yscale = 1.0)
483 alignment.add(scrolledWindow)
484
485 self.setMainWidget(alignment)
486
487 self.addPreviousButton(clicked = self._backClicked)
488
489 self._button = self.addNextButton(sensitive = False,
490 clicked = self._forwardClicked)
491
492 def activate(self):
493 """Fill the gate list."""
494 self._listStore.clear()
495 self._gateList.set_sensitive(True)
496 occupiedGateNumbers = self._wizard._fleet.getOccupiedGateNumbers()
497 for gateNumber in const.lhbpGateNumbers:
498 if gateNumber not in occupiedGateNumbers:
499 self._listStore.append([gateNumber])
500
501 def finalize(self):
502 """Finalize the page."""
503 self._gateList.set_sensitive(False)
504
505 def _selectionChanged(self, selection):
506 """Called when the selection is changed."""
507 self._button.set_sensitive(selection.count_selected_rows()==1)
508
509 def _backClicked(self, button):
510 """Called when the Back button is pressed."""
511 self.goBack()
512
513 def _forwardClicked(self, button):
514 """Called when the forward button is clicked."""
515 if not self._completed:
516 selection = self._gateList.get_selection()
517 (listStore, iter) = selection.get_selected()
518 (gateNumber,) = listStore.get(iter, 0)
519
520 self._wizard._departureGate = gateNumber
521
522 self._wizard.updatePlane(self._planeUpdated,
523 self._wizard._bookedFlight.tailNumber,
524 const.PLANE_HOME, gateNumber)
525 else:
526 self._wizard.nextPage()
527
528 def _planeUpdated(self, success):
529 """Callback for the plane updating call."""
530 if success is None or success:
531 self._wizard.nextPage()
532 else:
533 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
534 type = MESSAGETYPE_ERROR,
535 message_format = xstr("gatesel_conflict"))
536 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
537 dialog.set_title(WINDOW_TITLE_BASE)
538 dialog.format_secondary_markup(xstr("gatesel_conflict_sec"))
539 dialog.run()
540 dialog.hide()
541
542 self._wizard.getFleet(self._fleetRetrieved)
543
544 def _fleetRetrieved(self, fleet):
545 """Called when the fleet has been retrieved."""
546 if fleet is None:
547 self._wizard.nextPage()
548 else:
549 self.activate()
550
551#-----------------------------------------------------------------------------
552
553class ConnectPage(Page):
554 """Page which displays the departure airport and gate (if at LHBP)."""
555 def __init__(self, wizard):
556 """Construct the connect page."""
557 help = "Load the aircraft below into the simulator and park it\n" \
558 "at the given airport, at the gate below, if present.\n\n" \
559 "Then press the Connect button to connect to the simulator."
560 completedHelp = "The basic data of your flight can be read below."
561 super(ConnectPage, self).__init__(wizard, xstr("connect_title"),
562 xstr("connect_help"),
563 completedHelp = xstr("connect_chelp"))
564
565 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
566 xscale = 0.0, yscale = 0.0)
567
568 table = gtk.Table(5, 2)
569 table.set_row_spacings(4)
570 table.set_col_spacings(16)
571 table.set_homogeneous(True)
572 alignment.add(table)
573 self.setMainWidget(alignment)
574
575 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
576 label = gtk.Label(xstr("connect_flightno"))
577 labelAlignment.add(label)
578 table.attach(labelAlignment, 0, 1, 0, 1)
579
580 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
581 self._flightNumber = gtk.Label()
582 self._flightNumber.set_width_chars(7)
583 self._flightNumber.set_alignment(0.0, 0.5)
584 labelAlignment.add(self._flightNumber)
585 table.attach(labelAlignment, 1, 2, 0, 1)
586
587 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
588 label = gtk.Label(xstr("connect_acft"))
589 labelAlignment.add(label)
590 table.attach(labelAlignment, 0, 1, 1, 2)
591
592 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
593 self._aircraft = gtk.Label()
594 self._aircraft.set_width_chars(25)
595 self._aircraft.set_alignment(0.0, 0.5)
596 labelAlignment.add(self._aircraft)
597 table.attach(labelAlignment, 1, 2, 1, 2)
598
599 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
600 label = gtk.Label(xstr("connect_tailno"))
601 labelAlignment.add(label)
602 table.attach(labelAlignment, 0, 1, 2, 3)
603
604 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
605 self._tailNumber = gtk.Label()
606 self._tailNumber.set_width_chars(10)
607 self._tailNumber.set_alignment(0.0, 0.5)
608 labelAlignment.add(self._tailNumber)
609 table.attach(labelAlignment, 1, 2, 2, 3)
610
611 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
612 label = gtk.Label(xstr("connect_airport"))
613 labelAlignment.add(label)
614 table.attach(labelAlignment, 0, 1, 3, 4)
615
616 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
617 self._departureICAO = gtk.Label()
618 self._departureICAO.set_width_chars(6)
619 self._departureICAO.set_alignment(0.0, 0.5)
620 labelAlignment.add(self._departureICAO)
621 table.attach(labelAlignment, 1, 2, 3, 4)
622
623 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
624 label = gtk.Label(xstr("connect_gate"))
625 labelAlignment.add(label)
626 table.attach(labelAlignment, 0, 1, 4, 5)
627
628 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
629 self._departureGate = gtk.Label()
630 self._departureGate.set_width_chars(5)
631 self._departureGate.set_alignment(0.0, 0.5)
632 labelAlignment.add(self._departureGate)
633 table.attach(labelAlignment, 1, 2, 4, 5)
634
635 self.addPreviousButton(clicked = self._backClicked)
636
637 self._button = self.addButton(xstr("button_connect"), default = True,
638 tooltip = xstr("button_connect_tooltip"))
639 self._clickedID = self._button.connect("clicked", self._connectClicked)
640
641 def activate(self):
642 """Setup the departure information."""
643 self._button.set_label(xstr("button_connect"))
644 self._button.set_use_underline(True)
645 self._button.set_tooltip_text(xstr("button_connect_tooltip"))
646 self._button.disconnect(self._clickedID)
647 self._clickedID = self._button.connect("clicked", self._connectClicked)
648
649 bookedFlight = self._wizard._bookedFlight
650
651 self._flightNumber.set_markup("<b>" + bookedFlight.callsign + "</b>")
652
653 aircraftType = acftTypeNames[bookedFlight.aircraftType]
654 self._aircraft.set_markup("<b>" + aircraftType + "</b>")
655
656 self._tailNumber.set_markup("<b>" + bookedFlight.tailNumber + "</b>")
657
658 icao = bookedFlight.departureICAO
659 self._departureICAO.set_markup("<b>" + icao + "</b>")
660 gate = self._wizard._departureGate
661 if gate!="-":
662 gate = "<b>" + gate + "</b>"
663 self._departureGate.set_markup(gate)
664
665 def finalize(self):
666 """Finalize the page."""
667 self._button.set_label(xstr("button_next"))
668 self._button.set_use_underline(True)
669 self._button.set_tooltip_text(xstr("button_next_tooltip"))
670 self._button.disconnect(self._clickedID)
671 self._clickedID = self._button.connect("clicked", self._forwardClicked)
672
673 def _backClicked(self, button):
674 """Called when the Back button is pressed."""
675 self.goBack()
676
677 def _connectClicked(self, button):
678 """Called when the Connect button is pressed."""
679 self._wizard._connectSimulator()
680
681 def _forwardClicked(self, button):
682 """Called when the Forward button is pressed."""
683 self._wizard.nextPage()
684
685#-----------------------------------------------------------------------------
686
687class PayloadPage(Page):
688 """Page to allow setting up the payload."""
689 def __init__(self, wizard):
690 """Construct the page."""
691 super(PayloadPage, self).__init__(wizard, xstr("payload_title"),
692 xstr("payload_help"),
693 completedHelp = xstr("payload_chelp"))
694
695 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
696 xscale = 0.0, yscale = 0.0)
697
698 table = gtk.Table(7, 3)
699 table.set_row_spacings(4)
700 table.set_col_spacings(16)
701 table.set_homogeneous(False)
702 alignment.add(table)
703 self.setMainWidget(alignment)
704
705 label = gtk.Label(xstr("payload_crew"))
706 label.set_alignment(0.0, 0.5)
707 table.attach(label, 0, 1, 0, 1)
708
709 self._numCrew = gtk.Label()
710 self._numCrew.set_width_chars(6)
711 self._numCrew.set_alignment(1.0, 0.5)
712 table.attach(self._numCrew, 1, 2, 0, 1)
713
714 label = gtk.Label(xstr("payload_pax"))
715 label.set_alignment(0.0, 0.5)
716 table.attach(label, 0, 1, 1, 2)
717
718 self._numPassengers = gtk.Label()
719 self._numPassengers.set_width_chars(6)
720 self._numPassengers.set_alignment(1.0, 0.5)
721 table.attach(self._numPassengers, 1, 2, 1, 2)
722
723 label = gtk.Label(xstr("payload_bag"))
724 label.set_alignment(0.0, 0.5)
725 table.attach(label, 0, 1, 2, 3)
726
727 self._bagWeight = gtk.Label()
728 self._bagWeight.set_width_chars(6)
729 self._bagWeight.set_alignment(1.0, 0.5)
730 table.attach(self._bagWeight, 1, 2, 2, 3)
731
732 table.attach(gtk.Label("kg"), 2, 3, 2, 3)
733
734 label = gtk.Label(xstr("payload_cargo"))
735 label.set_use_underline(True)
736 label.set_alignment(0.0, 0.5)
737 table.attach(label, 0, 1, 3, 4)
738
739 self._cargoWeight = IntegerEntry(defaultValue = 0)
740 self._cargoWeight.set_width_chars(6)
741 self._cargoWeight.connect("integer-changed", self._cargoWeightChanged)
742 self._cargoWeight.set_tooltip_text(xstr("payload_cargo_tooltip"))
743 table.attach(self._cargoWeight, 1, 2, 3, 4)
744 label.set_mnemonic_widget(self._cargoWeight)
745
746 table.attach(gtk.Label("kg"), 2, 3, 3, 4)
747
748 label = gtk.Label(xstr("payload_mail"))
749 label.set_alignment(0.0, 0.5)
750 table.attach(label, 0, 1, 4, 5)
751
752 self._mailWeight = gtk.Label()
753 self._mailWeight.set_width_chars(6)
754 self._mailWeight.set_alignment(1.0, 0.5)
755 table.attach(self._mailWeight, 1, 2, 4, 5)
756
757 table.attach(gtk.Label("kg"), 2, 3, 4, 5)
758
759 label = gtk.Label("<b>" + xstr("payload_zfw") + "</b>")
760 label.set_alignment(0.0, 0.5)
761 label.set_use_markup(True)
762 table.attach(label, 0, 1, 5, 6)
763
764 self._calculatedZFW = gtk.Label()
765 self._calculatedZFW.set_width_chars(6)
766 self._calculatedZFW.set_alignment(1.0, 0.5)
767 table.attach(self._calculatedZFW, 1, 2, 5, 6)
768
769 table.attach(gtk.Label("kg"), 2, 3, 5, 6)
770
771 self._zfwButton = gtk.Button(xstr("payload_fszfw"))
772 self._zfwButton.set_use_underline(True)
773 self._zfwButton.connect("clicked", self._zfwRequested)
774 self._zfwButton.set_tooltip_text(xstr("payload_fszfw_tooltip"))
775 table.attach(self._zfwButton, 0, 1, 6, 7)
776
777 self._simulatorZFW = gtk.Label("-")
778 self._simulatorZFW.set_width_chars(6)
779 self._simulatorZFW.set_alignment(1.0, 0.5)
780 table.attach(self._simulatorZFW, 1, 2, 6, 7)
781 self._simulatorZFWValue = None
782
783 table.attach(gtk.Label("kg"), 2, 3, 6, 7)
784
785 self._backButton = self.addPreviousButton(clicked = self._backClicked)
786 self._button = self.addNextButton(clicked = self._forwardClicked)
787
788 @property
789 def cargoWeight(self):
790 """Get the cargo weight entered."""
791 return self._cargoWeight.get_int()
792
793 def activate(self):
794 """Setup the information."""
795 bookedFlight = self._wizard._bookedFlight
796 self._numCrew.set_text(str(bookedFlight.numCrew))
797 self._numPassengers.set_text(str(bookedFlight.numPassengers))
798 self._bagWeight.set_text(str(bookedFlight.bagWeight))
799 self._cargoWeight.set_int(bookedFlight.cargoWeight)
800 self._cargoWeight.set_sensitive(True)
801 self._mailWeight.set_text(str(bookedFlight.mailWeight))
802 self._simulatorZFW.set_text("-")
803 self._simulatorZFWValue = None
804 self._zfwButton.set_sensitive(True)
805 self._updateCalculatedZFW()
806
807 def finalize(self):
808 """Finalize the payload page."""
809 self._cargoWeight.set_sensitive(False)
810 self._wizard.gui.initializeWeightHelp()
811
812 def calculateZFW(self):
813 """Calculate the ZFW value."""
814 zfw = self._wizard.gui._flight.aircraft.dow
815 bookedFlight = self._wizard._bookedFlight
816 zfw += (bookedFlight.numCrew + bookedFlight.numPassengers) * 82
817 zfw += bookedFlight.bagWeight
818 zfw += self._cargoWeight.get_int()
819 zfw += bookedFlight.mailWeight
820 return zfw
821
822 def _updateCalculatedZFW(self):
823 """Update the calculated ZFW"""
824 zfw = self.calculateZFW()
825
826 markupBegin = "<b>"
827 markupEnd = "</b>"
828 if self._simulatorZFWValue is not None and \
829 PayloadChecker.isZFWFaulty(self._simulatorZFWValue, zfw):
830 markupBegin += '<span foreground="red">'
831 markupEnd = "</span>" + markupEnd
832 self._calculatedZFW.set_markup(markupBegin + str(zfw) + markupEnd)
833
834 def _cargoWeightChanged(self, entry, weight):
835 """Called when the cargo weight has changed."""
836 self._updateCalculatedZFW()
837
838 def _zfwRequested(self, button):
839 """Called when the ZFW is requested from the simulator."""
840 self._zfwButton.set_sensitive(False)
841 self._backButton.set_sensitive(False)
842 self._button.set_sensitive(False)
843 gui = self._wizard.gui
844 gui.beginBusy(xstr("payload_zfw_busy"))
845 gui.simulator.requestZFW(self._handleZFW)
846
847 def _handleZFW(self, zfw):
848 """Called when the ZFW value is retrieved."""
849 gobject.idle_add(self._processZFW, zfw)
850
851 def _processZFW(self, zfw):
852 """Process the given ZFW value received from the simulator."""
853 self._wizard.gui.endBusy()
854 self._zfwButton.set_sensitive(True)
855 self._backButton.set_sensitive(True)
856 self._button.set_sensitive(True)
857 self._simulatorZFWValue = zfw
858 self._simulatorZFW.set_text("%.0f" % (zfw,))
859 self._updateCalculatedZFW()
860
861 def _forwardClicked(self, button):
862 """Called when the forward button is clicked."""
863 self._wizard.nextPage()
864
865 def _backClicked(self, button):
866 """Called when the Back button is pressed."""
867 self.goBack()
868
869#-----------------------------------------------------------------------------
870
871class TimePage(Page):
872 """Page displaying the departure and arrival times and allows querying the
873 current time from the flight simulator."""
874 def __init__(self, wizard):
875 super(TimePage, self).__init__(wizard, xstr("time_title"),
876 xstr("time_help"),
877 completedHelp = xstr("time_chelp"))
878
879 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
880 xscale = 0.0, yscale = 0.0)
881
882 table = gtk.Table(3, 2)
883 table.set_row_spacings(4)
884 table.set_col_spacings(16)
885 table.set_homogeneous(False)
886 alignment.add(table)
887 self.setMainWidget(alignment)
888
889 label = gtk.Label(xstr("time_departure"))
890 label.set_alignment(0.0, 0.5)
891 table.attach(label, 0, 1, 0, 1)
892
893 self._departure = gtk.Label()
894 self._departure.set_alignment(0.0, 0.5)
895 table.attach(self._departure, 1, 2, 0, 1)
896
897 label = gtk.Label(xstr("time_arrival"))
898 label.set_alignment(0.0, 0.5)
899 table.attach(label, 0, 1, 1, 2)
900
901 self._arrival = gtk.Label()
902 self._arrival.set_alignment(0.0, 0.5)
903 table.attach(self._arrival, 1, 2, 1, 2)
904
905 self._timeButton = gtk.Button(xstr("time_fs"))
906 self._timeButton.set_use_underline(True)
907 self._timeButton.set_tooltip_text(xstr("time_fs_tooltip"))
908 self._timeButton.connect("clicked", self._timeRequested)
909 table.attach(self._timeButton, 0, 1, 2, 3)
910
911 self._simulatorTime = gtk.Label("-")
912 self._simulatorTime.set_alignment(0.0, 0.5)
913 table.attach(self._simulatorTime, 1, 2, 2, 3)
914
915 self._backButton = self.addPreviousButton(clicked = self._backClicked)
916 self._button = self.addNextButton(clicked = self._forwardClicked)
917
918 def activate(self):
919 """Activate the page."""
920 self._timeButton.set_sensitive(True)
921 bookedFlight = self._wizard._bookedFlight
922 self._departure.set_text(str(bookedFlight.departureTime.time()))
923 self._arrival.set_text(str(bookedFlight.arrivalTime.time()))
924 self._simulatorTime.set_text("-")
925
926 def _timeRequested(self, button):
927 """Request the time from the simulator."""
928 self._timeButton.set_sensitive(False)
929 self._backButton.set_sensitive(False)
930 self._button.set_sensitive(False)
931 self._wizard.gui.beginBusy(xstr("time_busy"))
932 self._wizard.gui.simulator.requestTime(self._handleTime)
933
934 def _handleTime(self, timestamp):
935 """Handle the result of a time retrieval."""
936 gobject.idle_add(self._processTime, timestamp)
937
938 def _processTime(self, timestamp):
939 """Process the given time."""
940 self._wizard.gui.endBusy()
941 self._timeButton.set_sensitive(True)
942 self._backButton.set_sensitive(True)
943 self._button.set_sensitive(True)
944 tm = time.gmtime(timestamp)
945 t = datetime.time(tm.tm_hour, tm.tm_min, tm.tm_sec)
946 self._simulatorTime.set_text(str(t))
947
948 ts = tm.tm_hour * 3600 + tm.tm_min * 60 + tm.tm_sec
949 dt = self._wizard._bookedFlight.departureTime.time()
950 dts = dt.hour * 3600 + dt.minute * 60 + dt.second
951 diff = dts-ts
952
953 markupBegin = ""
954 markupEnd = ""
955 if diff < 0:
956 markupBegin = '<b><span foreground="red">'
957 markupEnd = '</span></b>'
958 elif diff < 3*60 or diff > 30*60:
959 markupBegin = '<b><span foreground="orange">'
960 markupEnd = '</span></b>'
961
962 self._departure.set_markup(markupBegin + str(dt) + markupEnd)
963
964 def _backClicked(self, button):
965 """Called when the Back button is pressed."""
966 self.goBack()
967
968 def _forwardClicked(self, button):
969 """Called when the forward button is clicked."""
970 if not self._completed:
971 gui = self._wizard.gui
972 gui.beginBusy(xstr("fuel_get_busy"))
973
974 gui.simulator.getFuel(gui.flight.aircraft.fuelTanks,
975 self._handleFuel)
976 else:
977 self._wizard.nextPage()
978
979 def _handleFuel(self, fuelData):
980 """Callback for the fuel query operation."""
981 gobject.idle_add(self._processFuel, fuelData)
982
983 def _processFuel(self, fuelData):
984 """Process the given fuel data."""
985 self._wizard.gui.endBusy()
986 self._wizard._fuelData = fuelData
987 self._wizard.nextPage()
988
989#-----------------------------------------------------------------------------
990
991class FuelTank(gtk.VBox):
992 """Widget for the fuel tank."""
993 def __init__(self, fuelTank, name, capacity, currentWeight):
994 """Construct the widget for the tank with the given name."""
995 super(FuelTank, self).__init__()
996
997 self.fuelTank = fuelTank
998 self.capacity = capacity
999 self.currentWeight = currentWeight
1000 self.expectedWeight = currentWeight
1001
1002 label = gtk.Label("<b>" + name + "</b>")
1003 label.set_use_markup(True)
1004 label.set_justify(JUSTIFY_CENTER)
1005 label.set_alignment(0.5, 1.0)
1006 self.pack_start(label, False, False, 4)
1007
1008 self._tankFigure = gtk.DrawingArea()
1009 self._tankFigure.set_size_request(38, -1)
1010
1011 if pygobject:
1012 self._tankFigure.connect("draw", self._drawTankFigure)
1013 else:
1014 self._tankFigure.connect("expose_event", self._drawTankFigure)
1015
1016 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1017 xscale = 0.0, yscale = 1.0)
1018 alignment.add(self._tankFigure)
1019
1020 self.pack_start(alignment, True, True, 4)
1021
1022 self._expectedButton = gtk.SpinButton()
1023 self._expectedButton.set_numeric(True)
1024 self._expectedButton.set_range(0, self.capacity)
1025 self._expectedButton.set_increments(10, 100)
1026 self._expectedButton.set_value(currentWeight)
1027 self._expectedButton.set_alignment(1.0)
1028 self._expectedButton.set_width_chars(5)
1029 self._expectedButton.connect("value-changed", self._expectedChanged)
1030
1031 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1032 xscale = 0.0, yscale = 1.0)
1033 alignment.add(self._expectedButton)
1034 self.pack_start(alignment, False, False, 4)
1035
1036 def setCurrent(self, currentWeight):
1037 """Set the current weight."""
1038 self.currentWeight = currentWeight
1039 self._redraw()
1040
1041 def isCorrect(self):
1042 """Determine if the contents of the fuel tank are as expected"""
1043 return abs(self.expectedWeight - self.currentWeight)<=1
1044
1045 def disable(self):
1046 """Disable the fuel tank."""
1047 self._expectedButton.set_sensitive(False)
1048
1049 def _redraw(self):
1050 """Redraw the tank figure."""
1051 self._tankFigure.queue_draw()
1052
1053 def _drawTankFigure(self, connStateArea, eventOrContext):
1054 """Draw the tank figure."""
1055 triangleSize = 5
1056
1057 context = eventOrContext if pygobject else connStateArea.window.cairo_create()
1058
1059 width = connStateArea.get_allocated_width() if pygobject \
1060 else connStateArea.allocation.width
1061 height = connStateArea.get_allocated_height() if pygobject \
1062 else connStateArea.allocation.height
1063
1064 rectangleX0 = triangleSize
1065 rectangleY0 = triangleSize
1066 rectangleX1 = width - 1 - triangleSize
1067 rectangleY1 = height - 1 - triangleSize
1068 rectangleLineWidth = 2.0
1069
1070 context.set_source_rgb(0.0, 0.0, 0.0)
1071 context.set_line_width(rectangleLineWidth)
1072 context.rectangle(rectangleX0 + rectangleLineWidth/2,
1073 rectangleY0 + rectangleLineWidth/2,
1074 rectangleX1 - rectangleX0 - rectangleLineWidth,
1075 rectangleY1 - rectangleY0 - rectangleLineWidth)
1076 context.stroke()
1077
1078 rectangleInnerLeft = rectangleX0 + rectangleLineWidth
1079 rectangleInnerRight = rectangleX1 - rectangleLineWidth
1080 rectangleInnerTop = rectangleY0 + rectangleLineWidth
1081 rectangleInnerBottom = rectangleY1 - rectangleLineWidth
1082
1083 rectangleInnerWidth = rectangleInnerRight - rectangleInnerLeft
1084 rectangleInnerHeight = rectangleInnerBottom - rectangleInnerTop
1085
1086 context.set_source_rgb(1.0, 0.9, 0.6)
1087 currentHeight = self.currentWeight * rectangleInnerHeight / self.capacity
1088 currentX = rectangleInnerTop + rectangleInnerHeight - currentHeight
1089 context.rectangle(rectangleInnerLeft,
1090 rectangleInnerTop + rectangleInnerHeight - currentHeight,
1091 rectangleInnerWidth, currentHeight)
1092 context.fill()
1093
1094 expectedHeight = self.expectedWeight * rectangleInnerHeight / self.capacity
1095 expectedY = rectangleInnerTop + rectangleInnerHeight - expectedHeight
1096
1097 context.set_line_width(1.5)
1098 context.set_source_rgb(0.0, 0.85, 0.85)
1099 context.move_to(rectangleX0, expectedY)
1100 context.line_to(rectangleX1, expectedY)
1101 context.stroke()
1102
1103 context.set_line_width(0.0)
1104 context.move_to(0, expectedY - triangleSize)
1105 context.line_to(0, expectedY + triangleSize)
1106 context.line_to(rectangleX0 + 1, expectedY)
1107 context.line_to(0, expectedY - triangleSize)
1108 context.fill()
1109
1110 context.set_line_width(0.0)
1111 context.move_to(width, expectedY - triangleSize)
1112 context.line_to(width, expectedY + triangleSize)
1113 context.line_to(rectangleX1 - 1, expectedY)
1114 context.line_to(width, expectedY - triangleSize)
1115 context.fill()
1116
1117 def _expectedChanged(self, spinButton):
1118 """Called when the expected value has changed."""
1119 self.expectedWeight = spinButton.get_value_as_int()
1120 self._redraw()
1121
1122#-----------------------------------------------------------------------------
1123
1124class FuelPage(Page):
1125 """The page containing the fuel tank filling."""
1126 _pumpStep = 0.02
1127
1128 def __init__(self, wizard):
1129 """Construct the page."""
1130 super(FuelPage, self).__init__(wizard, xstr("fuel_title"),
1131 xstr("fuel_help"),
1132 completedHelp = xstr("fuel_chelp"))
1133
1134 self._fuelTanks = []
1135 self._fuelTable = None
1136 self._fuelAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1137 xscale = 0.0, yscale = 1.0)
1138 self.setMainWidget(self._fuelAlignment)
1139
1140 tanks = acft.MostFuelTankAircraft.fuelTanks
1141 tankData = ((2500, 3900),) * len(tanks)
1142 self._setupTanks(tanks, tankData)
1143
1144 self._backButton = self.addPreviousButton(clicked = self._backClicked)
1145 self._button = self.addNextButton(clicked = self._forwardClicked)
1146
1147 self._pumpIndex = 0
1148
1149 def activate(self):
1150 """Activate the page."""
1151 gui = self._wizard.gui
1152
1153 self._setupTanks(gui.flight.aircraft.fuelTanks,
1154 self._wizard._fuelData)
1155
1156 def finalize(self):
1157 """Finalize the page."""
1158 for fuelTank in self._fuelTanks:
1159 fuelTank.disable()
1160
1161 def _backClicked(self, button):
1162 """Called when the Back button is pressed."""
1163 self.goBack()
1164
1165 def _forwardClicked(self, button):
1166 """Called when the forward button is clicked."""
1167 if not self._completed:
1168 self._pumpIndex = 0
1169 self._wizard.gui.beginBusy(xstr("fuel_pump_busy"))
1170 self._pump()
1171 else:
1172 self._wizard.nextPage()
1173
1174 def _setupTanks(self, tanks, tankData):
1175 """Setup the tanks for the given data."""
1176 numTanks = len(tanks)
1177 if self._fuelTable is not None:
1178 self._fuelAlignment.remove(self._fuelTable)
1179
1180 self._fuelTanks = []
1181 self._fuelTable = gtk.Table(numTanks, 1)
1182 self._fuelTable.set_col_spacings(16)
1183 for i in range(0, numTanks):
1184 tank = tanks[i]
1185 (current, capacity) = tankData[i]
1186
1187 fuelTank = FuelTank(tank,
1188 xstr("fuel_tank_" +
1189 const.fuelTank2string(tank)),
1190 capacity, current)
1191 self._fuelTable.attach(fuelTank, i, i+1, 0, 1)
1192 self._fuelTanks.append(fuelTank)
1193
1194 self._fuelAlignment.add(self._fuelTable)
1195 self.show_all()
1196
1197 def _pump(self):
1198 """Perform one step of pumping.
1199
1200 It is checked, if the current tank's contents are of the right
1201 quantity. If not, it is filled one step further to the desired
1202 contents. Otherwise the next tank is started. If all tanks are are
1203 filled, the next page is selected."""
1204 numTanks = len(self._fuelTanks)
1205
1206 fuelTank = None
1207 while self._pumpIndex < numTanks:
1208 fuelTank = self._fuelTanks[self._pumpIndex]
1209 if fuelTank.isCorrect():
1210 self._pumpIndex += 1
1211 fuelTank = None
1212 else:
1213 break
1214
1215 if fuelTank is None:
1216 self._wizard.gui.endBusy()
1217 self._wizard.nextPage()
1218 else:
1219 currentLevel = fuelTank.currentWeight / fuelTank.capacity
1220 expectedLevel = fuelTank.expectedWeight / fuelTank.capacity
1221 if currentLevel<expectedLevel:
1222 currentLevel += FuelPage._pumpStep
1223 if currentLevel>expectedLevel: currentLevel = expectedLevel
1224 else:
1225 currentLevel -= FuelPage._pumpStep
1226 if currentLevel<expectedLevel: currentLevel = expectedLevel
1227 fuelTank.setCurrent(currentLevel * fuelTank.capacity)
1228 self._wizard.gui.simulator.setFuelLevel([(fuelTank.fuelTank,
1229 currentLevel)])
1230 gobject.timeout_add(50, self._pump)
1231
1232#-----------------------------------------------------------------------------
1233
1234class RoutePage(Page):
1235 """The page containing the route and the flight level."""
1236 def __init__(self, wizard):
1237 """Construct the page."""
1238 super(RoutePage, self).__init__(wizard, xstr("route_title"),
1239 xstr("route_help"),
1240 completedHelp = xstr("route_chelp"))
1241
1242 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1243 xscale = 0.0, yscale = 0.0)
1244
1245 mainBox = gtk.VBox()
1246 alignment.add(mainBox)
1247 self.setMainWidget(alignment)
1248
1249 levelBox = gtk.HBox()
1250
1251 label = gtk.Label(xstr("route_level"))
1252 label.set_use_underline(True)
1253 levelBox.pack_start(label, True, True, 0)
1254
1255 self._cruiseLevel = gtk.SpinButton()
1256 self._cruiseLevel.set_increments(step = 10, page = 100)
1257 self._cruiseLevel.set_range(min = 50, max = 500)
1258 self._cruiseLevel.set_tooltip_text(xstr("route_level_tooltip"))
1259 self._cruiseLevel.set_numeric(True)
1260 self._cruiseLevel.connect("value-changed", self._cruiseLevelChanged)
1261 label.set_mnemonic_widget(self._cruiseLevel)
1262 self._filedCruiseLevel = 240
1263
1264 levelBox.pack_start(self._cruiseLevel, False, False, 8)
1265
1266 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
1267 xscale = 0.0, yscale = 0.0)
1268 alignment.add(levelBox)
1269
1270 mainBox.pack_start(alignment, False, False, 0)
1271
1272
1273 routeBox = gtk.VBox()
1274
1275 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
1276 xscale = 0.0, yscale = 0.0)
1277 label = gtk.Label(xstr("route_route"))
1278 label.set_use_underline(True)
1279 alignment.add(label)
1280 routeBox.pack_start(alignment, True, True, 0)
1281
1282 routeWindow = gtk.ScrolledWindow()
1283 routeWindow.set_size_request(400, 80)
1284 routeWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
1285 else gtk.SHADOW_IN)
1286 routeWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1287 else gtk.POLICY_AUTOMATIC,
1288 gtk.PolicyType.AUTOMATIC if pygobject
1289 else gtk.POLICY_AUTOMATIC)
1290
1291 self._uppercasingRoute = False
1292
1293 self._route = gtk.TextView()
1294 self._route.set_tooltip_text(xstr("route_route_tooltip"))
1295 self._route.set_wrap_mode(WRAP_WORD)
1296 self._route.get_buffer().connect("changed", self._routeChanged)
1297 self._route.get_buffer().connect_after("insert-text", self._routeInserted)
1298 routeWindow.add(self._route)
1299
1300 label.set_mnemonic_widget(self._route)
1301 routeBox.pack_start(routeWindow, True, True, 0)
1302
1303 mainBox.pack_start(routeBox, True, True, 8)
1304
1305 self._backButton = self.addPreviousButton(clicked = self._backClicked)
1306 self._button = self.addNextButton(clicked = self._forwardClicked)
1307
1308 @property
1309 def filedCruiseLevel(self):
1310 """Get the filed cruise level."""
1311 return self._filedCruiseLevel
1312
1313 @property
1314 def cruiseLevel(self):
1315 """Get the cruise level."""
1316 return self._cruiseLevel.get_value_as_int()
1317
1318 @property
1319 def route(self):
1320 """Get the route."""
1321 return self._getRoute()
1322
1323 def activate(self):
1324 """Setup the route from the booked flight."""
1325 self._cruiseLevel.set_value(240)
1326 self._filedCruiseLevel = 240
1327 self._route.get_buffer().set_text(self._wizard._bookedFlight.route)
1328 self._updateForwardButton()
1329
1330 def _getRoute(self):
1331 """Get the text of the route."""
1332 buffer = self._route.get_buffer()
1333 return buffer.get_text(buffer.get_start_iter(),
1334 buffer.get_end_iter(), True)
1335
1336 def _updateForwardButton(self):
1337 """Update the sensitivity of the forward button."""
1338 self._button.set_sensitive(self._cruiseLevel.get_value_as_int()>=50 and \
1339 self._getRoute()!="")
1340
1341 def _cruiseLevelChanged(self, spinButton):
1342 """Called when the cruise level has changed."""
1343 self._updateForwardButton()
1344
1345 def _routeChanged(self, textBuffer):
1346 """Called when the route has changed."""
1347 if not self._uppercasingRoute:
1348 self._updateForwardButton()
1349
1350 def _routeInserted(self, textBuffer, iter, text, length):
1351 """Called when new characters are inserted into the route.
1352
1353 It uppercases all characters."""
1354 if not self._uppercasingRoute:
1355 self._uppercasingRoute = True
1356
1357 iter1 = iter.copy()
1358 iter1.backward_chars(length)
1359 textBuffer.delete(iter, iter1)
1360
1361 textBuffer.insert(iter, text.upper())
1362
1363 self._uppercasingRoute = False
1364
1365 def _backClicked(self, button):
1366 """Called when the Back button is pressed."""
1367 self.goBack()
1368
1369 def _forwardClicked(self, button):
1370 """Called when the Forward button is clicked."""
1371 if self._completed:
1372 self._wizard.nextPage()
1373 else:
1374 bookedFlight = self._wizard._bookedFlight
1375 self._filedCruiseLevel = self.cruiseLevel
1376 self._wizard.gui.beginBusy(xstr("route_down_notams"))
1377 self._wizard.gui.webHandler.getNOTAMs(self._notamsCallback,
1378 bookedFlight.departureICAO,
1379 bookedFlight.arrivalICAO)
1380
1381 def _notamsCallback(self, returned, result):
1382 """Callback for the NOTAMs."""
1383 gobject.idle_add(self._handleNOTAMs, returned, result)
1384
1385 def _handleNOTAMs(self, returned, result):
1386 """Handle the NOTAMs."""
1387 if returned:
1388 self._wizard._departureNOTAMs = result.departureNOTAMs
1389 self._wizard._arrivalNOTAMs = result.arrivalNOTAMs
1390 else:
1391 self._wizard._departureNOTAMs = None
1392 self._wizard._arrivalNOTAMs = None
1393
1394 bookedFlight = self._wizard._bookedFlight
1395 self._wizard.gui.beginBusy(xstr("route_down_metars"))
1396 self._wizard.gui.webHandler.getMETARs(self._metarsCallback,
1397 [bookedFlight.departureICAO,
1398 bookedFlight.arrivalICAO])
1399
1400 def _metarsCallback(self, returned, result):
1401 """Callback for the METARs."""
1402 gobject.idle_add(self._handleMETARs, returned, result)
1403
1404 def _handleMETARs(self, returned, result):
1405 """Handle the METARs."""
1406 self._wizard._departureMETAR = None
1407 self._wizard._arrivalMETAR = None
1408 bookedFlight = self._wizard._bookedFlight
1409 if returned:
1410 if bookedFlight.departureICAO in result.metars:
1411 self._wizard._departureMETAR = result.metars[bookedFlight.departureICAO]
1412 if bookedFlight.arrivalICAO in result.metars:
1413 self._wizard._arrivalMETAR = result.metars[bookedFlight.arrivalICAO]
1414
1415 self._wizard.gui.endBusy()
1416 self._backButton.set_sensitive(True)
1417 self._button.set_sensitive(True)
1418 self._wizard.nextPage()
1419
1420#-----------------------------------------------------------------------------
1421
1422class BriefingPage(Page):
1423 """Page for the briefing."""
1424 def __init__(self, wizard, departure):
1425 """Construct the briefing page."""
1426 self._departure = departure
1427
1428 title = xstr("briefing_title") % (1 if departure else 2,
1429 xstr("briefing_departure")
1430 if departure
1431 else xstr("briefing_arrival"))
1432 super(BriefingPage, self).__init__(wizard, title, xstr("briefing_help"),
1433 completedHelp = xstr("briefing_chelp"))
1434
1435 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1436 xscale = 1.0, yscale = 1.0)
1437
1438 mainBox = gtk.VBox()
1439 alignment.add(mainBox)
1440 self.setMainWidget(alignment)
1441
1442 self._notamsFrame = gtk.Frame()
1443 self._notamsFrame.set_label(xstr("briefing_notams_init"))
1444 scrolledWindow = gtk.ScrolledWindow()
1445 scrolledWindow.set_size_request(-1, 128)
1446 # FIXME: these constants should be in common
1447 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1448 else gtk.POLICY_AUTOMATIC,
1449 gtk.PolicyType.AUTOMATIC if pygobject
1450 else gtk.POLICY_AUTOMATIC)
1451 self._notams = gtk.TextView()
1452 self._notams.set_editable(False)
1453 self._notams.set_accepts_tab(False)
1454 self._notams.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
1455 scrolledWindow.add(self._notams)
1456 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
1457 xscale = 1.0, yscale = 1.0)
1458 alignment.set_padding(padding_top = 4, padding_bottom = 0,
1459 padding_left = 0, padding_right = 0)
1460 alignment.add(scrolledWindow)
1461 self._notamsFrame.add(alignment)
1462 mainBox.pack_start(self._notamsFrame, True, True, 4)
1463
1464 self._metarFrame = gtk.Frame()
1465 self._metarFrame.set_label(xstr("briefing_metar_init"))
1466 scrolledWindow = gtk.ScrolledWindow()
1467 scrolledWindow.set_size_request(-1, 32)
1468 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1469 else gtk.POLICY_AUTOMATIC,
1470 gtk.PolicyType.AUTOMATIC if pygobject
1471 else gtk.POLICY_AUTOMATIC)
1472
1473 self._uppercasingMETAR = False
1474
1475 self._metar = gtk.TextView()
1476 self._metar.set_accepts_tab(False)
1477 self._metar.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
1478 self._metar.get_buffer().connect("changed", self._metarChanged)
1479 self._metar.get_buffer().connect_after("insert-text", self._metarInserted)
1480 scrolledWindow.add(self._metar)
1481 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
1482 xscale = 1.0, yscale = 1.0)
1483 alignment.set_padding(padding_top = 4, padding_bottom = 0,
1484 padding_left = 0, padding_right = 0)
1485 alignment.add(scrolledWindow)
1486 self._metarFrame.add(alignment)
1487 mainBox.pack_start(self._metarFrame, True, True, 4)
1488 self.metarEdited = False
1489
1490 self.addPreviousButton(clicked = self._backClicked)
1491 self._button = self.addNextButton(clicked = self._forwardClicked)
1492
1493 @property
1494 def metar(self):
1495 """Get the METAR on the page."""
1496 buffer = self._metar.get_buffer()
1497 return buffer.get_text(buffer.get_start_iter(),
1498 buffer.get_end_iter(), True)
1499
1500 def setMETAR(self, metar):
1501 """Set the metar."""
1502 self._metar.get_buffer().set_text(metar)
1503 self.metarEdited = False
1504
1505 def activate(self):
1506 """Activate the page."""
1507 if not self._departure:
1508 self._button.set_label(xstr("briefing_button"))
1509 self._button.set_has_tooltip(False)
1510 self._button.set_use_stock(False)
1511
1512 bookedFlight = self._wizard._bookedFlight
1513
1514 icao = bookedFlight.departureICAO if self._departure \
1515 else bookedFlight.arrivalICAO
1516 notams = self._wizard._departureNOTAMs if self._departure \
1517 else self._wizard._arrivalNOTAMs
1518 metar = self._wizard._departureMETAR if self._departure \
1519 else self._wizard._arrivalMETAR
1520
1521 self._notamsFrame.set_label(xstr("briefing_notams_template") % (icao,))
1522 buffer = self._notams.get_buffer()
1523 if notams is None:
1524 buffer.set_text(xstr("briefing_notams_failed"))
1525 elif not notams:
1526 buffer.set_text(xstr("briefing_notams_missing"))
1527 else:
1528 s = ""
1529 for notam in notams:
1530 s += str(notam.begin)
1531 if notam.end is not None:
1532 s += " - " + str(notam.end)
1533 elif notam.permanent:
1534 s += " - PERMANENT"
1535 s += "\n"
1536 if notam.repeatCycle:
1537 s += "Repeat cycle: " + notam.repeatCycle + "\n"
1538 s += notam.notice + "\n"
1539 s += "-------------------- * --------------------\n"
1540 buffer.set_text(s)
1541
1542 self._metarFrame.set_label(xstr("briefing_metar_template") % (icao,))
1543 buffer = self._metar.get_buffer()
1544 if metar is None:
1545 buffer.set_text(xstr("briefing_metar_failed"))
1546 else:
1547 buffer.set_text(metar)
1548
1549 label = self._metarFrame.get_label_widget()
1550 label.set_use_underline(True)
1551 label.set_mnemonic_widget(self._metar)
1552
1553 self.metarEdited = False
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 if not self._departure:
1562 if not self._completed:
1563 self._wizard.gui.startMonitoring()
1564 self._button.set_label(xstr("button_next"))
1565 self._button.set_tooltip_text(xstr("button_next_tooltip"))
1566 self.complete()
1567
1568 self._wizard.nextPage()
1569
1570 def _metarChanged(self, buffer):
1571 """Called when the METAR has changed."""
1572 if not self._uppercasingMETAR:
1573 self.metarEdited = True
1574 self._button.set_sensitive(buffer.get_text(buffer.get_start_iter(),
1575 buffer.get_end_iter(),
1576 True)!="")
1577
1578 def _metarInserted(self, textBuffer, iter, text, length):
1579 """Called when new characters are inserted into the METAR.
1580
1581 It uppercases all characters."""
1582 if not self._uppercasingMETAR:
1583 self._uppercasingMETAR = True
1584
1585 iter1 = iter.copy()
1586 iter1.backward_chars(length)
1587 textBuffer.delete(iter, iter1)
1588
1589 textBuffer.insert(iter, text.upper())
1590
1591 self._uppercasingMETAR = False
1592
1593#-----------------------------------------------------------------------------
1594
1595class TakeoffPage(Page):
1596 """Page for entering the takeoff data."""
1597 def __init__(self, wizard):
1598 """Construct the takeoff page."""
1599 super(TakeoffPage, self).__init__(wizard, xstr("takeoff_title"),
1600 xstr("takeoff_help"),
1601 completedHelp = xstr("takeoff_chelp"))
1602
1603 self._forwardAllowed = False
1604
1605 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1606 xscale = 0.0, yscale = 0.0)
1607
1608 table = gtk.Table(5, 4)
1609 table.set_row_spacings(4)
1610 table.set_col_spacings(16)
1611 table.set_homogeneous(False)
1612 alignment.add(table)
1613 self.setMainWidget(alignment)
1614
1615 label = gtk.Label(xstr("takeoff_runway"))
1616 label.set_use_underline(True)
1617 label.set_alignment(0.0, 0.5)
1618 table.attach(label, 0, 1, 0, 1)
1619
1620 self._runway = gtk.Entry()
1621 self._runway.set_width_chars(10)
1622 self._runway.set_tooltip_text(xstr("takeoff_runway_tooltip"))
1623 self._runway.connect("changed", self._upperChanged)
1624 table.attach(self._runway, 1, 3, 0, 1)
1625 label.set_mnemonic_widget(self._runway)
1626
1627 label = gtk.Label(xstr("takeoff_sid"))
1628 label.set_use_underline(True)
1629 label.set_alignment(0.0, 0.5)
1630 table.attach(label, 0, 1, 1, 2)
1631
1632 self._sid = gtk.Entry()
1633 self._sid.set_width_chars(10)
1634 self._sid.set_tooltip_text(xstr("takeoff_sid_tooltip"))
1635 self._sid.connect("changed", self._upperChanged)
1636 table.attach(self._sid, 1, 3, 1, 2)
1637 label.set_mnemonic_widget(self._sid)
1638
1639 label = gtk.Label(xstr("takeoff_v1"))
1640 label.set_use_markup(True)
1641 label.set_use_underline(True)
1642 label.set_alignment(0.0, 0.5)
1643 table.attach(label, 0, 1, 2, 3)
1644
1645 self._v1 = IntegerEntry()
1646 self._v1.set_width_chars(4)
1647 self._v1.set_tooltip_markup(xstr("takeoff_v1_tooltip"))
1648 self._v1.connect("integer-changed", self._valueChanged)
1649 table.attach(self._v1, 2, 3, 2, 3)
1650 label.set_mnemonic_widget(self._v1)
1651
1652 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 2, 3)
1653
1654 label = gtk.Label(xstr("takeoff_vr"))
1655 label.set_use_markup(True)
1656 label.set_use_underline(True)
1657 label.set_alignment(0.0, 0.5)
1658 table.attach(label, 0, 1, 3, 4)
1659
1660 self._vr = IntegerEntry()
1661 self._vr.set_width_chars(4)
1662 self._vr.set_tooltip_markup(xstr("takeoff_vr_tooltip"))
1663 self._vr.connect("integer-changed", self._valueChanged)
1664 table.attach(self._vr, 2, 3, 3, 4)
1665 label.set_mnemonic_widget(self._vr)
1666
1667 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 3, 4)
1668
1669 label = gtk.Label(xstr("takeoff_v2"))
1670 label.set_use_markup(True)
1671 label.set_use_underline(True)
1672 label.set_alignment(0.0, 0.5)
1673 table.attach(label, 0, 1, 4, 5)
1674
1675 self._v2 = IntegerEntry()
1676 self._v2.set_width_chars(4)
1677 self._v2.set_tooltip_markup(xstr("takeoff_v2_tooltip"))
1678 self._v2.connect("integer-changed", self._valueChanged)
1679 table.attach(self._v2, 2, 3, 4, 5)
1680 label.set_mnemonic_widget(self._v2)
1681
1682 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 4, 5)
1683
1684 self.addPreviousButton(clicked = self._backClicked)
1685
1686 self._button = self.addNextButton(clicked = self._forwardClicked)
1687
1688 @property
1689 def runway(self):
1690 """Get the runway."""
1691 return self._runway.get_text()
1692
1693 @property
1694 def sid(self):
1695 """Get the SID."""
1696 return self._sid.get_text()
1697
1698 @property
1699 def v1(self):
1700 """Get the v1 speed."""
1701 return self._v1.get_int()
1702
1703 @property
1704 def vr(self):
1705 """Get the vr speed."""
1706 return self._vr.get_int()
1707
1708 @property
1709 def v2(self):
1710 """Get the v2 speed."""
1711 return self._v2.get_int()
1712
1713 def activate(self):
1714 """Activate the page."""
1715 self._runway.set_text("")
1716 self._runway.set_sensitive(True)
1717 self._sid.set_text("")
1718 self._sid.set_sensitive(True)
1719 self._v1.set_int(None)
1720 self._v1.set_sensitive(True)
1721 self._vr.set_int(None)
1722 self._vr.set_sensitive(True)
1723 self._v2.set_int(None)
1724 self._v2.set_sensitive(True)
1725 self._button.set_sensitive(False)
1726
1727 def finalize(self):
1728 """Finalize the page."""
1729 self._runway.set_sensitive(False)
1730 self._sid.set_sensitive(False)
1731 self._v1.set_sensitive(False)
1732 self._vr.set_sensitive(False)
1733 self._v2.set_sensitive(False)
1734 self._wizard.gui.flight.aircraft.updateV1R2()
1735
1736 def allowForward(self):
1737 """Allow going to the next page."""
1738 self._forwardAllowed = True
1739 self._updateForwardButton()
1740
1741 def _updateForwardButton(self):
1742 """Update the sensitivity of the forward button based on some conditions."""
1743 sensitive = self._forwardAllowed and \
1744 self._runway.get_text()!="" and \
1745 self._sid.get_text()!="" and \
1746 self.v1 is not None and \
1747 self.vr is not None and \
1748 self.v2 is not None and \
1749 self.v1 <= self.vr and \
1750 self.vr <= self.v2
1751 self._button.set_sensitive(sensitive)
1752
1753 def _valueChanged(self, widget, arg = None):
1754 """Called when the value of some widget has changed."""
1755 self._updateForwardButton()
1756
1757 def _upperChanged(self, entry, arg = None):
1758 """Called when the value of some entry widget has changed and the value
1759 should be converted to uppercase."""
1760 entry.set_text(entry.get_text().upper())
1761 self._valueChanged(entry, arg)
1762
1763 def _backClicked(self, button):
1764 """Called when the Back button is pressed."""
1765 self.goBack()
1766
1767 def _forwardClicked(self, button):
1768 """Called when the forward button is clicked."""
1769 self._wizard.nextPage()
1770
1771#-----------------------------------------------------------------------------
1772
1773class LandingPage(Page):
1774 """Page for entering landing data."""
1775 def __init__(self, wizard):
1776 """Construct the landing page."""
1777 super(LandingPage, self).__init__(wizard, xstr("landing_title"),
1778 xstr("landing_help"),
1779 completedHelp = xstr("landing_chelp"))
1780
1781 self._flightEnded = False
1782
1783 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1784 xscale = 0.0, yscale = 0.0)
1785
1786 table = gtk.Table(5, 5)
1787 table.set_row_spacings(4)
1788 table.set_col_spacings(16)
1789 table.set_homogeneous(False)
1790 alignment.add(table)
1791 self.setMainWidget(alignment)
1792
1793 self._starButton = gtk.CheckButton()
1794 self._starButton.connect("clicked", self._starButtonClicked)
1795 table.attach(self._starButton, 0, 1, 0, 1)
1796
1797 label = gtk.Label(xstr("landing_star"))
1798 label.set_use_underline(True)
1799 label.set_alignment(0.0, 0.5)
1800 table.attach(label, 1, 2, 0, 1)
1801
1802 self._star = gtk.Entry()
1803 self._star.set_width_chars(10)
1804 self._star.set_tooltip_text(xstr("landing_star_tooltip"))
1805 self._star.connect("changed", self._upperChanged)
1806 self._star.set_sensitive(False)
1807 table.attach(self._star, 2, 4, 0, 1)
1808 label.set_mnemonic_widget(self._starButton)
1809
1810 self._transitionButton = gtk.CheckButton()
1811 self._transitionButton.connect("clicked", self._transitionButtonClicked)
1812 table.attach(self._transitionButton, 0, 1, 1, 2)
1813
1814 label = gtk.Label(xstr("landing_transition"))
1815 label.set_use_underline(True)
1816 label.set_alignment(0.0, 0.5)
1817 table.attach(label, 1, 2, 1, 2)
1818
1819 self._transition = gtk.Entry()
1820 self._transition.set_width_chars(10)
1821 self._transition.set_tooltip_text(xstr("landing_transition_tooltip"))
1822 self._transition.connect("changed", self._upperChanged)
1823 self._transition.set_sensitive(False)
1824 table.attach(self._transition, 2, 4, 1, 2)
1825 label.set_mnemonic_widget(self._transitionButton)
1826
1827 label = gtk.Label(xstr("landing_runway"))
1828 label.set_use_underline(True)
1829 label.set_alignment(0.0, 0.5)
1830 table.attach(label, 1, 2, 2, 3)
1831
1832 self._runway = gtk.Entry()
1833 self._runway.set_width_chars(10)
1834 self._runway.set_tooltip_text(xstr("landing_runway_tooltip"))
1835 self._runway.connect("changed", self._upperChanged)
1836 table.attach(self._runway, 2, 4, 2, 3)
1837 label.set_mnemonic_widget(self._runway)
1838
1839 label = gtk.Label(xstr("landing_approach"))
1840 label.set_use_underline(True)
1841 label.set_alignment(0.0, 0.5)
1842 table.attach(label, 1, 2, 3, 4)
1843
1844 self._approachType = gtk.Entry()
1845 self._approachType.set_width_chars(10)
1846 self._approachType.set_tooltip_text(xstr("landing_approach_tooltip"))
1847 self._approachType.connect("changed", self._upperChanged)
1848 table.attach(self._approachType, 2, 4, 3, 4)
1849 label.set_mnemonic_widget(self._approachType)
1850
1851 label = gtk.Label(xstr("landing_vref"))
1852 label.set_use_markup(True)
1853 label.set_use_underline(True)
1854 label.set_alignment(0.0, 0.5)
1855 table.attach(label, 1, 2, 5, 6)
1856
1857 self._vref = IntegerEntry()
1858 self._vref.set_width_chars(5)
1859 self._vref.set_tooltip_markup(xstr("landing_vref_tooltip"))
1860 self._vref.connect("integer-changed", self._vrefChanged)
1861 table.attach(self._vref, 3, 4, 5, 6)
1862 label.set_mnemonic_widget(self._vref)
1863
1864 table.attach(gtk.Label(xstr("label_knots")), 4, 5, 5, 6)
1865
1866 self.addPreviousButton(clicked = self._backClicked)
1867
1868 self._button = self.addNextButton(clicked = self._forwardClicked)
1869
1870 # These are needed for correct size calculations
1871 self._starButton.set_active(True)
1872 self._transitionButton.set_active(True)
1873
1874 @property
1875 def star(self):
1876 """Get the STAR or None if none entered."""
1877 return self._star.get_text() if self._starButton.get_active() else None
1878
1879 @property
1880 def transition(self):
1881 """Get the transition or None if none entered."""
1882 return self._transition.get_text() \
1883 if self._transitionButton.get_active() else None
1884
1885 @property
1886 def approachType(self):
1887 """Get the approach type."""
1888 return self._approachType.get_text()
1889
1890 @property
1891 def runway(self):
1892 """Get the runway."""
1893 return self._runway.get_text()
1894
1895 @property
1896 def vref(self):
1897 """Return the landing reference speed."""
1898 return self._vref.get_int()
1899
1900 def activate(self):
1901 """Called when the page is activated."""
1902 self._starButton.set_sensitive(True)
1903 self._starButton.set_active(False)
1904 self._star.set_text("")
1905
1906 self._transitionButton.set_sensitive(True)
1907 self._transitionButton.set_active(False)
1908 self._transition.set_text("")
1909
1910 self._runway.set_text("")
1911 self._runway.set_sensitive(True)
1912
1913 self._approachType.set_text("")
1914 self._approachType.set_sensitive(True)
1915
1916 self._vref.set_int(None)
1917 self._vref.set_sensitive(True)
1918
1919 self._updateForwardButton()
1920
1921 def flightEnded(self):
1922 """Called when the flight has ended."""
1923 self._flightEnded = True
1924 self._updateForwardButton()
1925
1926 def finalize(self):
1927 """Finalize the page."""
1928 self._starButton.set_sensitive(False)
1929 self._star.set_sensitive(False)
1930
1931 self._transitionButton.set_sensitive(False)
1932 self._transition.set_sensitive(False)
1933
1934 self._runway.set_sensitive(False)
1935
1936 self._approachType.set_sensitive(False)
1937
1938 self._vref.set_sensitive(False)
1939 self._wizard.gui.flight.aircraft.updateVRef()
1940 # FIXME: Perhaps a separate initialize() call which would set up
1941 # defaults? -> use reset()
1942 self._flightEnded = False
1943
1944 def _starButtonClicked(self, button):
1945 """Called when the STAR button is clicked."""
1946 active = button.get_active()
1947 self._star.set_sensitive(active)
1948 if active:
1949 self._star.grab_focus()
1950 self._updateForwardButton()
1951
1952 def _transitionButtonClicked(self, button):
1953 """Called when the Transition button is clicked."""
1954 active = button.get_active()
1955 self._transition.set_sensitive(active)
1956 if active:
1957 self._transition.grab_focus()
1958 self._updateForwardButton()
1959
1960 def _updateForwardButton(self):
1961 """Update the sensitivity of the forward button."""
1962 sensitive = self._flightEnded and \
1963 (self._starButton.get_active() or \
1964 self._transitionButton.get_active()) and \
1965 (self._star.get_text()!="" or
1966 not self._starButton.get_active()) and \
1967 (self._transition.get_text()!="" or
1968 not self._transitionButton.get_active()) and \
1969 self._runway.get_text()!="" and \
1970 self._approachType.get_text()!="" and \
1971 self.vref is not None
1972 self._button.set_sensitive(sensitive)
1973
1974 def _upperChanged(self, entry):
1975 """Called for entry widgets that must be converted to uppercase."""
1976 entry.set_text(entry.get_text().upper())
1977 self._updateForwardButton()
1978
1979 def _vrefChanged(self, widget, value):
1980 """Called when the Vref has changed."""
1981 self._updateForwardButton()
1982
1983 def _backClicked(self, button):
1984 """Called when the Back button is pressed."""
1985 self.goBack()
1986
1987 def _forwardClicked(self, button):
1988 """Called when the forward button is clicked."""
1989 if self._wizard.gui.config.onlineGateSystem and \
1990 not self._completed and \
1991 self._wizard.bookedFlight.arrivalICAO=="LHBP":
1992 self._wizard.getFleet(callback = self._fleetRetrieved,
1993 force = True)
1994 else:
1995 self._wizard.nextPage()
1996
1997 def _fleetRetrieved(self, fleet):
1998 """Callback for the fleet retrieval."""
1999 self._wizard.nextPage()
2000
2001#-----------------------------------------------------------------------------
2002
2003class FinishPage(Page):
2004 """Flight finish page."""
2005 _flightTypes = [ ("flighttype_scheduled", const.FLIGHTTYPE_SCHEDULED),
2006 ("flighttype_ot", const.FLIGHTTYPE_OLDTIMER),
2007 ("flighttype_vip", const.FLIGHTTYPE_VIP),
2008 ("flighttype_charter", const.FLIGHTTYPE_CHARTER) ]
2009
2010 def __init__(self, wizard):
2011 """Construct the finish page."""
2012 super(FinishPage, self).__init__(wizard, xstr("finish_title"),
2013 xstr("finish_help"))
2014
2015 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
2016 xscale = 0.0, yscale = 0.0)
2017
2018 table = gtk.Table(8, 2)
2019 table.set_row_spacings(4)
2020 table.set_col_spacings(16)
2021 table.set_homogeneous(False)
2022 alignment.add(table)
2023 self.setMainWidget(alignment)
2024
2025 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2026 label = gtk.Label(xstr("finish_rating"))
2027 labelAlignment.add(label)
2028 table.attach(labelAlignment, 0, 1, 0, 1)
2029
2030 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2031 self._flightRating = gtk.Label()
2032 self._flightRating.set_width_chars(7)
2033 self._flightRating.set_alignment(0.0, 0.5)
2034 self._flightRating.set_use_markup(True)
2035 labelAlignment.add(self._flightRating)
2036 table.attach(labelAlignment, 1, 2, 0, 1)
2037
2038 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2039 label = gtk.Label(xstr("finish_flight_time"))
2040 labelAlignment.add(label)
2041 table.attach(labelAlignment, 0, 1, 1, 2)
2042
2043 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2044 self._flightTime = gtk.Label()
2045 self._flightTime.set_width_chars(10)
2046 self._flightTime.set_alignment(0.0, 0.5)
2047 self._flightTime.set_use_markup(True)
2048 labelAlignment.add(self._flightTime)
2049 table.attach(labelAlignment, 1, 2, 1, 2)
2050
2051 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2052 label = gtk.Label(xstr("finish_block_time"))
2053 labelAlignment.add(label)
2054 table.attach(labelAlignment, 0, 1, 2, 3)
2055
2056 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2057 self._blockTime = gtk.Label()
2058 self._blockTime.set_width_chars(10)
2059 self._blockTime.set_alignment(0.0, 0.5)
2060 self._blockTime.set_use_markup(True)
2061 labelAlignment.add(self._blockTime)
2062 table.attach(labelAlignment, 1, 2, 2, 3)
2063
2064 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2065 label = gtk.Label(xstr("finish_distance"))
2066 labelAlignment.add(label)
2067 table.attach(labelAlignment, 0, 1, 3, 4)
2068
2069 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2070 self._distanceFlown = gtk.Label()
2071 self._distanceFlown.set_width_chars(10)
2072 self._distanceFlown.set_alignment(0.0, 0.5)
2073 self._distanceFlown.set_use_markup(True)
2074 labelAlignment.add(self._distanceFlown)
2075 table.attach(labelAlignment, 1, 2, 3, 4)
2076
2077 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2078 label = gtk.Label(xstr("finish_fuel"))
2079 labelAlignment.add(label)
2080 table.attach(labelAlignment, 0, 1, 4, 5)
2081
2082 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2083 self._fuelUsed = gtk.Label()
2084 self._fuelUsed.set_width_chars(10)
2085 self._fuelUsed.set_alignment(0.0, 0.5)
2086 self._fuelUsed.set_use_markup(True)
2087 labelAlignment.add(self._fuelUsed)
2088 table.attach(labelAlignment, 1, 2, 4, 5)
2089
2090 labelAlignment = gtk.Alignment(xalign = 1.0, xscale = 0.0,
2091 yalign = 0.5, yscale = 0.0)
2092 label = gtk.Label(xstr("finish_type"))
2093 label.set_use_underline(True)
2094 labelAlignment.add(label)
2095 table.attach(labelAlignment, 0, 1, 5, 6)
2096
2097 flightTypeModel = gtk.ListStore(str, int)
2098 for (name, type) in FinishPage._flightTypes:
2099 flightTypeModel.append([xstr(name), type])
2100
2101 self._flightType = gtk.ComboBox(model = flightTypeModel)
2102 renderer = gtk.CellRendererText()
2103 self._flightType.pack_start(renderer, True)
2104 self._flightType.add_attribute(renderer, "text", 0)
2105 self._flightType.set_tooltip_text(xstr("finish_type_tooltip"))
2106 self._flightType.set_active(0)
2107 self._flightType.connect("changed", self._flightTypeChanged)
2108 flightTypeAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2109 flightTypeAlignment.add(self._flightType)
2110 table.attach(flightTypeAlignment, 1, 2, 5, 6)
2111 label.set_mnemonic_widget(self._flightType)
2112
2113 self._onlineFlight = gtk.CheckButton(xstr("finish_online"))
2114 self._onlineFlight.set_use_underline(True)
2115 self._onlineFlight.set_tooltip_text(xstr("finish_online_tooltip"))
2116 onlineFlightAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2117 onlineFlightAlignment.add(self._onlineFlight)
2118 table.attach(onlineFlightAlignment, 1, 2, 6, 7)
2119
2120 labelAlignment = gtk.Alignment(xalign = 1.0, xscale = 0.0,
2121 yalign = 0.5, yscale = 0.0)
2122 self._gateLabel = gtk.Label(xstr("finish_gate"))
2123 self._gateLabel.set_use_underline(True)
2124 labelAlignment.add(self._gateLabel)
2125 table.attach(labelAlignment, 0, 1, 7, 8)
2126
2127 self._gatesModel = gtk.ListStore(str)
2128
2129 self._gate = gtk.ComboBox(model = self._gatesModel)
2130 renderer = gtk.CellRendererText()
2131 self._gate.pack_start(renderer, True)
2132 self._gate.add_attribute(renderer, "text", 0)
2133 self._gate.set_tooltip_text(xstr("finish_gate_tooltip"))
2134 self._gate.connect("changed", self._gateChanged)
2135 gateAlignment = gtk.Alignment(xalign=0.0, xscale=1.0)
2136 gateAlignment.add(self._gate)
2137 table.attach(gateAlignment, 1, 2, 7, 8)
2138 self._gateLabel.set_mnemonic_widget(self._gate)
2139
2140 self.addPreviousButton(clicked = self._backClicked)
2141
2142 self._saveButton = self.addButton(xstr("finish_save"),
2143 sensitive = False,
2144 tooltip = xstr("finish_send_tooltip"))
2145
2146 self._sendButton = self.addButton(xstr("finish_send"), default = True,
2147 sensitive = False,
2148 clicked = self._sendClicked,
2149 tooltip = xstr("finish_send_tooltip"))
2150
2151 @property
2152 def flightType(self):
2153 """Get the flight type."""
2154 index = self._flightType.get_active()
2155 return None if index<0 else self._flightType.get_model()[index][1]
2156
2157 @property
2158 def online(self):
2159 """Get whether the flight was an online flight or not."""
2160 return self._onlineFlight.get_active()
2161
2162 def activate(self):
2163 """Activate the page."""
2164 flight = self._wizard.gui._flight
2165 rating = flight.logger.getRating()
2166 if rating<0:
2167 self._flightRating.set_markup('<b><span foreground="red">NO GO</span></b>')
2168 else:
2169 self._flightRating.set_markup("<b>%.1f %%</b>" % (rating,))
2170
2171 flightLength = flight.flightTimeEnd - flight.flightTimeStart
2172 self._flightTime.set_markup("<b>%s</b>" % \
2173 (util.getTimeIntervalString(flightLength),))
2174
2175 blockLength = flight.blockTimeEnd - flight.blockTimeStart
2176 self._blockTime.set_markup("<b>%s</b>" % \
2177 (util.getTimeIntervalString(blockLength),))
2178
2179 self._distanceFlown.set_markup("<b>%.2f NM</b>" % \
2180 (flight.flownDistance,))
2181
2182 self._fuelUsed.set_markup("<b>%.0f kg</b>" % \
2183 (flight.startFuel - flight.endFuel,))
2184
2185 self._flightType.set_active(-1)
2186 self._onlineFlight.set_active(True)
2187
2188 self._gatesModel.clear()
2189 if self._wizard.gui.config.onlineGateSystem and \
2190 self._wizard.bookedFlight.arrivalICAO=="LHBP":
2191 occupiedGates = self._wizard._fleet.getOccupiedGateNumbers()
2192 for gateNumber in const.lhbpGateNumbers:
2193 if gateNumber not in occupiedGates:
2194 self._gatesModel.append([gateNumber])
2195 self._gateLabel.set_sensitive(True)
2196 self._gate.set_sensitive(True)
2197 self._gate.set_active(-1)
2198 else:
2199 self._gateLabel.set_sensitive(False)
2200 self._gate.set_sensitive(False)
2201
2202 def _backClicked(self, button):
2203 """Called when the Back button is pressed."""
2204 self.goBack()
2205
2206 def _updateButtons(self):
2207 """Update the sensitivity state of the buttons."""
2208 sensitive = self._flightType.get_active()>=0 and \
2209 (self._gatesModel.get_iter_first() is None or
2210 self._gate.get_active()>=0)
2211
2212 #self._saveButton.set_sensitive(sensitive)
2213 self._sendButton.set_sensitive(sensitive)
2214
2215 def _flightTypeChanged(self, comboBox):
2216 """Called when the flight type has changed."""
2217 self._updateButtons()
2218
2219 def _gateChanged(self, comboBox):
2220 """Called when the arrival gate has changed."""
2221 self._updateButtons()
2222
2223 def _sendClicked(self, button):
2224 """Called when the Send button is clicked."""
2225 pirep = PIREP(self._wizard.gui)
2226 gui = self._wizard.gui
2227 gui.beginBusy(xstr("finish_send_busy"))
2228 gui.webHandler.sendPIREP(self._pirepSentCallback, pirep)
2229
2230 def _pirepSentCallback(self, returned, result):
2231 """Callback for the PIREP sending result."""
2232 gobject.idle_add(self._handlePIREPSent, returned, result)
2233
2234 def _handlePIREPSent(self, returned, result):
2235 """Callback for the PIREP sending result."""
2236 self._wizard.gui.endBusy()
2237 secondaryMarkup = None
2238 type = MESSAGETYPE_ERROR
2239 if returned:
2240 if result.success:
2241 type = MESSAGETYPE_INFO
2242 messageFormat = xstr("finish_send_success")
2243 secondaryMarkup = xstr("finish_send_success_sec")
2244 elif result.alreadyFlown:
2245 messageFormat = xstr("finish_send_already")
2246 secondaryMarkup = xstr("finish_send_already_sec")
2247 elif result.notAvailable:
2248 messageFormat = xstr("finish_send_notavail")
2249 else:
2250 messageFormat = xstr("finish_send_unknown")
2251 secondaryMarkup = xstr("finish_send_unknown_sec")
2252 else:
2253 print "PIREP sending failed", result
2254 messageFormat = xstr("finish_send_failed")
2255 secondaryMarkup = xstr("finish_send_failed_sec")
2256
2257 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
2258 type = type, message_format = messageFormat)
2259 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
2260 dialog.set_title(WINDOW_TITLE_BASE)
2261 if secondaryMarkup is not None:
2262 dialog.format_secondary_markup(secondaryMarkup)
2263
2264 dialog.run()
2265 dialog.hide()
2266
2267 if self._wizard.gui.config.onlineGateSystem and returned and result.success:
2268 bookedFlight = self._wizard.bookedFlight
2269 if bookedFlight.arrivalICAO=="LHBP":
2270 iter = self._gate.get_active_iter()
2271 gateNumber = None if iter is None \
2272 else self._gatesModel.get_value(iter, 0)
2273
2274 status = const.PLANE_PARKING if gateNumber is None \
2275 else const.PLANE_HOME
2276 else:
2277 gateNumber = None
2278 status = const.PLANE_AWAY
2279
2280 self._wizard.updatePlane(self._planeUpdated,
2281 bookedFlight.tailNumber,
2282 status, gateNumber = gateNumber)
2283
2284 def _planeUpdated(self, success):
2285 """Callback for the plane updating."""
2286 pass
2287
2288#-----------------------------------------------------------------------------
2289
2290class Wizard(gtk.VBox):
2291 """The flight wizard."""
2292 def __init__(self, gui):
2293 """Construct the wizard."""
2294 super(Wizard, self).__init__()
2295
2296 self.gui = gui
2297
2298 self._pages = []
2299 self._currentPage = None
2300
2301 self._pages.append(LoginPage(self))
2302 self._pages.append(FlightSelectionPage(self))
2303 self._pages.append(GateSelectionPage(self))
2304 self._pages.append(ConnectPage(self))
2305 self._payloadPage = PayloadPage(self)
2306 self._pages.append(self._payloadPage)
2307 self._payloadIndex = len(self._pages)
2308 self._pages.append(TimePage(self))
2309 self._pages.append(FuelPage(self))
2310 self._routePage = RoutePage(self)
2311 self._pages.append(self._routePage)
2312 self._departureBriefingPage = BriefingPage(self, True)
2313 self._pages.append(self._departureBriefingPage)
2314 self._arrivalBriefingPage = BriefingPage(self, False)
2315 self._pages.append(self._arrivalBriefingPage)
2316 self._arrivalBriefingIndex = len(self._pages)
2317 self._takeoffPage = TakeoffPage(self)
2318 self._pages.append(self._takeoffPage)
2319 self._landingPage = LandingPage(self)
2320 self._pages.append(self._landingPage)
2321 self._finishPage = FinishPage(self)
2322 self._pages.append(self._finishPage)
2323
2324 maxWidth = 0
2325 maxHeight = 0
2326 for page in self._pages:
2327 page.show_all()
2328 pageSizeRequest = page.size_request()
2329 width = pageSizeRequest.width if pygobject else pageSizeRequest[0]
2330 height = pageSizeRequest.height if pygobject else pageSizeRequest[1]
2331 maxWidth = max(maxWidth, width)
2332 maxHeight = max(maxHeight, height)
2333 maxWidth += 16
2334 maxHeight += 32
2335 self.set_size_request(maxWidth, maxHeight)
2336
2337 self._initialize()
2338
2339 @property
2340 def loginResult(self):
2341 """Get the login result."""
2342 return self._loginResult
2343
2344 def setCurrentPage(self, index, finalize = False):
2345 """Set the current page to the one with the given index."""
2346 assert index < len(self._pages)
2347
2348 fromPage = self._currentPage
2349 if fromPage is not None:
2350 page = self._pages[fromPage]
2351 if finalize and not page._completed:
2352 page.complete()
2353 self.remove(page)
2354
2355 self._currentPage = index
2356 page = self._pages[index]
2357 self.add(page)
2358 if page._fromPage is None:
2359 page._fromPage = fromPage
2360 page.initialize()
2361 self.show_all()
2362 if fromPage is not None:
2363 self.grabDefault()
2364
2365 @property
2366 def bookedFlight(self):
2367 """Get the booked flight selected."""
2368 return self._bookedFlight
2369
2370 @property
2371 def cargoWeight(self):
2372 """Get the calculated ZFW value."""
2373 return self._payloadPage.cargoWeight
2374
2375 @property
2376 def zfw(self):
2377 """Get the calculated ZFW value."""
2378 return 0 if self._bookedFlight is None \
2379 else self._payloadPage.calculateZFW()
2380
2381 @property
2382 def filedCruiseAltitude(self):
2383 """Get the filed cruise altitude."""
2384 return self._routePage.filedCruiseLevel * 100
2385
2386 @property
2387 def cruiseAltitude(self):
2388 """Get the cruise altitude."""
2389 return self._routePage.cruiseLevel * 100
2390
2391 @property
2392 def route(self):
2393 """Get the route."""
2394 return self._routePage.route
2395
2396 @property
2397 def departureMETAR(self):
2398 """Get the METAR of the departure airport."""
2399 return self._departureBriefingPage.metar
2400
2401 @property
2402 def arrivalMETAR(self):
2403 """Get the METAR of the arrival airport."""
2404 return self._arrivalBriefingPage.metar
2405
2406 @property
2407 def departureRunway(self):
2408 """Get the departure runway."""
2409 return self._takeoffPage.runway
2410
2411 @property
2412 def sid(self):
2413 """Get the SID."""
2414 return self._takeoffPage.sid
2415
2416 @property
2417 def v1(self):
2418 """Get the V1 speed."""
2419 return self._takeoffPage.v1
2420
2421 @property
2422 def vr(self):
2423 """Get the Vr speed."""
2424 return self._takeoffPage.vr
2425
2426 @property
2427 def v2(self):
2428 """Get the V2 speed."""
2429 return self._takeoffPage.v2
2430
2431 @property
2432 def arrivalRunway(self):
2433 """Get the arrival runway."""
2434 return self._landingPage.runway
2435
2436 @property
2437 def star(self):
2438 """Get the STAR."""
2439 return self._landingPage.star
2440
2441 @property
2442 def transition(self):
2443 """Get the transition."""
2444 return self._landingPage.transition
2445
2446 @property
2447 def approachType(self):
2448 """Get the approach type."""
2449 return self._landingPage.approachType
2450
2451 @property
2452 def vref(self):
2453 """Get the Vref speed."""
2454 return self._landingPage.vref
2455
2456 @property
2457 def flightType(self):
2458 """Get the flight type."""
2459 return self._finishPage.flightType
2460
2461 @property
2462 def online(self):
2463 """Get whether the flight was online or not."""
2464 return self._finishPage.online
2465
2466 def nextPage(self, finalize = True):
2467 """Go to the next page."""
2468 self.jumpPage(1, finalize)
2469
2470 def jumpPage(self, count, finalize = True):
2471 """Go to the page which is 'count' pages after the current one."""
2472 self.setCurrentPage(self._currentPage + count, finalize = finalize)
2473
2474 def grabDefault(self):
2475 """Make the default button of the current page the default."""
2476 self._pages[self._currentPage].grabDefault()
2477
2478 def connected(self, fsType, descriptor):
2479 """Called when the connection could be made to the simulator."""
2480 self.nextPage()
2481
2482 def reset(self):
2483 """Resets the wizard to go back to the login page."""
2484 self._initialize()
2485
2486 def setStage(self, stage):
2487 """Set the flight stage to the given one."""
2488 if stage==const.STAGE_TAKEOFF:
2489 self._takeoffPage.allowForward()
2490 elif stage==const.STAGE_LANDING:
2491 if not self._arrivalBriefingPage.metarEdited:
2492 print "Downloading arrival METAR again"
2493 self.gui.webHandler.getMETARs(self._arrivalMETARCallback,
2494 [self._bookedFlight.arrivalICAO])
2495
2496 elif stage==const.STAGE_END:
2497 self._landingPage.flightEnded()
2498
2499 def _initialize(self):
2500 """Initialize the wizard."""
2501 self._fleet = None
2502 self._fleetCallback = None
2503
2504 self._loginResult = None
2505 self._bookedFlight = None
2506 self._departureGate = "-"
2507 self._fuelData = None
2508 self._departureNOTAMs = None
2509 self._departureMETAR = None
2510 self._arrivalNOTAMs = None
2511 self._arrivalMETAR = None
2512
2513 for page in self._pages:
2514 page.reset()
2515
2516 self.setCurrentPage(0)
2517
2518 def getFleet(self, callback, force = False):
2519 """Get the fleet via the GUI and call the given callback."""
2520 self._fleetCallback = callback
2521 self.gui.getFleet(callback = self._fleetRetrieved, force = force)
2522
2523 def _fleetRetrieved(self, fleet):
2524 """Callback for the fleet retrieval."""
2525 self._fleet = fleet
2526 if self._fleetCallback is not None:
2527 self._fleetCallback(fleet)
2528 self._fleetCallback = None
2529
2530 def updatePlane(self, callback, tailNumber, status, gateNumber = None):
2531 """Update the given plane's gate information."""
2532 self.gui.updatePlane(tailNumber, status, gateNumber = gateNumber,
2533 callback = callback)
2534
2535 def _connectSimulator(self):
2536 """Connect to the simulator."""
2537 self.gui.connectSimulator(self._bookedFlight.aircraftType)
2538
2539 def _arrivalMETARCallback(self, returned, result):
2540 """Called when the METAR of the arrival airport is retrieved."""
2541 gobject.idle_add(self._handleArrivalMETAR, returned, result)
2542
2543 def _handleArrivalMETAR(self, returned, result):
2544 """Called when the METAR of the arrival airport is retrieved."""
2545 icao = self._bookedFlight.arrivalICAO
2546 if returned and icao in result.metars:
2547 metar = result.metars[icao]
2548 if metar!="":
2549 self._arrivalBriefingPage.setMETAR(metar)
2550
2551#-----------------------------------------------------------------------------
2552
Note: See TracBrowser for help on using the repository browser.