source: src/mlx/gui/flight.py@ 128:e14fcd9d9215

Last change on this file since 128:e14fcd9d9215 was 126:1ab5a6f817e1, checked in by István Váradi <ivaradi@…>, 13 years ago

Fixed fleet retrieval

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