source: src/mlx/gui/flight.py@ 117:af3d52b9adc4

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

Implemented the weight help tab

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