source: src/mlx/gui/flight.py@ 118:aaa1bc00131b

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

Implemented the gates tab

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