source: src/mlx/gui/flight.py@ 110:97802dcf8cde

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

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

File size: 83.0 KB
Line 
1# The flight handling "wizard"
2
3from mlx.gui.common import *
4
5import mlx.const as const
6import mlx.fs as fs
7from mlx.checks import PayloadChecker
8import mlx.util as util
9from mlx.pirep import PIREP
10from mlx.i18n import xstr
11
12import datetime
13import time
14
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
33#-----------------------------------------------------------------------------
34
35class Page(gtk.Alignment):
36 """A page in the flight wizard."""
37 def __init__(self, wizard, title, help, completedHelp = None):
38 """Construct the page."""
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()
50 self._vbox.set_homogeneous(False)
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
69 mainBox = gtk.VBox()
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)
75 alignment.add(mainBox)
76 self._vbox.pack_start(alignment, True, True, 0)
77
78 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
79 xscale = 0.0, yscale = 0.0)
80 alignment.set_padding(padding_top = 0, padding_bottom = 16,
81 padding_left = 0, padding_right = 0)
82
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)
98 mainBox.pack_start(alignment, False, False, 0)
99
100 self._mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
101 xscale = 1.0, yscale = 1.0)
102 mainBox.pack_start(self._mainAlignment, True, True, 0)
103
104 buttonAlignment = gtk.Alignment(xalign = 1.0, xscale=0.0, yscale = 0.0)
105 buttonAlignment.set_padding(padding_top = 4, padding_bottom = 10,
106 padding_left = 16, padding_right = 16)
107
108 self._buttonBox = gtk.HBox()
109 self._buttonBox.set_homogeneous(False)
110 self._defaultButton = None
111 buttonAlignment.add(self._buttonBox)
112
113 self._vbox.pack_start(buttonAlignment, False, False, 0)
114
115 self._wizard = wizard
116
117 self._completed = False
118 self._fromPage = None
119
120 def setMainWidget(self, widget):
121 """Set the given widget as the main one."""
122 self._mainAlignment.add(widget)
123
124 def addButton(self, label, default = False, sensitive = True,
125 tooltip = None, clicked = None):
126 """Add a button with the given label.
127
128 Return the button object created."""
129 button = gtk.Button(label)
130 self._buttonBox.pack_start(button, False, False, 4)
131 button.set_use_underline(True)
132 if default:
133 button.set_can_default(True)
134 self._defaultButton = button
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)
140 return button
141
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
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
166 def activate(self):
167 """Called when this page becomes active.
168
169 This default implementation does nothing."""
170 pass
171
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
183 def finalize(self):
184 """Called when the page is finalized."""
185 pass
186
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()
191
192 def reset(self):
193 """Reset the page if the wizard is reset."""
194 self._completed = False
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)
202
203#-----------------------------------------------------------------------------
204
205class LoginPage(Page):
206 """The login page."""
207 def __init__(self, wizard):
208 """Construct the login page."""
209 super(LoginPage, self).__init__(wizard, xstr("login"),
210 xstr("loginHelp"))
211
212 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
213 xscale = 0.0, yscale = 0.0)
214
215 table = gtk.Table(2, 3)
216 table.set_row_spacings(4)
217 table.set_col_spacings(32)
218 alignment.add(table)
219 self.setMainWidget(alignment)
220
221 labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
222 xscale = 0.0, yscale = 0.0)
223 label = gtk.Label(xstr("label_pilotID"))
224 label.set_use_underline(True)
225 labelAlignment.add(label)
226 table.attach(labelAlignment, 0, 1, 0, 1)
227
228 self._pilotID = gtk.Entry()
229 self._pilotID.connect("changed", self._setLoginButton)
230 self._pilotID.set_tooltip_text(xstr("login_pilotID_tooltip"))
231 table.attach(self._pilotID, 1, 2, 0, 1)
232 label.set_mnemonic_widget(self._pilotID)
233
234 labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
235 xscale = 0.0, yscale = 0.0)
236 label = gtk.Label(xstr("label_password"))
237 label.set_use_underline(True)
238 labelAlignment.add(label)
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)
244 self._password.set_tooltip_text(xstr("login_password_tooltip"))
245 table.attach(self._password, 1, 2, 1, 2)
246 label.set_mnemonic_widget(self._password)
247
248 self._rememberButton = gtk.CheckButton(xstr("remember_password"))
249 self._rememberButton.set_use_underline(True)
250 self._rememberButton.set_tooltip_text(xstr("login_remember_tooltip"))
251 table.attach(self._rememberButton, 1, 2, 2, 3, ypadding = 8)
252
253 self._loginButton = self.addButton(xstr("button_login"), default = True)
254 self._loginButton.set_sensitive(False)
255 self._loginButton.connect("clicked", self._loginClicked)
256 self._loginButton.set_tooltip_text(xstr("login_button_tooltip"))
257
258 def activate(self):
259 """Activate the page."""
260 config = self._wizard.gui.config
261 self._pilotID.set_text(config.pilotID)
262 self._password.set_text(config.password)
263 self._rememberButton.set_active(config.rememberPassword)
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."""
275 self._loginButton.set_sensitive(False)
276 gui = self._wizard.gui
277 gui.beginBusy(xstr("login_busy"))
278 gui.webHandler.login(self._loginResultCallback,
279 self._pilotID.get_text(),
280 self._password.get_text())
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."""
288 self._wizard.gui.endBusy()
289 self._loginButton.set_sensitive(True)
290 if returned:
291 if result.loggedIn:
292 config = self._wizard.gui.config
293
294 config.pilotID = self._pilotID.get_text()
295
296 rememberPassword = self._rememberButton.get_active()
297 config.password = self._password.get_text() if rememberPassword \
298 else ""
299
300 config.rememberPassword = rememberPassword
301
302 config.save()
303 self._wizard._loginResult = result
304 self._wizard.nextPage()
305 else:
306 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
307 type = MESSAGETYPE_ERROR,
308 buttons = BUTTONSTYPE_OK,
309 message_format = xstr("login_invalid"))
310 dialog.set_title(WINDOW_TITLE_BASE)
311 dialog.format_secondary_markup(xstr("login_invalid_sec"))
312 dialog.run()
313 dialog.hide()
314 else:
315 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
316 type = MESSAGETYPE_ERROR,
317 buttons = BUTTONSTYPE_OK,
318 message_format = xstr("login_failconn"))
319 dialog.set_title(WINDOW_TITLE_BASE)
320 dialog.format_secondary_markup(xstr("login_failconn_sec"))
321
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."""
331 help = xstr("flightsel_help")
332 completedHelp = xstr("flightsel_chelp")
333 super(FlightSelectionPage, self).__init__(wizard, xstr("flightsel_title"),
334 help, completedHelp = completedHelp)
335
336
337 self._listStore = gtk.ListStore(str, str, str, str)
338 self._flightList = gtk.TreeView(self._listStore)
339 column = gtk.TreeViewColumn(xstr("flightsel_no"), gtk.CellRendererText(),
340 text = 1)
341 column.set_expand(True)
342 self._flightList.append_column(column)
343 column = gtk.TreeViewColumn(xstr("flightsel_deptime"), gtk.CellRendererText(),
344 text = 0)
345 column.set_expand(True)
346 self._flightList.append_column(column)
347 column = gtk.TreeViewColumn(xstr("flightsel_from"), gtk.CellRendererText(),
348 text = 2)
349 column.set_expand(True)
350 self._flightList.append_column(column)
351 column = gtk.TreeViewColumn(xstr("flightsel_to"), gtk.CellRendererText(),
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,
364 gtk.PolicyType.AUTOMATIC if pygobject
365 else gtk.POLICY_AUTOMATIC)
366 scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
367 else gtk.SHADOW_IN)
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
374 self._button = self.addNextButton(sensitive = False,
375 clicked = self._forwardClicked)
376
377 def activate(self):
378 """Fill the flight list."""
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)
390
391 def _selectionChanged(self, selection):
392 """Called when the selection is changed."""
393 self._button.set_sensitive(selection.count_selected_rows()==1)
394
395 def _forwardClicked(self, button):
396 """Called when the forward button was clicked."""
397 if self._completed:
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
404
405 flight = self._wizard.loginResult.flights[index]
406 self._wizard._bookedFlight = flight
407 # FIXME: with PyGObject this call causes error messages to
408 # appear on the standard output
409 self._wizard.gui.enableFlightInfo()
410
411 self._updateDepartureGate()
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:
419 self._nextDistance = 2
420 self._wizard.jumpPage(2)
421
422 def _fleetRetrieved(self, fleet):
423 """Called when the fleet has been retrieved."""
424 if fleet is None:
425 self._nextDistance = 2
426 self._wizard.jumpPage(2)
427 else:
428 plane = fleet[self._wizard._bookedFlight.tailNumber]
429 if plane is None:
430 self._nextDistance = 2
431 self._wizard.jumpPage(2)
432 elif plane.gateNumber is not None and \
433 not fleet.isGateConflicting(plane):
434 self._wizard._departureGate = plane.gateNumber
435 self._nextDistance = 2
436 self._wizard.jumpPage(2)
437 else:
438 self._nextDistance = 1
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."""
448 super(GateSelectionPage, self).__init__(wizard, xstr("gatesel_title"),
449 xstr("gatesel_help"))
450
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,
467 gtk.PolicyType.AUTOMATIC if pygobject
468 else gtk.POLICY_AUTOMATIC)
469 scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
470 else gtk.SHADOW_IN)
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
477 self.addPreviousButton(clicked = self._backClicked)
478
479 self._button = self.addNextButton(sensitive = False,
480 clicked = self._forwardClicked)
481
482 def activate(self):
483 """Fill the gate list."""
484 self._listStore.clear()
485 self._gateList.set_sensitive(True)
486 occupiedGateNumbers = self._wizard._fleet.getOccupiedGateNumbers()
487 for gateNumber in const.lhbpGateNumbers:
488 if gateNumber not in occupiedGateNumbers:
489 self._listStore.append([gateNumber])
490
491 def finalize(self):
492 """Finalize the page."""
493 self._gateList.set_sensitive(False)
494
495 def _selectionChanged(self, selection):
496 """Called when the selection is changed."""
497 self._button.set_sensitive(selection.count_selected_rows()==1)
498
499 def _backClicked(self, button):
500 """Called when the Back button is pressed."""
501 self.goBack()
502
503 def _forwardClicked(self, button):
504 """Called when the forward button is clicked."""
505 if not self._completed:
506 selection = self._gateList.get_selection()
507 (listStore, iter) = selection.get_selected()
508 (gateNumber,) = listStore.get(iter, 0)
509
510 self._wizard._departureGate = gateNumber
511
512 #self._wizard._updatePlane(self._planeUpdated,
513 # self._wizard._bookedFlight.tailNumber,
514 # const.PLANE_HOME,
515 # gateNumber)
516
517 self._wizard.nextPage()
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:
524 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
525 type = MESSAGETYPE_ERROR,
526 buttons = BUTTONSTYPE_OK,
527 message_format = xstr("gatesel_conflict"))
528 dialog.set_title(WINDOW_TITLE_BASE)
529 dialog.format_secondary_markup(xstr("gatesel_conflict_sec"))
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."""
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" \
550 "Then press the Connect button to connect to the simulator."
551 completedHelp = "The basic data of your flight can be read below."
552 super(ConnectPage, self).__init__(wizard, xstr("connect_title"),
553 xstr("connect_help"),
554 completedHelp = xstr("connect_chelp"))
555
556 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
557 xscale = 0.0, yscale = 0.0)
558
559 table = gtk.Table(5, 2)
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)
567 label = gtk.Label(xstr("connect_flightno"))
568 labelAlignment.add(label)
569 table.attach(labelAlignment, 0, 1, 0, 1)
570
571 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
572 self._flightNumber = gtk.Label()
573 self._flightNumber.set_width_chars(7)
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)
579 label = gtk.Label(xstr("connect_acft"))
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)
591 label = gtk.Label(xstr("connect_tailno"))
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()
597 self._tailNumber.set_width_chars(10)
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)
603 label = gtk.Label(xstr("connect_airport"))
604 labelAlignment.add(label)
605 table.attach(labelAlignment, 0, 1, 3, 4)
606
607 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
608 self._departureICAO = gtk.Label()
609 self._departureICAO.set_width_chars(6)
610 self._departureICAO.set_alignment(0.0, 0.5)
611 labelAlignment.add(self._departureICAO)
612 table.attach(labelAlignment, 1, 2, 3, 4)
613
614 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
615 label = gtk.Label(xstr("connect_gate"))
616 labelAlignment.add(label)
617 table.attach(labelAlignment, 0, 1, 4, 5)
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)
624 table.attach(labelAlignment, 1, 2, 4, 5)
625
626 self.addPreviousButton(clicked = self._backClicked)
627
628 self._button = self.addButton(xstr("button_connect"), default = True,
629 tooltip = xstr("button_connect_tooltip"))
630 self._clickedID = self._button.connect("clicked", self._connectClicked)
631
632 def activate(self):
633 """Setup the departure information."""
634 self._button.set_label(xstr("button_connect"))
635 self._button.set_use_underline(True)
636 self._button.set_tooltip_text(xstr("button_connect_tooltip"))
637 self._button.disconnect(self._clickedID)
638 self._clickedID = self._button.connect("clicked", self._connectClicked)
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>")
646
647 self._tailNumber.set_markup("<b>" + bookedFlight.tailNumber + "</b>")
648
649 icao = bookedFlight.departureICAO
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
656 def finalize(self):
657 """Finalize the page."""
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"))
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
668 def _connectClicked(self, button):
669 """Called when the Connect button is pressed."""
670 self._wizard._connectSimulator()
671
672 def _forwardClicked(self, button):
673 """Called when the Forward button is pressed."""
674 self._wizard.nextPage()
675
676#-----------------------------------------------------------------------------
677
678class PayloadPage(Page):
679 """Page to allow setting up the payload."""
680 def __init__(self, wizard):
681 """Construct the page."""
682 super(PayloadPage, self).__init__(wizard, xstr("payload_title"),
683 xstr("payload_help"),
684 completedHelp = xstr("payload_chelp"))
685
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
696 label = gtk.Label(xstr("payload_crew"))
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
705 label = gtk.Label(xstr("payload_pax"))
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
714 label = gtk.Label(xstr("payload_bag"))
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
725 label = gtk.Label(xstr("payload_cargo"))
726 label.set_use_underline(True)
727 label.set_alignment(0.0, 0.5)
728 table.attach(label, 0, 1, 3, 4)
729
730 self._cargoWeight = IntegerEntry(defaultValue = 0)
731 self._cargoWeight.set_width_chars(6)
732 self._cargoWeight.connect("integer-changed", self._cargoWeightChanged)
733 self._cargoWeight.set_tooltip_text(xstr("payload_cargo_tooltip"))
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
739 label = gtk.Label(xstr("payload_mail"))
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
750 label = gtk.Label("<b>" + xstr("payload_zfw") + "</b>")
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
762 self._zfwButton = gtk.Button(xstr("payload_fszfw"))
763 self._zfwButton.set_use_underline(True)
764 self._zfwButton.connect("clicked", self._zfwRequested)
765 self._zfwButton.set_tooltip_text(xstr("payload_fszfw_tooltip"))
766 table.attach(self._zfwButton, 0, 1, 6, 7)
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
776 self._backButton = self.addPreviousButton(clicked = self._backClicked)
777 self._button = self.addNextButton(clicked = self._forwardClicked)
778
779 @property
780 def cargoWeight(self):
781 """Get the cargo weight entered."""
782 return self._cargoWeight.get_int()
783
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))
790 self._cargoWeight.set_int(bookedFlight.cargoWeight)
791 self._cargoWeight.set_sensitive(True)
792 self._mailWeight.set_text(str(bookedFlight.mailWeight))
793 self._simulatorZFW.set_text("-")
794 self._simulatorZFWValue = None
795 self._zfwButton.set_sensitive(True)
796 self._updateCalculatedZFW()
797
798 def finalize(self):
799 """Finalize the payload page."""
800 self._cargoWeight.set_sensitive(False)
801
802 def calculateZFW(self):
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
808 zfw += self._cargoWeight.get_int()
809 zfw += bookedFlight.mailWeight
810 return zfw
811
812 def _updateCalculatedZFW(self):
813 """Update the calculated ZFW"""
814 zfw = self.calculateZFW()
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
824 def _cargoWeightChanged(self, entry, weight):
825 """Called when the cargo weight has changed."""
826 self._updateCalculatedZFW()
827
828 def _zfwRequested(self, button):
829 """Called when the ZFW is requested from the simulator."""
830 self._zfwButton.set_sensitive(False)
831 self._backButton.set_sensitive(False)
832 self._button.set_sensitive(False)
833 gui = self._wizard.gui
834 gui.beginBusy(xstr("payload_zfw_busy"))
835 gui.simulator.requestZFW(self._handleZFW)
836
837 def _handleZFW(self, zfw):
838 """Called when the ZFW value is retrieved."""
839 gobject.idle_add(self._processZFW, zfw)
840
841 def _processZFW(self, zfw):
842 """Process the given ZFW value received from the simulator."""
843 self._wizard.gui.endBusy()
844 self._zfwButton.set_sensitive(True)
845 self._backButton.set_sensitive(True)
846 self._button.set_sensitive(True)
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()
854
855 def _backClicked(self, button):
856 """Called when the Back button is pressed."""
857 self.goBack()
858
859#-----------------------------------------------------------------------------
860
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):
865 super(TimePage, self).__init__(wizard, xstr("time_title"),
866 xstr("time_help"),
867 completedHelp = xstr("time_chelp"))
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
879 label = gtk.Label(xstr("time_departure"))
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
887 label = gtk.Label(xstr("time_arrival"))
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
895 self._timeButton = gtk.Button(xstr("time_fs"))
896 self._timeButton.set_use_underline(True)
897 self._timeButton.set_tooltip_text(xstr("time_fs_tooltip"))
898 self._timeButton.connect("clicked", self._timeRequested)
899 table.attach(self._timeButton, 0, 1, 2, 3)
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
905 self._backButton = self.addPreviousButton(clicked = self._backClicked)
906 self._button = self.addNextButton(clicked = self._forwardClicked)
907
908 def activate(self):
909 """Activate the page."""
910 self._timeButton.set_sensitive(True)
911 bookedFlight = self._wizard._bookedFlight
912 self._departure.set_text(str(bookedFlight.departureTime.time()))
913 self._arrival.set_text(str(bookedFlight.arrivalTime.time()))
914 self._simulatorTime.set_text("-")
915
916 def _timeRequested(self, button):
917 """Request the time from the simulator."""
918 self._timeButton.set_sensitive(False)
919 self._backButton.set_sensitive(False)
920 self._button.set_sensitive(False)
921 self._wizard.gui.beginBusy(xstr("time_busy"))
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()
931 self._timeButton.set_sensitive(True)
932 self._backButton.set_sensitive(True)
933 self._button.set_sensitive(True)
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
954 def _backClicked(self, button):
955 """Called when the Back button is pressed."""
956 self.goBack()
957
958 def _forwardClicked(self, button):
959 """Called when the forward button is clicked."""
960 self._wizard.nextPage()
961
962#-----------------------------------------------------------------------------
963
964class RoutePage(Page):
965 """The page containing the route and the flight level."""
966 def __init__(self, wizard):
967 super(RoutePage, self).__init__(wizard, xstr("route_title"),
968 xstr("route_help"),
969 completedHelp = xstr("route_chelp"))
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
980 label = gtk.Label(xstr("route_level"))
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)
987 self._cruiseLevel.set_tooltip_text(xstr("route_level_tooltip"))
988 self._cruiseLevel.set_numeric(True)
989 self._cruiseLevel.connect("value-changed", self._cruiseLevelChanged)
990 label.set_mnemonic_widget(self._cruiseLevel)
991 self._filedCruiseLevel = 240
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)
1006 label = gtk.Label(xstr("route_route"))
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)
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)
1019
1020 self._route = gtk.TextView()
1021 self._route.set_tooltip_text(xstr("route_route_tooltip"))
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
1030 self._backButton = self.addPreviousButton(clicked = self._backClicked)
1031 self._button = self.addNextButton(clicked = self._forwardClicked)
1032
1033 @property
1034 def filedCruiseLevel(self):
1035 """Get the filed cruise level."""
1036 return self._filedCruiseLevel
1037
1038 @property
1039 def cruiseLevel(self):
1040 """Get the cruise level."""
1041 return self._cruiseLevel.get_value_as_int()
1042
1043 @property
1044 def route(self):
1045 """Get the route."""
1046 return self._getRoute()
1047
1048 def activate(self):
1049 """Setup the route from the booked flight."""
1050 self._cruiseLevel.set_value(240)
1051 self._filedCruiseLevel = 240
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 \
1064 self._getRoute()!="")
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
1074 def _backClicked(self, button):
1075 """Called when the Back button is pressed."""
1076 self.goBack()
1077
1078 def _forwardClicked(self, button):
1079 """Called when the Forward button is clicked."""
1080 if self._completed:
1081 self._wizard.nextPage()
1082 else:
1083 bookedFlight = self._wizard._bookedFlight
1084 self._filedCruiseLevel = self.cruiseLevel
1085 self._wizard.gui.beginBusy(xstr("route_down_notams"))
1086 self._wizard.gui.webHandler.getNOTAMs(self._notamsCallback,
1087 bookedFlight.departureICAO,
1088 bookedFlight.arrivalICAO)
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
1099 else:
1100 self._wizard._departureNOTAMs = None
1101 self._wizard._arrivalNOTAMs = None
1102
1103 bookedFlight = self._wizard._bookedFlight
1104 self._wizard.gui.beginBusy(xstr("route_down_metars"))
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()
1125 self._backButton.set_sensitive(True)
1126 self._button.set_sensitive(True)
1127 self._wizard.nextPage()
1128
1129#-----------------------------------------------------------------------------
1130
1131class BriefingPage(Page):
1132 """Page for the briefing."""
1133 def __init__(self, wizard, departure):
1134 """Construct the briefing page."""
1135 self._departure = departure
1136
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"))
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
1151 self._notamsFrame = gtk.Frame()
1152 self._notamsFrame.set_label(xstr("briefing_notams_init"))
1153 scrolledWindow = gtk.ScrolledWindow()
1154 scrolledWindow.set_size_request(-1, 128)
1155 # FIXME: these constants should be in common
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)
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()
1174 self._metarFrame.set_label(xstr("briefing_metar_init"))
1175 scrolledWindow = gtk.ScrolledWindow()
1176 scrolledWindow.set_size_request(-1, 32)
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)
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)
1184 self._metar.get_buffer().connect("changed", self._metarChanged)
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)
1193 self.metarEdited = False
1194
1195 self.addPreviousButton(clicked = self._backClicked)
1196 self._button = self.addNextButton(clicked = self._forwardClicked)
1197
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
1205 def setMETAR(self, metar):
1206 """Set the metar."""
1207 self._metar.get_buffer().set_text(metar)
1208 self.metarEdited = False
1209
1210 def activate(self):
1211 """Activate the page."""
1212 if not self._departure:
1213 self._button.set_label(xstr("briefing_button"))
1214 self._button.set_has_tooltip(False)
1215 self._button.set_use_stock(False)
1216
1217 bookedFlight = self._wizard._bookedFlight
1218
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
1225
1226 self._notamsFrame.set_label(xstr("briefing_notams_template") % (icao,))
1227 buffer = self._notams.get_buffer()
1228 if notams is None:
1229 buffer.set_text(xstr("briefing_notams_failed"))
1230 elif not notams:
1231 buffer.set_text(xstr("briefing_notams_missing"))
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)
1246
1247 self._metarFrame.set_label(xstr("briefing_metar_template") % (icao,))
1248 buffer = self._metar.get_buffer()
1249 if metar is None:
1250 buffer.set_text(xstr("briefing_metar_failed"))
1251 else:
1252 buffer.set_text(metar)
1253
1254 label = self._metarFrame.get_label_widget()
1255 label.set_use_underline(True)
1256 label.set_mnemonic_widget(self._metar)
1257
1258 self.metarEdited = False
1259
1260 def _backClicked(self, button):
1261 """Called when the Back button is pressed."""
1262 self.goBack()
1263
1264 def _forwardClicked(self, button):
1265 """Called when the forward button is clicked."""
1266 if not self._departure:
1267 if not self._completed:
1268 self._wizard.gui.startMonitoring()
1269 self._button.set_label(xstr("button_next"))
1270 self._button.set_tooltip_text(xstr("button_next_tooltip"))
1271 self.complete()
1272
1273 self._wizard.nextPage()
1274
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
1282#-----------------------------------------------------------------------------
1283
1284class TakeoffPage(Page):
1285 """Page for entering the takeoff data."""
1286 def __init__(self, wizard):
1287 """Construct the takeoff page."""
1288 super(TakeoffPage, self).__init__(wizard, xstr("takeoff_title"),
1289 xstr("takeoff_help"),
1290 completedHelp = xstr("takeoff_chelp"))
1291
1292 self._forwardAllowed = False
1293
1294 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1295 xscale = 0.0, yscale = 0.0)
1296
1297 table = gtk.Table(5, 4)
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
1304 label = gtk.Label(xstr("takeoff_runway"))
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)
1311 self._runway.set_tooltip_text(xstr("takeoff_runway_tooltip"))
1312 self._runway.connect("changed", self._valueChanged)
1313 table.attach(self._runway, 1, 3, 0, 1)
1314 label.set_mnemonic_widget(self._runway)
1315
1316 label = gtk.Label(xstr("takeoff_sid"))
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)
1323 self._sid.set_tooltip_text(xstr("takeoff_sid_tooltip"))
1324 self._sid.connect("changed", self._valueChanged)
1325 table.attach(self._sid, 1, 3, 1, 2)
1326 label.set_mnemonic_widget(self._sid)
1327
1328 label = gtk.Label(xstr("takeoff_v1"))
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
1334 self._v1 = IntegerEntry()
1335 self._v1.set_width_chars(4)
1336 self._v1.set_tooltip_markup(xstr("takeoff_v1_tooltip"))
1337 self._v1.connect("integer-changed", self._valueChanged)
1338 table.attach(self._v1, 2, 3, 2, 3)
1339 label.set_mnemonic_widget(self._v1)
1340
1341 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 2, 3)
1342
1343 label = gtk.Label(xstr("takeoff_vr"))
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
1349 self._vr = IntegerEntry()
1350 self._vr.set_width_chars(4)
1351 self._vr.set_tooltip_markup(xstr("takeoff_vr_tooltip"))
1352 self._vr.connect("integer-changed", self._valueChanged)
1353 table.attach(self._vr, 2, 3, 3, 4)
1354 label.set_mnemonic_widget(self._vr)
1355
1356 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 3, 4)
1357
1358 label = gtk.Label(xstr("takeoff_v2"))
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
1364 self._v2 = IntegerEntry()
1365 self._v2.set_width_chars(4)
1366 self._v2.set_tooltip_markup(xstr("takeoff_v2_tooltip"))
1367 self._v2.connect("integer-changed", self._valueChanged)
1368 table.attach(self._v2, 2, 3, 4, 5)
1369 label.set_mnemonic_widget(self._v2)
1370
1371 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 4, 5)
1372
1373 self.addPreviousButton(clicked = self._backClicked)
1374
1375 self._button = self.addNextButton(clicked = self._forwardClicked)
1376
1377 @property
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
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
1402 def activate(self):
1403 """Activate the page."""
1404 self._runway.set_text("")
1405 self._runway.set_sensitive(True)
1406 self._sid.set_text("")
1407 self._sid.set_sensitive(True)
1408 self._v1.set_int(None)
1409 self._v1.set_sensitive(True)
1410 self._vr.set_int(None)
1411 self._vr.set_sensitive(True)
1412 self._v2.set_int(None)
1413 self._v2.set_sensitive(True)
1414 self._button.set_sensitive(False)
1415
1416 def finalize(self):
1417 """Finalize the page."""
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)
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()
1445
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."""
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."""
1460 super(LandingPage, self).__init__(wizard, xstr("landing_title"),
1461 xstr("landing_help"),
1462 completedHelp = xstr("landing_chelp"))
1463
1464 self._flightEnded = False
1465
1466 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1467 xscale = 0.0, yscale = 0.0)
1468
1469 table = gtk.Table(5, 5)
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
1480 label = gtk.Label(xstr("landing_star"))
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)
1487 self._star.set_tooltip_text(xstr("landing_star_tooltip"))
1488 self._star.connect("changed", self._updateForwardButton)
1489 self._star.set_sensitive(False)
1490 table.attach(self._star, 2, 4, 0, 1)
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
1497 label = gtk.Label(xstr("landing_transition"))
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)
1504 self._transition.set_tooltip_text(xstr("landing_transition_tooltip"))
1505 self._transition.connect("changed", self._updateForwardButton)
1506 self._transition.set_sensitive(False)
1507 table.attach(self._transition, 2, 4, 1, 2)
1508 label.set_mnemonic_widget(self._transitionButton)
1509
1510 label = gtk.Label(xstr("landing_runway"))
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)
1517 self._runway.set_tooltip_text(xstr("landing_runway_tooltip"))
1518 self._runway.connect("changed", self._updateForwardButton)
1519 table.attach(self._runway, 2, 4, 2, 3)
1520 label.set_mnemonic_widget(self._runway)
1521
1522 label = gtk.Label(xstr("landing_approach"))
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)
1529 self._approachType.set_tooltip_text(xstr("landing_approach_tooltip"))
1530 self._approachType.connect("changed", self._updateForwardButton)
1531 table.attach(self._approachType, 2, 4, 3, 4)
1532 label.set_mnemonic_widget(self._approachType)
1533
1534 label = gtk.Label(xstr("landing_vref"))
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
1540 self._vref = IntegerEntry()
1541 self._vref.set_width_chars(5)
1542 self._vref.set_tooltip_markup(xstr("landing_vref_tooltip"))
1543 self._vref.connect("integer-changed", self._vrefChanged)
1544 table.attach(self._vref, 3, 4, 5, 6)
1545 label.set_mnemonic_widget(self._vref)
1546
1547 table.attach(gtk.Label(xstr("label_knots")), 4, 5, 5, 6)
1548
1549 self.addPreviousButton(clicked = self._backClicked)
1550
1551 self._button = self.addNextButton(clicked = self._forwardClicked)
1552
1553 # These are needed for correct size calculations
1554 self._starButton.set_active(True)
1555 self._transitionButton.set_active(True)
1556
1557 @property
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
1579 def vref(self):
1580 """Return the landing reference speed."""
1581 return self._vref.get_int()
1582
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
1599 self._vref.set_int(None)
1600 self._vref.set_sensitive(True)
1601
1602 self._updateForwardButton()
1603
1604 def flightEnded(self):
1605 """Called when the flight has ended."""
1606 self._flightEnded = True
1607 self._updateForwardButton()
1608
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)
1622 self._wizard.gui.flight.aircraft.updateVRef()
1623 # FIXME: Perhaps a separate initialize() call which would set up
1624 # defaults? -> use reset()
1625 self._flightEnded = False
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()
1641 self._updateForwardButton()
1642
1643 def _updateForwardButton(self, widget = None):
1644 """Update the sensitivity of the forward button."""
1645 sensitive = self._flightEnded and \
1646 (self._starButton.get_active() or \
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 \
1653 self._approachType.get_text()!="" and \
1654 self.vref is not None
1655 self._button.set_sensitive(sensitive)
1656
1657 def _vrefChanged(self, widget, value):
1658 """Called when the Vref has changed."""
1659 self._updateForwardButton()
1660
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."""
1667 self._wizard.nextPage()
1668
1669#-----------------------------------------------------------------------------
1670
1671class FinishPage(Page):
1672 """Flight finish page."""
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) ]
1677
1678 def __init__(self, wizard):
1679 """Construct the finish page."""
1680 super(FinishPage, self).__init__(wizard, xstr("finish_title"),
1681 xstr("finish_help"))
1682
1683 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1684 xscale = 0.0, yscale = 0.0)
1685
1686 table = gtk.Table(7, 2)
1687 table.set_row_spacings(4)
1688 table.set_col_spacings(16)
1689 table.set_homogeneous(False)
1690 alignment.add(table)
1691 self.setMainWidget(alignment)
1692
1693 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1694 label = gtk.Label(xstr("finish_rating"))
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)
1707 label = gtk.Label(xstr("finish_flight_time"))
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)
1720 label = gtk.Label(xstr("finish_block_time"))
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)
1733 label = gtk.Label(xstr("finish_distance"))
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)
1746 label = gtk.Label(xstr("finish_fuel"))
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
1758 labelAlignment = gtk.Alignment(xalign = 1.0, xscale = 0.0,
1759 yalign = 0.5, yscale = 0.0)
1760 label = gtk.Label(xstr("finish_type"))
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)
1766 for (name, type) in FinishPage._flightTypes:
1767 flightTypeModel.append([xstr(name), type])
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)
1773 self._flightType.set_tooltip_text(xstr("finish_type_tooltip"))
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
1781 self._onlineFlight = gtk.CheckButton(xstr("finish_online"))
1782 self._onlineFlight.set_use_underline(True)
1783 self._onlineFlight.set_tooltip_text(xstr("finish_online_tooltip"))
1784 onlineFlightAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1785 onlineFlightAlignment.add(self._onlineFlight)
1786 table.attach(onlineFlightAlignment, 1, 2, 6, 7)
1787
1788 self.addPreviousButton(clicked = self._backClicked)
1789
1790 self._saveButton = self.addButton(xstr("finish_save"),
1791 sensitive = False,
1792 tooltip = xstr("finish_send_tooltip"))
1793
1794 self._sendButton = self.addButton(xstr("finish_send"), default = True,
1795 sensitive = False,
1796 clicked = self._sendClicked,
1797 tooltip = xstr("finish_send_tooltip"))
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()
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>" % \
1831 (flight.startFuel - flight.endFuel,))
1832
1833 self._flightType.set_active(-1)
1834 self._onlineFlight.set_active(True)
1835
1836 def _backClicked(self, button):
1837 """Called when the Back button is pressed."""
1838 self.goBack()
1839
1840 def _flightTypeChanged(self, comboBox):
1841 """Called when the flight type has changed."""
1842 index = self._flightType.get_active()
1843 flightTypeIsValid = index>=0
1844 #self._saveButton.set_sensitive(flightTypeIsValid)
1845 self._sendButton.set_sensitive(flightTypeIsValid)
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
1851 gui.beginBusy(xstr("finish_send_busy"))
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
1866 messageFormat = xstr("finish_send_success")
1867 secondaryMarkup = xstr("finish_send_success_sec")
1868 elif result.alreadyFlown:
1869 messageFormat = xstr("finish_send_already")
1870 secondaryMarkup = xstr("finish_send_already_sec")
1871 elif result.notAvailable:
1872 messageFormat = xstr("finish_send_notavail")
1873 else:
1874 messageFormat = xstr("finish_send_unknown")
1875 secondaryMarkup = xstr("finish_send_unknown_sec")
1876 else:
1877 print "PIREP sending failed", result
1878 messageFormat = xstr("finish_send_failed")
1879 secondaryMarkup = xstr("finish_send_failed_sec")
1880
1881 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
1882 type = type, buttons = BUTTONSTYPE_OK,
1883 message_format = messageFormat)
1884 dialog.set_title(WINDOW_TITLE_BASE)
1885 if secondaryMarkup is not None:
1886 dialog.format_secondary_markup(secondaryMarkup)
1887
1888 dialog.run()
1889 dialog.hide()
1890
1891#-----------------------------------------------------------------------------
1892
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))
1906 self._pages.append(GateSelectionPage(self))
1907 self._pages.append(ConnectPage(self))
1908 self._payloadPage = PayloadPage(self)
1909 self._pages.append(self._payloadPage)
1910 self._pages.append(TimePage(self))
1911 self._routePage = RoutePage(self)
1912 self._pages.append(self._routePage)
1913 self._departureBriefingPage = BriefingPage(self, True)
1914 self._pages.append(self._departureBriefingPage)
1915 self._arrivalBriefingPage = BriefingPage(self, False)
1916 self._pages.append(self._arrivalBriefingPage)
1917 self._takeoffPage = TakeoffPage(self)
1918 self._pages.append(self._takeoffPage)
1919 self._landingPage = LandingPage(self)
1920 self._pages.append(self._landingPage)
1921 self._finishPage = FinishPage(self)
1922 self._pages.append(self._finishPage)
1923
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
1937 self._initialize()
1938
1939 @property
1940 def loginResult(self):
1941 """Get the login result."""
1942 return self._loginResult
1943
1944 def setCurrentPage(self, index, finalize = False):
1945 """Set the current page to the one with the given index."""
1946 assert index < len(self._pages)
1947
1948 fromPage = self._currentPage
1949 if fromPage is not None:
1950 page = self._pages[fromPage]
1951 if finalize and not page._completed:
1952 page.complete()
1953 self.remove(page)
1954
1955 self._currentPage = index
1956 page = self._pages[index]
1957 self.add(page)
1958 if page._fromPage is None:
1959 page._fromPage = fromPage
1960 page.initialize()
1961 self.show_all()
1962 if fromPage is not None:
1963 self.grabDefault()
1964
1965 @property
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
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
1982 def filedCruiseAltitude(self):
1983 """Get the filed cruise altitude."""
1984 return self._routePage.filedCruiseLevel * 100
1985
1986 @property
1987 def cruiseAltitude(self):
1988 """Get the cruise altitude."""
1989 return self._routePage.cruiseLevel * 100
1990
1991 @property
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
2017 def v1(self):
2018 """Get the V1 speed."""
2019 return self._takeoffPage.v1
2020
2021 @property
2022 def vr(self):
2023 """Get the Vr speed."""
2024 return self._takeoffPage.vr
2025
2026 @property
2027 def v2(self):
2028 """Get the V2 speed."""
2029 return self._takeoffPage.v2
2030
2031 @property
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
2052 def vref(self):
2053 """Get the Vref speed."""
2054 return self._landingPage.vref
2055
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
2066 def nextPage(self, finalize = True):
2067 """Go to the next page."""
2068 self.jumpPage(1, finalize)
2069
2070 def jumpPage(self, count, finalize = True):
2071 """Go to the page which is 'count' pages after the current one."""
2072 self.setCurrentPage(self._currentPage + count, finalize = finalize)
2073
2074 def grabDefault(self):
2075 """Make the default button of the current page the default."""
2076 self._pages[self._currentPage].grabDefault()
2077
2078 def connected(self, fsType, descriptor):
2079 """Called when the connection could be made to the simulator."""
2080 self.nextPage()
2081
2082 def reset(self):
2083 """Resets the wizard to go back to the login page."""
2084 self._initialize()
2085
2086 def setStage(self, stage):
2087 """Set the flight stage to the given one."""
2088 if stage==const.STAGE_TAKEOFF:
2089 self._takeoffPage.allowForward()
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()
2097 elif stage==const.STAGE_END:
2098 self._landingPage.flightEnded()
2099
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 = "-"
2109 self._departureNOTAMs = None
2110 self._departureMETAR = None
2111 self._arrivalNOTAMs = None
2112 self._arrivalMETAR = None
2113
2114 for page in self._pages:
2115 page.reset()
2116
2117 self.setCurrentPage(0)
2118
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
2129 self.gui.beginBusy(xstr("fleet_busy"))
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
2145 dialog = gtk.MessageDialog(parent = self.gui.mainWindow,
2146 type = MESSAGETYPE_ERROR,
2147 buttons = BUTTONSTYPE_OK,
2148 message_format = xstr("fleet_failed"))
2149 dialog.set_title(WINDOW_TITLE_BASE)
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."""
2157 self.gui.beginBusy(xstr("fleet_update_busy"))
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
2174 dialog = gtk.MessageDialog(parent = self.gui.mainWindow,
2175 type = MESSAGETYPE_ERROR,
2176 buttons = BUTTONSTYPE_OK,
2177 message_format =
2178 xstr("fleet_update_failed"))
2179 dialog.set_title(WINDOW_TITLE_BASE)
2180 dialog.run()
2181 dialog.hide()
2182
2183 self._updatePlaneCallback(success)
2184
2185 def _connectSimulator(self):
2186 """Connect to the simulator."""
2187 self.gui.connectSimulator(self._bookedFlight.aircraftType)
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)
2200
2201#-----------------------------------------------------------------------------
2202
Note: See TracBrowser for help on using the repository browser.