source: src/mlx/gui/flight.py@ 137:f7489252b322

Last change on this file since 137:f7489252b322 was 136:6d206b573dee, checked in by István Váradi <ivaradi@…>, 13 years ago

Added option to enable/disable the online gate system

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