source: src/mlx/gui/flight.py@ 136:6d206b573dee

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

Added option to enable/disable the online gate system

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