source: src/mlx/gui/flight.py@ 122:95d8dd0a14a6

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

Eliminated further assertion failures

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