source: src/mlx/gui/flight.py@ 132:92f78dc5b965

Last change on this file since 132:92f78dc5b965 was 130:f3b2a892af5a, checked in by István Váradi <ivaradi@…>, 13 years ago

Plane position updating works

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