source: src/mlx/gui/flight.py@ 143:ec65e7e02833

Last change on this file since 143:ec65e7e02833 was 142:4fe5a65e7c37, checked in by István Váradi <ivaradi@…>, 13 years ago

Eliminated the annoying background of the fuel tank figures

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