source: src/mlx/gui/flight.py@ 145:0f8b76274d8e

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

Added mnemonics to the fuel tanks.

File size: 98.3 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_use_underline(True)
1005 label.set_justify(JUSTIFY_CENTER)
1006 label.set_alignment(0.5, 1.0)
1007 self.pack_start(label, False, False, 4)
1008
1009 self._tankFigure = gtk.EventBox()
1010 self._tankFigure.set_size_request(38, -1)
1011 self._tankFigure.set_visible_window(False)
1012 self._tankFigure.set_tooltip_markup(xstr("fuel_tank_tooltip"))
1013
1014 if pygobject:
1015 self._tankFigure.connect("draw", self._drawTankFigure)
1016 else:
1017 self._tankFigure.connect("expose_event", self._drawTankFigure)
1018 self._tankFigure.connect("button_press_event", self._buttonPressed)
1019 self._tankFigure.connect("motion_notify_event", self._motionNotify)
1020 self._tankFigure.connect("scroll-event", self._scrolled)
1021
1022 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1023 xscale = 0.0, yscale = 1.0)
1024 alignment.add(self._tankFigure)
1025
1026 self.pack_start(alignment, True, True, 4)
1027
1028 self._expectedButton = gtk.SpinButton()
1029 self._expectedButton.set_numeric(True)
1030 self._expectedButton.set_range(0, self.capacity)
1031 self._expectedButton.set_increments(10, 100)
1032 self._expectedButton.set_value(currentWeight)
1033 self._expectedButton.set_alignment(1.0)
1034 self._expectedButton.set_width_chars(5)
1035 self._expectedButton.connect("value-changed", self._expectedChanged)
1036
1037 label.set_mnemonic_widget(self._expectedButton)
1038
1039 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1040 xscale = 0.0, yscale = 1.0)
1041 alignment.add(self._expectedButton)
1042 self.pack_start(alignment, False, False, 4)
1043
1044 def setCurrent(self, currentWeight):
1045 """Set the current weight."""
1046 self.currentWeight = currentWeight
1047 self._redraw()
1048
1049 def isCorrect(self):
1050 """Determine if the contents of the fuel tank are as expected"""
1051 return abs(self.expectedWeight - self.currentWeight)<=1
1052
1053 def disable(self):
1054 """Disable the fuel tank."""
1055 self._expectedButton.set_sensitive(False)
1056
1057 def _redraw(self):
1058 """Redraw the tank figure."""
1059 self._tankFigure.queue_draw()
1060
1061 def _drawTankFigure(self, tankFigure, eventOrContext):
1062 """Draw the tank figure."""
1063 triangleSize = 5
1064
1065 context = eventOrContext if pygobject else tankFigure.window.cairo_create()
1066 (xOffset, yOffset) = (0, 0) if pygobject \
1067 else (tankFigure.allocation.x, tankFigure.allocation.y)
1068
1069 width = tankFigure.get_allocated_width() if pygobject \
1070 else tankFigure.allocation.width
1071 height = tankFigure.get_allocated_height() if pygobject \
1072 else tankFigure.allocation.height
1073
1074 rectangleX0 = triangleSize
1075 rectangleY0 = triangleSize
1076 rectangleX1 = width - 1 - triangleSize
1077 rectangleY1 = height - 1 - triangleSize
1078 rectangleLineWidth = 2.0
1079
1080 context.set_source_rgb(0.0, 0.0, 0.0)
1081 context.set_line_width(rectangleLineWidth)
1082 context.rectangle(xOffset + rectangleX0 + rectangleLineWidth/2,
1083 yOffset + rectangleY0 + rectangleLineWidth/2,
1084 rectangleX1 - rectangleX0 - rectangleLineWidth,
1085 rectangleY1 - rectangleY0 - rectangleLineWidth)
1086 context.stroke()
1087
1088 rectangleInnerLeft = rectangleX0 + rectangleLineWidth
1089 rectangleInnerRight = rectangleX1 - rectangleLineWidth
1090 self._rectangleInnerTop = rectangleInnerTop = rectangleY0 + rectangleLineWidth
1091 self._rectangleInnerBottom = rectangleInnerBottom = rectangleY1 - rectangleLineWidth
1092
1093 rectangleInnerWidth = rectangleInnerRight - rectangleInnerLeft
1094 rectangleInnerHeight = rectangleInnerBottom - rectangleInnerTop
1095
1096 context.set_source_rgb(1.0, 0.9, 0.6)
1097 currentHeight = self.currentWeight * rectangleInnerHeight / self.capacity
1098 currentX = rectangleInnerTop + rectangleInnerHeight - currentHeight
1099 context.rectangle(xOffset + rectangleInnerLeft,
1100 yOffset + rectangleInnerTop +
1101 rectangleInnerHeight - currentHeight,
1102 rectangleInnerWidth, currentHeight)
1103 context.fill()
1104
1105 expectedHeight = self.expectedWeight * rectangleInnerHeight / self.capacity
1106 expectedY = rectangleInnerTop + rectangleInnerHeight - expectedHeight
1107
1108 context.set_line_width(1.5)
1109 context.set_source_rgb(0.0, 0.85, 0.85)
1110 context.move_to(xOffset + rectangleX0, yOffset + expectedY)
1111 context.line_to(xOffset + rectangleX1, yOffset + expectedY)
1112 context.stroke()
1113
1114 context.set_line_width(0.0)
1115 context.move_to(xOffset + 0, yOffset + expectedY - triangleSize)
1116 context.line_to(xOffset + 0, yOffset + expectedY + triangleSize)
1117 context.line_to(xOffset + rectangleX0 + 1, yOffset + expectedY)
1118 context.line_to(xOffset + 0, yOffset + expectedY - triangleSize)
1119 context.fill()
1120
1121 context.set_line_width(0.0)
1122 context.move_to(xOffset + width, yOffset + expectedY - triangleSize)
1123 context.line_to(xOffset + width, yOffset + expectedY + triangleSize)
1124 context.line_to(xOffset + rectangleX1 - 1, yOffset + expectedY)
1125 context.line_to(xOffset + width, yOffset + expectedY - triangleSize)
1126 context.fill()
1127
1128 return True
1129
1130 def _setExpectedFromY(self, y):
1131 """Set the expected weight from the given Y-coordinate."""
1132 level = (self._rectangleInnerBottom - y) / \
1133 (self._rectangleInnerBottom - self._rectangleInnerTop)
1134 level = min(1.0, max(0.0, level))
1135 self._expectedButton.set_value(level * self.capacity)
1136
1137 def _buttonPressed(self, tankFigure, event):
1138 """Called when a button is pressed in the figure.
1139
1140 The expected level will be set there."""
1141 if event.button==1:
1142 self._setExpectedFromY(event.y)
1143
1144 def _motionNotify(self, tankFigure, event):
1145 """Called when the mouse pointer moves within the area of a tank figure."""
1146 if event.state==BUTTON1_MASK:
1147 self._setExpectedFromY(event.y)
1148
1149 def _scrolled(self, tankFigure, event):
1150 """Called when a scroll event is received."""
1151 increment = 1 if event.state==CONTROL_MASK \
1152 else 100 if event.state==SHIFT_MASK \
1153 else 10 if event.state==0 else 0
1154 if increment!=0:
1155 if event.direction==SCROLL_DOWN:
1156 increment *= -1
1157 self._expectedButton.spin(SPIN_USER_DEFINED, increment)
1158
1159 def _expectedChanged(self, spinButton):
1160 """Called when the expected value has changed."""
1161 self.expectedWeight = spinButton.get_value_as_int()
1162 self._redraw()
1163
1164#-----------------------------------------------------------------------------
1165
1166class FuelPage(Page):
1167 """The page containing the fuel tank filling."""
1168 _pumpStep = 0.02
1169
1170 def __init__(self, wizard):
1171 """Construct the page."""
1172 super(FuelPage, self).__init__(wizard, xstr("fuel_title"),
1173 xstr("fuel_help"),
1174 completedHelp = xstr("fuel_chelp"))
1175
1176 self._fuelTanks = []
1177 self._fuelTable = None
1178 self._fuelAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1179 xscale = 0.0, yscale = 1.0)
1180 self.setMainWidget(self._fuelAlignment)
1181
1182 tanks = acft.MostFuelTankAircraft.fuelTanks
1183 tankData = ((2500, 3900),) * len(tanks)
1184 self._setupTanks(tanks, tankData)
1185
1186 self._backButton = self.addPreviousButton(clicked = self._backClicked)
1187 self._button = self.addNextButton(clicked = self._forwardClicked)
1188
1189 self._pumpIndex = 0
1190
1191 def activate(self):
1192 """Activate the page."""
1193 gui = self._wizard.gui
1194
1195 self._setupTanks(gui.flight.aircraft.fuelTanks,
1196 self._wizard._fuelData)
1197
1198 def finalize(self):
1199 """Finalize the page."""
1200 for fuelTank in self._fuelTanks:
1201 fuelTank.disable()
1202
1203 def _backClicked(self, button):
1204 """Called when the Back button is pressed."""
1205 self.goBack()
1206
1207 def _forwardClicked(self, button):
1208 """Called when the forward button is clicked."""
1209 if not self._completed:
1210 self._pumpIndex = 0
1211 self._wizard.gui.beginBusy(xstr("fuel_pump_busy"))
1212 self._pump()
1213 else:
1214 self._wizard.nextPage()
1215
1216 def _setupTanks(self, tanks, tankData):
1217 """Setup the tanks for the given data."""
1218 numTanks = len(tanks)
1219 if self._fuelTable is not None:
1220 self._fuelAlignment.remove(self._fuelTable)
1221
1222 self._fuelTanks = []
1223 self._fuelTable = gtk.Table(numTanks, 1)
1224 self._fuelTable.set_col_spacings(16)
1225 for i in range(0, numTanks):
1226 tank = tanks[i]
1227 (current, capacity) = tankData[i]
1228
1229 fuelTank = FuelTank(tank,
1230 xstr("fuel_tank_" +
1231 const.fuelTank2string(tank)),
1232 capacity, current)
1233 self._fuelTable.attach(fuelTank, i, i+1, 0, 1)
1234 self._fuelTanks.append(fuelTank)
1235
1236 self._fuelAlignment.add(self._fuelTable)
1237 self.show_all()
1238
1239 def _pump(self):
1240 """Perform one step of pumping.
1241
1242 It is checked, if the current tank's contents are of the right
1243 quantity. If not, it is filled one step further to the desired
1244 contents. Otherwise the next tank is started. If all tanks are are
1245 filled, the next page is selected."""
1246 numTanks = len(self._fuelTanks)
1247
1248 fuelTank = None
1249 while self._pumpIndex < numTanks:
1250 fuelTank = self._fuelTanks[self._pumpIndex]
1251 if fuelTank.isCorrect():
1252 self._pumpIndex += 1
1253 fuelTank = None
1254 else:
1255 break
1256
1257 if fuelTank is None:
1258 self._wizard.gui.endBusy()
1259 self._wizard.nextPage()
1260 else:
1261 currentLevel = fuelTank.currentWeight / fuelTank.capacity
1262 expectedLevel = fuelTank.expectedWeight / fuelTank.capacity
1263 if currentLevel<expectedLevel:
1264 currentLevel += FuelPage._pumpStep
1265 if currentLevel>expectedLevel: currentLevel = expectedLevel
1266 else:
1267 currentLevel -= FuelPage._pumpStep
1268 if currentLevel<expectedLevel: currentLevel = expectedLevel
1269 fuelTank.setCurrent(currentLevel * fuelTank.capacity)
1270 self._wizard.gui.simulator.setFuelLevel([(fuelTank.fuelTank,
1271 currentLevel)])
1272 gobject.timeout_add(50, self._pump)
1273
1274#-----------------------------------------------------------------------------
1275
1276class RoutePage(Page):
1277 """The page containing the route and the flight level."""
1278 def __init__(self, wizard):
1279 """Construct the page."""
1280 super(RoutePage, self).__init__(wizard, xstr("route_title"),
1281 xstr("route_help"),
1282 completedHelp = xstr("route_chelp"))
1283
1284 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1285 xscale = 0.0, yscale = 0.0)
1286
1287 mainBox = gtk.VBox()
1288 alignment.add(mainBox)
1289 self.setMainWidget(alignment)
1290
1291 levelBox = gtk.HBox()
1292
1293 label = gtk.Label(xstr("route_level"))
1294 label.set_use_underline(True)
1295 levelBox.pack_start(label, True, True, 0)
1296
1297 self._cruiseLevel = gtk.SpinButton()
1298 self._cruiseLevel.set_increments(step = 10, page = 100)
1299 self._cruiseLevel.set_range(min = 50, max = 500)
1300 self._cruiseLevel.set_tooltip_text(xstr("route_level_tooltip"))
1301 self._cruiseLevel.set_numeric(True)
1302 self._cruiseLevel.connect("value-changed", self._cruiseLevelChanged)
1303 label.set_mnemonic_widget(self._cruiseLevel)
1304 self._filedCruiseLevel = 240
1305
1306 levelBox.pack_start(self._cruiseLevel, False, False, 8)
1307
1308 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
1309 xscale = 0.0, yscale = 0.0)
1310 alignment.add(levelBox)
1311
1312 mainBox.pack_start(alignment, False, False, 0)
1313
1314
1315 routeBox = gtk.VBox()
1316
1317 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
1318 xscale = 0.0, yscale = 0.0)
1319 label = gtk.Label(xstr("route_route"))
1320 label.set_use_underline(True)
1321 alignment.add(label)
1322 routeBox.pack_start(alignment, True, True, 0)
1323
1324 routeWindow = gtk.ScrolledWindow()
1325 routeWindow.set_size_request(400, 80)
1326 routeWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
1327 else gtk.SHADOW_IN)
1328 routeWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1329 else gtk.POLICY_AUTOMATIC,
1330 gtk.PolicyType.AUTOMATIC if pygobject
1331 else gtk.POLICY_AUTOMATIC)
1332
1333 self._uppercasingRoute = False
1334
1335 self._route = gtk.TextView()
1336 self._route.set_tooltip_text(xstr("route_route_tooltip"))
1337 self._route.set_wrap_mode(WRAP_WORD)
1338 self._route.get_buffer().connect("changed", self._routeChanged)
1339 self._route.get_buffer().connect_after("insert-text", self._routeInserted)
1340 routeWindow.add(self._route)
1341
1342 label.set_mnemonic_widget(self._route)
1343 routeBox.pack_start(routeWindow, True, True, 0)
1344
1345 mainBox.pack_start(routeBox, True, True, 8)
1346
1347 self._backButton = self.addPreviousButton(clicked = self._backClicked)
1348 self._button = self.addNextButton(clicked = self._forwardClicked)
1349
1350 @property
1351 def filedCruiseLevel(self):
1352 """Get the filed cruise level."""
1353 return self._filedCruiseLevel
1354
1355 @property
1356 def cruiseLevel(self):
1357 """Get the cruise level."""
1358 return self._cruiseLevel.get_value_as_int()
1359
1360 @property
1361 def route(self):
1362 """Get the route."""
1363 return self._getRoute()
1364
1365 def activate(self):
1366 """Setup the route from the booked flight."""
1367 self._cruiseLevel.set_value(240)
1368 self._filedCruiseLevel = 240
1369 self._route.get_buffer().set_text(self._wizard._bookedFlight.route)
1370 self._updateForwardButton()
1371
1372 def _getRoute(self):
1373 """Get the text of the route."""
1374 buffer = self._route.get_buffer()
1375 return buffer.get_text(buffer.get_start_iter(),
1376 buffer.get_end_iter(), True)
1377
1378 def _updateForwardButton(self):
1379 """Update the sensitivity of the forward button."""
1380 self._button.set_sensitive(self._cruiseLevel.get_value_as_int()>=50 and \
1381 self._getRoute()!="")
1382
1383 def _cruiseLevelChanged(self, spinButton):
1384 """Called when the cruise level has changed."""
1385 self._updateForwardButton()
1386
1387 def _routeChanged(self, textBuffer):
1388 """Called when the route has changed."""
1389 if not self._uppercasingRoute:
1390 self._updateForwardButton()
1391
1392 def _routeInserted(self, textBuffer, iter, text, length):
1393 """Called when new characters are inserted into the route.
1394
1395 It uppercases all characters."""
1396 if not self._uppercasingRoute:
1397 self._uppercasingRoute = True
1398
1399 iter1 = iter.copy()
1400 iter1.backward_chars(length)
1401 textBuffer.delete(iter, iter1)
1402
1403 textBuffer.insert(iter, text.upper())
1404
1405 self._uppercasingRoute = False
1406
1407 def _backClicked(self, button):
1408 """Called when the Back button is pressed."""
1409 self.goBack()
1410
1411 def _forwardClicked(self, button):
1412 """Called when the Forward button is clicked."""
1413 if self._completed:
1414 self._wizard.nextPage()
1415 else:
1416 bookedFlight = self._wizard._bookedFlight
1417 self._filedCruiseLevel = self.cruiseLevel
1418 self._wizard.gui.beginBusy(xstr("route_down_notams"))
1419 self._wizard.gui.webHandler.getNOTAMs(self._notamsCallback,
1420 bookedFlight.departureICAO,
1421 bookedFlight.arrivalICAO)
1422
1423 def _notamsCallback(self, returned, result):
1424 """Callback for the NOTAMs."""
1425 gobject.idle_add(self._handleNOTAMs, returned, result)
1426
1427 def _handleNOTAMs(self, returned, result):
1428 """Handle the NOTAMs."""
1429 if returned:
1430 self._wizard._departureNOTAMs = result.departureNOTAMs
1431 self._wizard._arrivalNOTAMs = result.arrivalNOTAMs
1432 else:
1433 self._wizard._departureNOTAMs = None
1434 self._wizard._arrivalNOTAMs = None
1435
1436 bookedFlight = self._wizard._bookedFlight
1437 self._wizard.gui.beginBusy(xstr("route_down_metars"))
1438 self._wizard.gui.webHandler.getMETARs(self._metarsCallback,
1439 [bookedFlight.departureICAO,
1440 bookedFlight.arrivalICAO])
1441
1442 def _metarsCallback(self, returned, result):
1443 """Callback for the METARs."""
1444 gobject.idle_add(self._handleMETARs, returned, result)
1445
1446 def _handleMETARs(self, returned, result):
1447 """Handle the METARs."""
1448 self._wizard._departureMETAR = None
1449 self._wizard._arrivalMETAR = None
1450 bookedFlight = self._wizard._bookedFlight
1451 if returned:
1452 if bookedFlight.departureICAO in result.metars:
1453 self._wizard._departureMETAR = result.metars[bookedFlight.departureICAO]
1454 if bookedFlight.arrivalICAO in result.metars:
1455 self._wizard._arrivalMETAR = result.metars[bookedFlight.arrivalICAO]
1456
1457 self._wizard.gui.endBusy()
1458 self._backButton.set_sensitive(True)
1459 self._button.set_sensitive(True)
1460 self._wizard.nextPage()
1461
1462#-----------------------------------------------------------------------------
1463
1464class BriefingPage(Page):
1465 """Page for the briefing."""
1466 def __init__(self, wizard, departure):
1467 """Construct the briefing page."""
1468 self._departure = departure
1469
1470 title = xstr("briefing_title") % (1 if departure else 2,
1471 xstr("briefing_departure")
1472 if departure
1473 else xstr("briefing_arrival"))
1474 super(BriefingPage, self).__init__(wizard, title, xstr("briefing_help"),
1475 completedHelp = xstr("briefing_chelp"))
1476
1477 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1478 xscale = 1.0, yscale = 1.0)
1479
1480 mainBox = gtk.VBox()
1481 alignment.add(mainBox)
1482 self.setMainWidget(alignment)
1483
1484 self._notamsFrame = gtk.Frame()
1485 self._notamsFrame.set_label(xstr("briefing_notams_init"))
1486 scrolledWindow = gtk.ScrolledWindow()
1487 scrolledWindow.set_size_request(-1, 128)
1488 # FIXME: these constants should be in common
1489 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1490 else gtk.POLICY_AUTOMATIC,
1491 gtk.PolicyType.AUTOMATIC if pygobject
1492 else gtk.POLICY_AUTOMATIC)
1493 self._notams = gtk.TextView()
1494 self._notams.set_editable(False)
1495 self._notams.set_accepts_tab(False)
1496 self._notams.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
1497 scrolledWindow.add(self._notams)
1498 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
1499 xscale = 1.0, yscale = 1.0)
1500 alignment.set_padding(padding_top = 4, padding_bottom = 0,
1501 padding_left = 0, padding_right = 0)
1502 alignment.add(scrolledWindow)
1503 self._notamsFrame.add(alignment)
1504 mainBox.pack_start(self._notamsFrame, True, True, 4)
1505
1506 self._metarFrame = gtk.Frame()
1507 self._metarFrame.set_label(xstr("briefing_metar_init"))
1508 scrolledWindow = gtk.ScrolledWindow()
1509 scrolledWindow.set_size_request(-1, 32)
1510 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1511 else gtk.POLICY_AUTOMATIC,
1512 gtk.PolicyType.AUTOMATIC if pygobject
1513 else gtk.POLICY_AUTOMATIC)
1514
1515 self._uppercasingMETAR = False
1516
1517 self._metar = gtk.TextView()
1518 self._metar.set_accepts_tab(False)
1519 self._metar.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
1520 self._metar.get_buffer().connect("changed", self._metarChanged)
1521 self._metar.get_buffer().connect_after("insert-text", self._metarInserted)
1522 scrolledWindow.add(self._metar)
1523 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
1524 xscale = 1.0, yscale = 1.0)
1525 alignment.set_padding(padding_top = 4, padding_bottom = 0,
1526 padding_left = 0, padding_right = 0)
1527 alignment.add(scrolledWindow)
1528 self._metarFrame.add(alignment)
1529 mainBox.pack_start(self._metarFrame, True, True, 4)
1530 self.metarEdited = False
1531
1532 self.addPreviousButton(clicked = self._backClicked)
1533 self._button = self.addNextButton(clicked = self._forwardClicked)
1534
1535 @property
1536 def metar(self):
1537 """Get the METAR on the page."""
1538 buffer = self._metar.get_buffer()
1539 return buffer.get_text(buffer.get_start_iter(),
1540 buffer.get_end_iter(), True)
1541
1542 def setMETAR(self, metar):
1543 """Set the metar."""
1544 self._metar.get_buffer().set_text(metar)
1545 self.metarEdited = False
1546
1547 def activate(self):
1548 """Activate the page."""
1549 if not self._departure:
1550 self._button.set_label(xstr("briefing_button"))
1551 self._button.set_has_tooltip(False)
1552 self._button.set_use_stock(False)
1553
1554 bookedFlight = self._wizard._bookedFlight
1555
1556 icao = bookedFlight.departureICAO if self._departure \
1557 else bookedFlight.arrivalICAO
1558 notams = self._wizard._departureNOTAMs if self._departure \
1559 else self._wizard._arrivalNOTAMs
1560 metar = self._wizard._departureMETAR if self._departure \
1561 else self._wizard._arrivalMETAR
1562
1563 self._notamsFrame.set_label(xstr("briefing_notams_template") % (icao,))
1564 buffer = self._notams.get_buffer()
1565 if notams is None:
1566 buffer.set_text(xstr("briefing_notams_failed"))
1567 elif not notams:
1568 buffer.set_text(xstr("briefing_notams_missing"))
1569 else:
1570 s = ""
1571 for notam in notams:
1572 s += str(notam.begin)
1573 if notam.end is not None:
1574 s += " - " + str(notam.end)
1575 elif notam.permanent:
1576 s += " - PERMANENT"
1577 s += "\n"
1578 if notam.repeatCycle:
1579 s += "Repeat cycle: " + notam.repeatCycle + "\n"
1580 s += notam.notice + "\n"
1581 s += "-------------------- * --------------------\n"
1582 buffer.set_text(s)
1583
1584 self._metarFrame.set_label(xstr("briefing_metar_template") % (icao,))
1585 buffer = self._metar.get_buffer()
1586 if metar is None:
1587 buffer.set_text(xstr("briefing_metar_failed"))
1588 else:
1589 buffer.set_text(metar)
1590
1591 label = self._metarFrame.get_label_widget()
1592 label.set_use_underline(True)
1593 label.set_mnemonic_widget(self._metar)
1594
1595 self.metarEdited = False
1596
1597 def _backClicked(self, button):
1598 """Called when the Back button is pressed."""
1599 self.goBack()
1600
1601 def _forwardClicked(self, button):
1602 """Called when the forward button is clicked."""
1603 if not self._departure:
1604 if not self._completed:
1605 self._wizard.gui.startMonitoring()
1606 self._button.set_label(xstr("button_next"))
1607 self._button.set_tooltip_text(xstr("button_next_tooltip"))
1608 self.complete()
1609
1610 self._wizard.nextPage()
1611
1612 def _metarChanged(self, buffer):
1613 """Called when the METAR has changed."""
1614 if not self._uppercasingMETAR:
1615 self.metarEdited = True
1616 self._button.set_sensitive(buffer.get_text(buffer.get_start_iter(),
1617 buffer.get_end_iter(),
1618 True)!="")
1619
1620 def _metarInserted(self, textBuffer, iter, text, length):
1621 """Called when new characters are inserted into the METAR.
1622
1623 It uppercases all characters."""
1624 if not self._uppercasingMETAR:
1625 self._uppercasingMETAR = True
1626
1627 iter1 = iter.copy()
1628 iter1.backward_chars(length)
1629 textBuffer.delete(iter, iter1)
1630
1631 textBuffer.insert(iter, text.upper())
1632
1633 self._uppercasingMETAR = False
1634
1635#-----------------------------------------------------------------------------
1636
1637class TakeoffPage(Page):
1638 """Page for entering the takeoff data."""
1639 def __init__(self, wizard):
1640 """Construct the takeoff page."""
1641 super(TakeoffPage, self).__init__(wizard, xstr("takeoff_title"),
1642 xstr("takeoff_help"),
1643 completedHelp = xstr("takeoff_chelp"))
1644
1645 self._forwardAllowed = False
1646
1647 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1648 xscale = 0.0, yscale = 0.0)
1649
1650 table = gtk.Table(5, 4)
1651 table.set_row_spacings(4)
1652 table.set_col_spacings(16)
1653 table.set_homogeneous(False)
1654 alignment.add(table)
1655 self.setMainWidget(alignment)
1656
1657 label = gtk.Label(xstr("takeoff_runway"))
1658 label.set_use_underline(True)
1659 label.set_alignment(0.0, 0.5)
1660 table.attach(label, 0, 1, 0, 1)
1661
1662 self._runway = gtk.Entry()
1663 self._runway.set_width_chars(10)
1664 self._runway.set_tooltip_text(xstr("takeoff_runway_tooltip"))
1665 self._runway.connect("changed", self._upperChanged)
1666 table.attach(self._runway, 1, 3, 0, 1)
1667 label.set_mnemonic_widget(self._runway)
1668
1669 label = gtk.Label(xstr("takeoff_sid"))
1670 label.set_use_underline(True)
1671 label.set_alignment(0.0, 0.5)
1672 table.attach(label, 0, 1, 1, 2)
1673
1674 self._sid = gtk.Entry()
1675 self._sid.set_width_chars(10)
1676 self._sid.set_tooltip_text(xstr("takeoff_sid_tooltip"))
1677 self._sid.connect("changed", self._upperChanged)
1678 table.attach(self._sid, 1, 3, 1, 2)
1679 label.set_mnemonic_widget(self._sid)
1680
1681 label = gtk.Label(xstr("takeoff_v1"))
1682 label.set_use_markup(True)
1683 label.set_use_underline(True)
1684 label.set_alignment(0.0, 0.5)
1685 table.attach(label, 0, 1, 2, 3)
1686
1687 self._v1 = IntegerEntry()
1688 self._v1.set_width_chars(4)
1689 self._v1.set_tooltip_markup(xstr("takeoff_v1_tooltip"))
1690 self._v1.connect("integer-changed", self._valueChanged)
1691 table.attach(self._v1, 2, 3, 2, 3)
1692 label.set_mnemonic_widget(self._v1)
1693
1694 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 2, 3)
1695
1696 label = gtk.Label(xstr("takeoff_vr"))
1697 label.set_use_markup(True)
1698 label.set_use_underline(True)
1699 label.set_alignment(0.0, 0.5)
1700 table.attach(label, 0, 1, 3, 4)
1701
1702 self._vr = IntegerEntry()
1703 self._vr.set_width_chars(4)
1704 self._vr.set_tooltip_markup(xstr("takeoff_vr_tooltip"))
1705 self._vr.connect("integer-changed", self._valueChanged)
1706 table.attach(self._vr, 2, 3, 3, 4)
1707 label.set_mnemonic_widget(self._vr)
1708
1709 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 3, 4)
1710
1711 label = gtk.Label(xstr("takeoff_v2"))
1712 label.set_use_markup(True)
1713 label.set_use_underline(True)
1714 label.set_alignment(0.0, 0.5)
1715 table.attach(label, 0, 1, 4, 5)
1716
1717 self._v2 = IntegerEntry()
1718 self._v2.set_width_chars(4)
1719 self._v2.set_tooltip_markup(xstr("takeoff_v2_tooltip"))
1720 self._v2.connect("integer-changed", self._valueChanged)
1721 table.attach(self._v2, 2, 3, 4, 5)
1722 label.set_mnemonic_widget(self._v2)
1723
1724 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 4, 5)
1725
1726 self.addPreviousButton(clicked = self._backClicked)
1727
1728 self._button = self.addNextButton(clicked = self._forwardClicked)
1729
1730 @property
1731 def runway(self):
1732 """Get the runway."""
1733 return self._runway.get_text()
1734
1735 @property
1736 def sid(self):
1737 """Get the SID."""
1738 return self._sid.get_text()
1739
1740 @property
1741 def v1(self):
1742 """Get the v1 speed."""
1743 return self._v1.get_int()
1744
1745 @property
1746 def vr(self):
1747 """Get the vr speed."""
1748 return self._vr.get_int()
1749
1750 @property
1751 def v2(self):
1752 """Get the v2 speed."""
1753 return self._v2.get_int()
1754
1755 def activate(self):
1756 """Activate the page."""
1757 self._runway.set_text("")
1758 self._runway.set_sensitive(True)
1759 self._sid.set_text("")
1760 self._sid.set_sensitive(True)
1761 self._v1.set_int(None)
1762 self._v1.set_sensitive(True)
1763 self._vr.set_int(None)
1764 self._vr.set_sensitive(True)
1765 self._v2.set_int(None)
1766 self._v2.set_sensitive(True)
1767 self._button.set_sensitive(False)
1768
1769 def finalize(self):
1770 """Finalize the page."""
1771 self._runway.set_sensitive(False)
1772 self._sid.set_sensitive(False)
1773 self._v1.set_sensitive(False)
1774 self._vr.set_sensitive(False)
1775 self._v2.set_sensitive(False)
1776 self._wizard.gui.flight.aircraft.updateV1R2()
1777
1778 def allowForward(self):
1779 """Allow going to the next page."""
1780 self._forwardAllowed = True
1781 self._updateForwardButton()
1782
1783 def _updateForwardButton(self):
1784 """Update the sensitivity of the forward button based on some conditions."""
1785 sensitive = self._forwardAllowed and \
1786 self._runway.get_text()!="" and \
1787 self._sid.get_text()!="" and \
1788 self.v1 is not None and \
1789 self.vr is not None and \
1790 self.v2 is not None and \
1791 self.v1 <= self.vr and \
1792 self.vr <= self.v2
1793 self._button.set_sensitive(sensitive)
1794
1795 def _valueChanged(self, widget, arg = None):
1796 """Called when the value of some widget has changed."""
1797 self._updateForwardButton()
1798
1799 def _upperChanged(self, entry, arg = None):
1800 """Called when the value of some entry widget has changed and the value
1801 should be converted to uppercase."""
1802 entry.set_text(entry.get_text().upper())
1803 self._valueChanged(entry, arg)
1804
1805 def _backClicked(self, button):
1806 """Called when the Back button is pressed."""
1807 self.goBack()
1808
1809 def _forwardClicked(self, button):
1810 """Called when the forward button is clicked."""
1811 self._wizard.nextPage()
1812
1813#-----------------------------------------------------------------------------
1814
1815class LandingPage(Page):
1816 """Page for entering landing data."""
1817 def __init__(self, wizard):
1818 """Construct the landing page."""
1819 super(LandingPage, self).__init__(wizard, xstr("landing_title"),
1820 xstr("landing_help"),
1821 completedHelp = xstr("landing_chelp"))
1822
1823 self._flightEnded = False
1824
1825 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1826 xscale = 0.0, yscale = 0.0)
1827
1828 table = gtk.Table(5, 5)
1829 table.set_row_spacings(4)
1830 table.set_col_spacings(16)
1831 table.set_homogeneous(False)
1832 alignment.add(table)
1833 self.setMainWidget(alignment)
1834
1835 self._starButton = gtk.CheckButton()
1836 self._starButton.connect("clicked", self._starButtonClicked)
1837 table.attach(self._starButton, 0, 1, 0, 1)
1838
1839 label = gtk.Label(xstr("landing_star"))
1840 label.set_use_underline(True)
1841 label.set_alignment(0.0, 0.5)
1842 table.attach(label, 1, 2, 0, 1)
1843
1844 self._star = gtk.Entry()
1845 self._star.set_width_chars(10)
1846 self._star.set_tooltip_text(xstr("landing_star_tooltip"))
1847 self._star.connect("changed", self._upperChanged)
1848 self._star.set_sensitive(False)
1849 table.attach(self._star, 2, 4, 0, 1)
1850 label.set_mnemonic_widget(self._starButton)
1851
1852 self._transitionButton = gtk.CheckButton()
1853 self._transitionButton.connect("clicked", self._transitionButtonClicked)
1854 table.attach(self._transitionButton, 0, 1, 1, 2)
1855
1856 label = gtk.Label(xstr("landing_transition"))
1857 label.set_use_underline(True)
1858 label.set_alignment(0.0, 0.5)
1859 table.attach(label, 1, 2, 1, 2)
1860
1861 self._transition = gtk.Entry()
1862 self._transition.set_width_chars(10)
1863 self._transition.set_tooltip_text(xstr("landing_transition_tooltip"))
1864 self._transition.connect("changed", self._upperChanged)
1865 self._transition.set_sensitive(False)
1866 table.attach(self._transition, 2, 4, 1, 2)
1867 label.set_mnemonic_widget(self._transitionButton)
1868
1869 label = gtk.Label(xstr("landing_runway"))
1870 label.set_use_underline(True)
1871 label.set_alignment(0.0, 0.5)
1872 table.attach(label, 1, 2, 2, 3)
1873
1874 self._runway = gtk.Entry()
1875 self._runway.set_width_chars(10)
1876 self._runway.set_tooltip_text(xstr("landing_runway_tooltip"))
1877 self._runway.connect("changed", self._upperChanged)
1878 table.attach(self._runway, 2, 4, 2, 3)
1879 label.set_mnemonic_widget(self._runway)
1880
1881 label = gtk.Label(xstr("landing_approach"))
1882 label.set_use_underline(True)
1883 label.set_alignment(0.0, 0.5)
1884 table.attach(label, 1, 2, 3, 4)
1885
1886 self._approachType = gtk.Entry()
1887 self._approachType.set_width_chars(10)
1888 self._approachType.set_tooltip_text(xstr("landing_approach_tooltip"))
1889 self._approachType.connect("changed", self._upperChanged)
1890 table.attach(self._approachType, 2, 4, 3, 4)
1891 label.set_mnemonic_widget(self._approachType)
1892
1893 label = gtk.Label(xstr("landing_vref"))
1894 label.set_use_markup(True)
1895 label.set_use_underline(True)
1896 label.set_alignment(0.0, 0.5)
1897 table.attach(label, 1, 2, 5, 6)
1898
1899 self._vref = IntegerEntry()
1900 self._vref.set_width_chars(5)
1901 self._vref.set_tooltip_markup(xstr("landing_vref_tooltip"))
1902 self._vref.connect("integer-changed", self._vrefChanged)
1903 table.attach(self._vref, 3, 4, 5, 6)
1904 label.set_mnemonic_widget(self._vref)
1905
1906 table.attach(gtk.Label(xstr("label_knots")), 4, 5, 5, 6)
1907
1908 self.addPreviousButton(clicked = self._backClicked)
1909
1910 self._button = self.addNextButton(clicked = self._forwardClicked)
1911
1912 # These are needed for correct size calculations
1913 self._starButton.set_active(True)
1914 self._transitionButton.set_active(True)
1915
1916 @property
1917 def star(self):
1918 """Get the STAR or None if none entered."""
1919 return self._star.get_text() if self._starButton.get_active() else None
1920
1921 @property
1922 def transition(self):
1923 """Get the transition or None if none entered."""
1924 return self._transition.get_text() \
1925 if self._transitionButton.get_active() else None
1926
1927 @property
1928 def approachType(self):
1929 """Get the approach type."""
1930 return self._approachType.get_text()
1931
1932 @property
1933 def runway(self):
1934 """Get the runway."""
1935 return self._runway.get_text()
1936
1937 @property
1938 def vref(self):
1939 """Return the landing reference speed."""
1940 return self._vref.get_int()
1941
1942 def activate(self):
1943 """Called when the page is activated."""
1944 self._starButton.set_sensitive(True)
1945 self._starButton.set_active(False)
1946 self._star.set_text("")
1947
1948 self._transitionButton.set_sensitive(True)
1949 self._transitionButton.set_active(False)
1950 self._transition.set_text("")
1951
1952 self._runway.set_text("")
1953 self._runway.set_sensitive(True)
1954
1955 self._approachType.set_text("")
1956 self._approachType.set_sensitive(True)
1957
1958 self._vref.set_int(None)
1959 self._vref.set_sensitive(True)
1960
1961 self._updateForwardButton()
1962
1963 def flightEnded(self):
1964 """Called when the flight has ended."""
1965 self._flightEnded = True
1966 self._updateForwardButton()
1967
1968 def finalize(self):
1969 """Finalize the page."""
1970 self._starButton.set_sensitive(False)
1971 self._star.set_sensitive(False)
1972
1973 self._transitionButton.set_sensitive(False)
1974 self._transition.set_sensitive(False)
1975
1976 self._runway.set_sensitive(False)
1977
1978 self._approachType.set_sensitive(False)
1979
1980 self._vref.set_sensitive(False)
1981 self._wizard.gui.flight.aircraft.updateVRef()
1982 # FIXME: Perhaps a separate initialize() call which would set up
1983 # defaults? -> use reset()
1984 self._flightEnded = False
1985
1986 def _starButtonClicked(self, button):
1987 """Called when the STAR button is clicked."""
1988 active = button.get_active()
1989 self._star.set_sensitive(active)
1990 if active:
1991 self._star.grab_focus()
1992 self._updateForwardButton()
1993
1994 def _transitionButtonClicked(self, button):
1995 """Called when the Transition button is clicked."""
1996 active = button.get_active()
1997 self._transition.set_sensitive(active)
1998 if active:
1999 self._transition.grab_focus()
2000 self._updateForwardButton()
2001
2002 def _updateForwardButton(self):
2003 """Update the sensitivity of the forward button."""
2004 sensitive = self._flightEnded and \
2005 (self._starButton.get_active() or \
2006 self._transitionButton.get_active()) and \
2007 (self._star.get_text()!="" or
2008 not self._starButton.get_active()) and \
2009 (self._transition.get_text()!="" or
2010 not self._transitionButton.get_active()) and \
2011 self._runway.get_text()!="" and \
2012 self._approachType.get_text()!="" and \
2013 self.vref is not None
2014 self._button.set_sensitive(sensitive)
2015
2016 def _upperChanged(self, entry):
2017 """Called for entry widgets that must be converted to uppercase."""
2018 entry.set_text(entry.get_text().upper())
2019 self._updateForwardButton()
2020
2021 def _vrefChanged(self, widget, value):
2022 """Called when the Vref has changed."""
2023 self._updateForwardButton()
2024
2025 def _backClicked(self, button):
2026 """Called when the Back button is pressed."""
2027 self.goBack()
2028
2029 def _forwardClicked(self, button):
2030 """Called when the forward button is clicked."""
2031 if self._wizard.gui.config.onlineGateSystem and \
2032 not self._completed and \
2033 self._wizard.bookedFlight.arrivalICAO=="LHBP":
2034 self._wizard.getFleet(callback = self._fleetRetrieved,
2035 force = True)
2036 else:
2037 self._wizard.nextPage()
2038
2039 def _fleetRetrieved(self, fleet):
2040 """Callback for the fleet retrieval."""
2041 self._wizard.nextPage()
2042
2043#-----------------------------------------------------------------------------
2044
2045class FinishPage(Page):
2046 """Flight finish page."""
2047 _flightTypes = [ ("flighttype_scheduled", const.FLIGHTTYPE_SCHEDULED),
2048 ("flighttype_ot", const.FLIGHTTYPE_OLDTIMER),
2049 ("flighttype_vip", const.FLIGHTTYPE_VIP),
2050 ("flighttype_charter", const.FLIGHTTYPE_CHARTER) ]
2051
2052 def __init__(self, wizard):
2053 """Construct the finish page."""
2054 super(FinishPage, self).__init__(wizard, xstr("finish_title"),
2055 xstr("finish_help"))
2056
2057 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
2058 xscale = 0.0, yscale = 0.0)
2059
2060 table = gtk.Table(8, 2)
2061 table.set_row_spacings(4)
2062 table.set_col_spacings(16)
2063 table.set_homogeneous(False)
2064 alignment.add(table)
2065 self.setMainWidget(alignment)
2066
2067 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2068 label = gtk.Label(xstr("finish_rating"))
2069 labelAlignment.add(label)
2070 table.attach(labelAlignment, 0, 1, 0, 1)
2071
2072 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2073 self._flightRating = gtk.Label()
2074 self._flightRating.set_width_chars(7)
2075 self._flightRating.set_alignment(0.0, 0.5)
2076 self._flightRating.set_use_markup(True)
2077 labelAlignment.add(self._flightRating)
2078 table.attach(labelAlignment, 1, 2, 0, 1)
2079
2080 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2081 label = gtk.Label(xstr("finish_flight_time"))
2082 labelAlignment.add(label)
2083 table.attach(labelAlignment, 0, 1, 1, 2)
2084
2085 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2086 self._flightTime = gtk.Label()
2087 self._flightTime.set_width_chars(10)
2088 self._flightTime.set_alignment(0.0, 0.5)
2089 self._flightTime.set_use_markup(True)
2090 labelAlignment.add(self._flightTime)
2091 table.attach(labelAlignment, 1, 2, 1, 2)
2092
2093 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2094 label = gtk.Label(xstr("finish_block_time"))
2095 labelAlignment.add(label)
2096 table.attach(labelAlignment, 0, 1, 2, 3)
2097
2098 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2099 self._blockTime = gtk.Label()
2100 self._blockTime.set_width_chars(10)
2101 self._blockTime.set_alignment(0.0, 0.5)
2102 self._blockTime.set_use_markup(True)
2103 labelAlignment.add(self._blockTime)
2104 table.attach(labelAlignment, 1, 2, 2, 3)
2105
2106 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2107 label = gtk.Label(xstr("finish_distance"))
2108 labelAlignment.add(label)
2109 table.attach(labelAlignment, 0, 1, 3, 4)
2110
2111 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2112 self._distanceFlown = gtk.Label()
2113 self._distanceFlown.set_width_chars(10)
2114 self._distanceFlown.set_alignment(0.0, 0.5)
2115 self._distanceFlown.set_use_markup(True)
2116 labelAlignment.add(self._distanceFlown)
2117 table.attach(labelAlignment, 1, 2, 3, 4)
2118
2119 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
2120 label = gtk.Label(xstr("finish_fuel"))
2121 labelAlignment.add(label)
2122 table.attach(labelAlignment, 0, 1, 4, 5)
2123
2124 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2125 self._fuelUsed = gtk.Label()
2126 self._fuelUsed.set_width_chars(10)
2127 self._fuelUsed.set_alignment(0.0, 0.5)
2128 self._fuelUsed.set_use_markup(True)
2129 labelAlignment.add(self._fuelUsed)
2130 table.attach(labelAlignment, 1, 2, 4, 5)
2131
2132 labelAlignment = gtk.Alignment(xalign = 1.0, xscale = 0.0,
2133 yalign = 0.5, yscale = 0.0)
2134 label = gtk.Label(xstr("finish_type"))
2135 label.set_use_underline(True)
2136 labelAlignment.add(label)
2137 table.attach(labelAlignment, 0, 1, 5, 6)
2138
2139 flightTypeModel = gtk.ListStore(str, int)
2140 for (name, type) in FinishPage._flightTypes:
2141 flightTypeModel.append([xstr(name), type])
2142
2143 self._flightType = gtk.ComboBox(model = flightTypeModel)
2144 renderer = gtk.CellRendererText()
2145 self._flightType.pack_start(renderer, True)
2146 self._flightType.add_attribute(renderer, "text", 0)
2147 self._flightType.set_tooltip_text(xstr("finish_type_tooltip"))
2148 self._flightType.set_active(0)
2149 self._flightType.connect("changed", self._flightTypeChanged)
2150 flightTypeAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2151 flightTypeAlignment.add(self._flightType)
2152 table.attach(flightTypeAlignment, 1, 2, 5, 6)
2153 label.set_mnemonic_widget(self._flightType)
2154
2155 self._onlineFlight = gtk.CheckButton(xstr("finish_online"))
2156 self._onlineFlight.set_use_underline(True)
2157 self._onlineFlight.set_tooltip_text(xstr("finish_online_tooltip"))
2158 onlineFlightAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
2159 onlineFlightAlignment.add(self._onlineFlight)
2160 table.attach(onlineFlightAlignment, 1, 2, 6, 7)
2161
2162 labelAlignment = gtk.Alignment(xalign = 1.0, xscale = 0.0,
2163 yalign = 0.5, yscale = 0.0)
2164 self._gateLabel = gtk.Label(xstr("finish_gate"))
2165 self._gateLabel.set_use_underline(True)
2166 labelAlignment.add(self._gateLabel)
2167 table.attach(labelAlignment, 0, 1, 7, 8)
2168
2169 self._gatesModel = gtk.ListStore(str)
2170
2171 self._gate = gtk.ComboBox(model = self._gatesModel)
2172 renderer = gtk.CellRendererText()
2173 self._gate.pack_start(renderer, True)
2174 self._gate.add_attribute(renderer, "text", 0)
2175 self._gate.set_tooltip_text(xstr("finish_gate_tooltip"))
2176 self._gate.connect("changed", self._gateChanged)
2177 gateAlignment = gtk.Alignment(xalign=0.0, xscale=1.0)
2178 gateAlignment.add(self._gate)
2179 table.attach(gateAlignment, 1, 2, 7, 8)
2180 self._gateLabel.set_mnemonic_widget(self._gate)
2181
2182 self.addPreviousButton(clicked = self._backClicked)
2183
2184 self._saveButton = self.addButton(xstr("finish_save"),
2185 sensitive = False,
2186 tooltip = xstr("finish_send_tooltip"))
2187
2188 self._sendButton = self.addButton(xstr("finish_send"), default = True,
2189 sensitive = False,
2190 clicked = self._sendClicked,
2191 tooltip = xstr("finish_send_tooltip"))
2192
2193 @property
2194 def flightType(self):
2195 """Get the flight type."""
2196 index = self._flightType.get_active()
2197 return None if index<0 else self._flightType.get_model()[index][1]
2198
2199 @property
2200 def online(self):
2201 """Get whether the flight was an online flight or not."""
2202 return self._onlineFlight.get_active()
2203
2204 def activate(self):
2205 """Activate the page."""
2206 flight = self._wizard.gui._flight
2207 rating = flight.logger.getRating()
2208 if rating<0:
2209 self._flightRating.set_markup('<b><span foreground="red">NO GO</span></b>')
2210 else:
2211 self._flightRating.set_markup("<b>%.1f %%</b>" % (rating,))
2212
2213 flightLength = flight.flightTimeEnd - flight.flightTimeStart
2214 self._flightTime.set_markup("<b>%s</b>" % \
2215 (util.getTimeIntervalString(flightLength),))
2216
2217 blockLength = flight.blockTimeEnd - flight.blockTimeStart
2218 self._blockTime.set_markup("<b>%s</b>" % \
2219 (util.getTimeIntervalString(blockLength),))
2220
2221 self._distanceFlown.set_markup("<b>%.2f NM</b>" % \
2222 (flight.flownDistance,))
2223
2224 self._fuelUsed.set_markup("<b>%.0f kg</b>" % \
2225 (flight.startFuel - flight.endFuel,))
2226
2227 self._flightType.set_active(-1)
2228 self._onlineFlight.set_active(True)
2229
2230 self._gatesModel.clear()
2231 if self._wizard.gui.config.onlineGateSystem and \
2232 self._wizard.bookedFlight.arrivalICAO=="LHBP":
2233 occupiedGates = self._wizard._fleet.getOccupiedGateNumbers()
2234 for gateNumber in const.lhbpGateNumbers:
2235 if gateNumber not in occupiedGates:
2236 self._gatesModel.append([gateNumber])
2237 self._gateLabel.set_sensitive(True)
2238 self._gate.set_sensitive(True)
2239 self._gate.set_active(-1)
2240 else:
2241 self._gateLabel.set_sensitive(False)
2242 self._gate.set_sensitive(False)
2243
2244 def _backClicked(self, button):
2245 """Called when the Back button is pressed."""
2246 self.goBack()
2247
2248 def _updateButtons(self):
2249 """Update the sensitivity state of the buttons."""
2250 sensitive = self._flightType.get_active()>=0 and \
2251 (self._gatesModel.get_iter_first() is None or
2252 self._gate.get_active()>=0)
2253
2254 #self._saveButton.set_sensitive(sensitive)
2255 self._sendButton.set_sensitive(sensitive)
2256
2257 def _flightTypeChanged(self, comboBox):
2258 """Called when the flight type has changed."""
2259 self._updateButtons()
2260
2261 def _gateChanged(self, comboBox):
2262 """Called when the arrival gate has changed."""
2263 self._updateButtons()
2264
2265 def _sendClicked(self, button):
2266 """Called when the Send button is clicked."""
2267 pirep = PIREP(self._wizard.gui)
2268 gui = self._wizard.gui
2269 gui.beginBusy(xstr("finish_send_busy"))
2270 gui.webHandler.sendPIREP(self._pirepSentCallback, pirep)
2271
2272 def _pirepSentCallback(self, returned, result):
2273 """Callback for the PIREP sending result."""
2274 gobject.idle_add(self._handlePIREPSent, returned, result)
2275
2276 def _handlePIREPSent(self, returned, result):
2277 """Callback for the PIREP sending result."""
2278 self._wizard.gui.endBusy()
2279 secondaryMarkup = None
2280 type = MESSAGETYPE_ERROR
2281 if returned:
2282 if result.success:
2283 type = MESSAGETYPE_INFO
2284 messageFormat = xstr("finish_send_success")
2285 secondaryMarkup = xstr("finish_send_success_sec")
2286 elif result.alreadyFlown:
2287 messageFormat = xstr("finish_send_already")
2288 secondaryMarkup = xstr("finish_send_already_sec")
2289 elif result.notAvailable:
2290 messageFormat = xstr("finish_send_notavail")
2291 else:
2292 messageFormat = xstr("finish_send_unknown")
2293 secondaryMarkup = xstr("finish_send_unknown_sec")
2294 else:
2295 print "PIREP sending failed", result
2296 messageFormat = xstr("finish_send_failed")
2297 secondaryMarkup = xstr("finish_send_failed_sec")
2298
2299 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
2300 type = type, message_format = messageFormat)
2301 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
2302 dialog.set_title(WINDOW_TITLE_BASE)
2303 if secondaryMarkup is not None:
2304 dialog.format_secondary_markup(secondaryMarkup)
2305
2306 dialog.run()
2307 dialog.hide()
2308
2309 if self._wizard.gui.config.onlineGateSystem and returned and result.success:
2310 bookedFlight = self._wizard.bookedFlight
2311 if bookedFlight.arrivalICAO=="LHBP":
2312 iter = self._gate.get_active_iter()
2313 gateNumber = None if iter is None \
2314 else self._gatesModel.get_value(iter, 0)
2315
2316 status = const.PLANE_PARKING if gateNumber is None \
2317 else const.PLANE_HOME
2318 else:
2319 gateNumber = None
2320 status = const.PLANE_AWAY
2321
2322 self._wizard.updatePlane(self._planeUpdated,
2323 bookedFlight.tailNumber,
2324 status, gateNumber = gateNumber)
2325
2326 def _planeUpdated(self, success):
2327 """Callback for the plane updating."""
2328 pass
2329
2330#-----------------------------------------------------------------------------
2331
2332class Wizard(gtk.VBox):
2333 """The flight wizard."""
2334 def __init__(self, gui):
2335 """Construct the wizard."""
2336 super(Wizard, self).__init__()
2337
2338 self.gui = gui
2339
2340 self._pages = []
2341 self._currentPage = None
2342
2343 self._pages.append(LoginPage(self))
2344 self._pages.append(FlightSelectionPage(self))
2345 self._pages.append(GateSelectionPage(self))
2346 self._pages.append(ConnectPage(self))
2347 self._payloadPage = PayloadPage(self)
2348 self._pages.append(self._payloadPage)
2349 self._payloadIndex = len(self._pages)
2350 self._pages.append(TimePage(self))
2351 self._pages.append(FuelPage(self))
2352 self._routePage = RoutePage(self)
2353 self._pages.append(self._routePage)
2354 self._departureBriefingPage = BriefingPage(self, True)
2355 self._pages.append(self._departureBriefingPage)
2356 self._arrivalBriefingPage = BriefingPage(self, False)
2357 self._pages.append(self._arrivalBriefingPage)
2358 self._arrivalBriefingIndex = len(self._pages)
2359 self._takeoffPage = TakeoffPage(self)
2360 self._pages.append(self._takeoffPage)
2361 self._landingPage = LandingPage(self)
2362 self._pages.append(self._landingPage)
2363 self._finishPage = FinishPage(self)
2364 self._pages.append(self._finishPage)
2365
2366 maxWidth = 0
2367 maxHeight = 0
2368 for page in self._pages:
2369 page.show_all()
2370 pageSizeRequest = page.size_request()
2371 width = pageSizeRequest.width if pygobject else pageSizeRequest[0]
2372 height = pageSizeRequest.height if pygobject else pageSizeRequest[1]
2373 maxWidth = max(maxWidth, width)
2374 maxHeight = max(maxHeight, height)
2375 maxWidth += 16
2376 maxHeight += 32
2377 self.set_size_request(maxWidth, maxHeight)
2378
2379 self._initialize()
2380
2381 @property
2382 def loginResult(self):
2383 """Get the login result."""
2384 return self._loginResult
2385
2386 def setCurrentPage(self, index, finalize = False):
2387 """Set the current page to the one with the given index."""
2388 assert index < len(self._pages)
2389
2390 fromPage = self._currentPage
2391 if fromPage is not None:
2392 page = self._pages[fromPage]
2393 if finalize and not page._completed:
2394 page.complete()
2395 self.remove(page)
2396
2397 self._currentPage = index
2398 page = self._pages[index]
2399 self.add(page)
2400 if page._fromPage is None:
2401 page._fromPage = fromPage
2402 page.initialize()
2403 self.show_all()
2404 if fromPage is not None:
2405 self.grabDefault()
2406
2407 @property
2408 def bookedFlight(self):
2409 """Get the booked flight selected."""
2410 return self._bookedFlight
2411
2412 @property
2413 def cargoWeight(self):
2414 """Get the calculated ZFW value."""
2415 return self._payloadPage.cargoWeight
2416
2417 @property
2418 def zfw(self):
2419 """Get the calculated ZFW value."""
2420 return 0 if self._bookedFlight is None \
2421 else self._payloadPage.calculateZFW()
2422
2423 @property
2424 def filedCruiseAltitude(self):
2425 """Get the filed cruise altitude."""
2426 return self._routePage.filedCruiseLevel * 100
2427
2428 @property
2429 def cruiseAltitude(self):
2430 """Get the cruise altitude."""
2431 return self._routePage.cruiseLevel * 100
2432
2433 @property
2434 def route(self):
2435 """Get the route."""
2436 return self._routePage.route
2437
2438 @property
2439 def departureMETAR(self):
2440 """Get the METAR of the departure airport."""
2441 return self._departureBriefingPage.metar
2442
2443 @property
2444 def arrivalMETAR(self):
2445 """Get the METAR of the arrival airport."""
2446 return self._arrivalBriefingPage.metar
2447
2448 @property
2449 def departureRunway(self):
2450 """Get the departure runway."""
2451 return self._takeoffPage.runway
2452
2453 @property
2454 def sid(self):
2455 """Get the SID."""
2456 return self._takeoffPage.sid
2457
2458 @property
2459 def v1(self):
2460 """Get the V1 speed."""
2461 return self._takeoffPage.v1
2462
2463 @property
2464 def vr(self):
2465 """Get the Vr speed."""
2466 return self._takeoffPage.vr
2467
2468 @property
2469 def v2(self):
2470 """Get the V2 speed."""
2471 return self._takeoffPage.v2
2472
2473 @property
2474 def arrivalRunway(self):
2475 """Get the arrival runway."""
2476 return self._landingPage.runway
2477
2478 @property
2479 def star(self):
2480 """Get the STAR."""
2481 return self._landingPage.star
2482
2483 @property
2484 def transition(self):
2485 """Get the transition."""
2486 return self._landingPage.transition
2487
2488 @property
2489 def approachType(self):
2490 """Get the approach type."""
2491 return self._landingPage.approachType
2492
2493 @property
2494 def vref(self):
2495 """Get the Vref speed."""
2496 return self._landingPage.vref
2497
2498 @property
2499 def flightType(self):
2500 """Get the flight type."""
2501 return self._finishPage.flightType
2502
2503 @property
2504 def online(self):
2505 """Get whether the flight was online or not."""
2506 return self._finishPage.online
2507
2508 def nextPage(self, finalize = True):
2509 """Go to the next page."""
2510 self.jumpPage(1, finalize)
2511
2512 def jumpPage(self, count, finalize = True):
2513 """Go to the page which is 'count' pages after the current one."""
2514 self.setCurrentPage(self._currentPage + count, finalize = finalize)
2515
2516 def grabDefault(self):
2517 """Make the default button of the current page the default."""
2518 self._pages[self._currentPage].grabDefault()
2519
2520 def connected(self, fsType, descriptor):
2521 """Called when the connection could be made to the simulator."""
2522 self.nextPage()
2523
2524 def reset(self):
2525 """Resets the wizard to go back to the login page."""
2526 self._initialize()
2527
2528 def setStage(self, stage):
2529 """Set the flight stage to the given one."""
2530 if stage==const.STAGE_TAKEOFF:
2531 self._takeoffPage.allowForward()
2532 elif stage==const.STAGE_LANDING:
2533 if not self._arrivalBriefingPage.metarEdited:
2534 print "Downloading arrival METAR again"
2535 self.gui.webHandler.getMETARs(self._arrivalMETARCallback,
2536 [self._bookedFlight.arrivalICAO])
2537
2538 elif stage==const.STAGE_END:
2539 self._landingPage.flightEnded()
2540
2541 def _initialize(self):
2542 """Initialize the wizard."""
2543 self._fleet = None
2544 self._fleetCallback = None
2545
2546 self._loginResult = None
2547 self._bookedFlight = None
2548 self._departureGate = "-"
2549 self._fuelData = None
2550 self._departureNOTAMs = None
2551 self._departureMETAR = None
2552 self._arrivalNOTAMs = None
2553 self._arrivalMETAR = None
2554
2555 for page in self._pages:
2556 page.reset()
2557
2558 self.setCurrentPage(0)
2559
2560 def getFleet(self, callback, force = False):
2561 """Get the fleet via the GUI and call the given callback."""
2562 self._fleetCallback = callback
2563 self.gui.getFleet(callback = self._fleetRetrieved, force = force)
2564
2565 def _fleetRetrieved(self, fleet):
2566 """Callback for the fleet retrieval."""
2567 self._fleet = fleet
2568 if self._fleetCallback is not None:
2569 self._fleetCallback(fleet)
2570 self._fleetCallback = None
2571
2572 def updatePlane(self, callback, tailNumber, status, gateNumber = None):
2573 """Update the given plane's gate information."""
2574 self.gui.updatePlane(tailNumber, status, gateNumber = gateNumber,
2575 callback = callback)
2576
2577 def _connectSimulator(self):
2578 """Connect to the simulator."""
2579 self.gui.connectSimulator(self._bookedFlight.aircraftType)
2580
2581 def _arrivalMETARCallback(self, returned, result):
2582 """Called when the METAR of the arrival airport is retrieved."""
2583 gobject.idle_add(self._handleArrivalMETAR, returned, result)
2584
2585 def _handleArrivalMETAR(self, returned, result):
2586 """Called when the METAR of the arrival airport is retrieved."""
2587 icao = self._bookedFlight.arrivalICAO
2588 if returned and icao in result.metars:
2589 metar = result.metars[icao]
2590 if metar!="":
2591 self._arrivalBriefingPage.setMETAR(metar)
2592
2593#-----------------------------------------------------------------------------
2594
Note: See TracBrowser for help on using the repository browser.