source: src/mlx/gui/flight.py@ 130:f3b2a892af5a

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

Plane position updating works

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