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

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

Implemented the weight help tab

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