source: src/mlx/gui/flight.py@ 107:35310bf5309c

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

Added support for internationalization and translated most of the flight wizard into Hungarian

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