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

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

Implemented the gates tab

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