source: src/mlx/gui/flight.py@ 144:3c7d3b02a0be

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

Further enhanced the fuel widget.

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