source: src/mlx/gui/flight.py@ 140:7f24ede5d214

Last change on this file since 140:7f24ede5d214 was 139:839016dcd0d1, checked in by István Váradi <ivaradi@…>, 13 years ago

Implemented ACARS sending

File size: 86.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 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._uppercasingRoute = False
1030
1031 self._route = gtk.TextView()
1032 self._route.set_tooltip_text(xstr("route_route_tooltip"))
1033 self._route.set_wrap_mode(WRAP_WORD)
1034 self._route.get_buffer().connect("changed", self._routeChanged)
1035 self._route.get_buffer().connect_after("insert-text", self._routeInserted)
1036 routeWindow.add(self._route)
1037
1038 label.set_mnemonic_widget(self._route)
1039 routeBox.pack_start(routeWindow, True, True, 0)
1040
1041 mainBox.pack_start(routeBox, True, True, 8)
1042
1043 self._backButton = self.addPreviousButton(clicked = self._backClicked)
1044 self._button = self.addNextButton(clicked = self._forwardClicked)
1045
1046 @property
1047 def filedCruiseLevel(self):
1048 """Get the filed cruise level."""
1049 return self._filedCruiseLevel
1050
1051 @property
1052 def cruiseLevel(self):
1053 """Get the cruise level."""
1054 return self._cruiseLevel.get_value_as_int()
1055
1056 @property
1057 def route(self):
1058 """Get the route."""
1059 return self._getRoute()
1060
1061 def activate(self):
1062 """Setup the route from the booked flight."""
1063 self._cruiseLevel.set_value(240)
1064 self._filedCruiseLevel = 240
1065 self._route.get_buffer().set_text(self._wizard._bookedFlight.route)
1066 self._updateForwardButton()
1067
1068 def _getRoute(self):
1069 """Get the text of the route."""
1070 buffer = self._route.get_buffer()
1071 return buffer.get_text(buffer.get_start_iter(),
1072 buffer.get_end_iter(), True)
1073
1074 def _updateForwardButton(self):
1075 """Update the sensitivity of the forward button."""
1076 self._button.set_sensitive(self._cruiseLevel.get_value_as_int()>=50 and \
1077 self._getRoute()!="")
1078
1079 def _cruiseLevelChanged(self, spinButton):
1080 """Called when the cruise level has changed."""
1081 self._updateForwardButton()
1082
1083 def _routeChanged(self, textBuffer):
1084 """Called when the route has changed."""
1085 if not self._uppercasingRoute:
1086 self._updateForwardButton()
1087
1088 def _routeInserted(self, textBuffer, iter, text, length):
1089 """Called when new characters are inserted into the route.
1090
1091 It uppercases all characters."""
1092 if not self._uppercasingRoute:
1093 self._uppercasingRoute = True
1094
1095 iter1 = iter.copy()
1096 iter1.backward_chars(length)
1097 textBuffer.delete(iter, iter1)
1098
1099 textBuffer.insert(iter, text.upper())
1100
1101 self._uppercasingRoute = False
1102
1103 def _backClicked(self, button):
1104 """Called when the Back button is pressed."""
1105 self.goBack()
1106
1107 def _forwardClicked(self, button):
1108 """Called when the Forward button is clicked."""
1109 if self._completed:
1110 self._wizard.nextPage()
1111 else:
1112 bookedFlight = self._wizard._bookedFlight
1113 self._filedCruiseLevel = self.cruiseLevel
1114 self._wizard.gui.beginBusy(xstr("route_down_notams"))
1115 self._wizard.gui.webHandler.getNOTAMs(self._notamsCallback,
1116 bookedFlight.departureICAO,
1117 bookedFlight.arrivalICAO)
1118
1119 def _notamsCallback(self, returned, result):
1120 """Callback for the NOTAMs."""
1121 gobject.idle_add(self._handleNOTAMs, returned, result)
1122
1123 def _handleNOTAMs(self, returned, result):
1124 """Handle the NOTAMs."""
1125 if returned:
1126 self._wizard._departureNOTAMs = result.departureNOTAMs
1127 self._wizard._arrivalNOTAMs = result.arrivalNOTAMs
1128 else:
1129 self._wizard._departureNOTAMs = None
1130 self._wizard._arrivalNOTAMs = None
1131
1132 bookedFlight = self._wizard._bookedFlight
1133 self._wizard.gui.beginBusy(xstr("route_down_metars"))
1134 self._wizard.gui.webHandler.getMETARs(self._metarsCallback,
1135 [bookedFlight.departureICAO,
1136 bookedFlight.arrivalICAO])
1137
1138 def _metarsCallback(self, returned, result):
1139 """Callback for the METARs."""
1140 gobject.idle_add(self._handleMETARs, returned, result)
1141
1142 def _handleMETARs(self, returned, result):
1143 """Handle the METARs."""
1144 self._wizard._departureMETAR = None
1145 self._wizard._arrivalMETAR = None
1146 bookedFlight = self._wizard._bookedFlight
1147 if returned:
1148 if bookedFlight.departureICAO in result.metars:
1149 self._wizard._departureMETAR = result.metars[bookedFlight.departureICAO]
1150 if bookedFlight.arrivalICAO in result.metars:
1151 self._wizard._arrivalMETAR = result.metars[bookedFlight.arrivalICAO]
1152
1153 self._wizard.gui.endBusy()
1154 self._backButton.set_sensitive(True)
1155 self._button.set_sensitive(True)
1156 self._wizard.nextPage()
1157
1158#-----------------------------------------------------------------------------
1159
1160class BriefingPage(Page):
1161 """Page for the briefing."""
1162 def __init__(self, wizard, departure):
1163 """Construct the briefing page."""
1164 self._departure = departure
1165
1166 title = xstr("briefing_title") % (1 if departure else 2,
1167 xstr("briefing_departure")
1168 if departure
1169 else xstr("briefing_arrival"))
1170 super(BriefingPage, self).__init__(wizard, title, xstr("briefing_help"),
1171 completedHelp = xstr("briefing_chelp"))
1172
1173 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1174 xscale = 1.0, yscale = 1.0)
1175
1176 mainBox = gtk.VBox()
1177 alignment.add(mainBox)
1178 self.setMainWidget(alignment)
1179
1180 self._notamsFrame = gtk.Frame()
1181 self._notamsFrame.set_label(xstr("briefing_notams_init"))
1182 scrolledWindow = gtk.ScrolledWindow()
1183 scrolledWindow.set_size_request(-1, 128)
1184 # FIXME: these constants should be in common
1185 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1186 else gtk.POLICY_AUTOMATIC,
1187 gtk.PolicyType.AUTOMATIC if pygobject
1188 else gtk.POLICY_AUTOMATIC)
1189 self._notams = gtk.TextView()
1190 self._notams.set_editable(False)
1191 self._notams.set_accepts_tab(False)
1192 self._notams.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
1193 scrolledWindow.add(self._notams)
1194 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
1195 xscale = 1.0, yscale = 1.0)
1196 alignment.set_padding(padding_top = 4, padding_bottom = 0,
1197 padding_left = 0, padding_right = 0)
1198 alignment.add(scrolledWindow)
1199 self._notamsFrame.add(alignment)
1200 mainBox.pack_start(self._notamsFrame, True, True, 4)
1201
1202 self._metarFrame = gtk.Frame()
1203 self._metarFrame.set_label(xstr("briefing_metar_init"))
1204 scrolledWindow = gtk.ScrolledWindow()
1205 scrolledWindow.set_size_request(-1, 32)
1206 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
1207 else gtk.POLICY_AUTOMATIC,
1208 gtk.PolicyType.AUTOMATIC if pygobject
1209 else gtk.POLICY_AUTOMATIC)
1210
1211 self._uppercasingMETAR = False
1212
1213 self._metar = gtk.TextView()
1214 self._metar.set_accepts_tab(False)
1215 self._metar.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
1216 self._metar.get_buffer().connect("changed", self._metarChanged)
1217 self._metar.get_buffer().connect_after("insert-text", self._metarInserted)
1218 scrolledWindow.add(self._metar)
1219 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
1220 xscale = 1.0, yscale = 1.0)
1221 alignment.set_padding(padding_top = 4, padding_bottom = 0,
1222 padding_left = 0, padding_right = 0)
1223 alignment.add(scrolledWindow)
1224 self._metarFrame.add(alignment)
1225 mainBox.pack_start(self._metarFrame, True, True, 4)
1226 self.metarEdited = False
1227
1228 self.addPreviousButton(clicked = self._backClicked)
1229 self._button = self.addNextButton(clicked = self._forwardClicked)
1230
1231 @property
1232 def metar(self):
1233 """Get the METAR on the page."""
1234 buffer = self._metar.get_buffer()
1235 return buffer.get_text(buffer.get_start_iter(),
1236 buffer.get_end_iter(), True)
1237
1238 def setMETAR(self, metar):
1239 """Set the metar."""
1240 self._metar.get_buffer().set_text(metar)
1241 self.metarEdited = False
1242
1243 def activate(self):
1244 """Activate the page."""
1245 if not self._departure:
1246 self._button.set_label(xstr("briefing_button"))
1247 self._button.set_has_tooltip(False)
1248 self._button.set_use_stock(False)
1249
1250 bookedFlight = self._wizard._bookedFlight
1251
1252 icao = bookedFlight.departureICAO if self._departure \
1253 else bookedFlight.arrivalICAO
1254 notams = self._wizard._departureNOTAMs if self._departure \
1255 else self._wizard._arrivalNOTAMs
1256 metar = self._wizard._departureMETAR if self._departure \
1257 else self._wizard._arrivalMETAR
1258
1259 self._notamsFrame.set_label(xstr("briefing_notams_template") % (icao,))
1260 buffer = self._notams.get_buffer()
1261 if notams is None:
1262 buffer.set_text(xstr("briefing_notams_failed"))
1263 elif not notams:
1264 buffer.set_text(xstr("briefing_notams_missing"))
1265 else:
1266 s = ""
1267 for notam in notams:
1268 s += str(notam.begin)
1269 if notam.end is not None:
1270 s += " - " + str(notam.end)
1271 elif notam.permanent:
1272 s += " - PERMANENT"
1273 s += "\n"
1274 if notam.repeatCycle:
1275 s += "Repeat cycle: " + notam.repeatCycle + "\n"
1276 s += notam.notice + "\n"
1277 s += "-------------------- * --------------------\n"
1278 buffer.set_text(s)
1279
1280 self._metarFrame.set_label(xstr("briefing_metar_template") % (icao,))
1281 buffer = self._metar.get_buffer()
1282 if metar is None:
1283 buffer.set_text(xstr("briefing_metar_failed"))
1284 else:
1285 buffer.set_text(metar)
1286
1287 label = self._metarFrame.get_label_widget()
1288 label.set_use_underline(True)
1289 label.set_mnemonic_widget(self._metar)
1290
1291 self.metarEdited = False
1292
1293 def _backClicked(self, button):
1294 """Called when the Back button is pressed."""
1295 self.goBack()
1296
1297 def _forwardClicked(self, button):
1298 """Called when the forward button is clicked."""
1299 if not self._departure:
1300 if not self._completed:
1301 self._wizard.gui.startMonitoring()
1302 self._button.set_label(xstr("button_next"))
1303 self._button.set_tooltip_text(xstr("button_next_tooltip"))
1304 self.complete()
1305
1306 self._wizard.nextPage()
1307
1308 def _metarChanged(self, buffer):
1309 """Called when the METAR has changed."""
1310 if not self._uppercasingMETAR:
1311 self.metarEdited = True
1312 self._button.set_sensitive(buffer.get_text(buffer.get_start_iter(),
1313 buffer.get_end_iter(),
1314 True)!="")
1315
1316 def _metarInserted(self, textBuffer, iter, text, length):
1317 """Called when new characters are inserted into the METAR.
1318
1319 It uppercases all characters."""
1320 if not self._uppercasingMETAR:
1321 self._uppercasingMETAR = True
1322
1323 iter1 = iter.copy()
1324 iter1.backward_chars(length)
1325 textBuffer.delete(iter, iter1)
1326
1327 textBuffer.insert(iter, text.upper())
1328
1329 self._uppercasingMETAR = False
1330
1331#-----------------------------------------------------------------------------
1332
1333class TakeoffPage(Page):
1334 """Page for entering the takeoff data."""
1335 def __init__(self, wizard):
1336 """Construct the takeoff page."""
1337 super(TakeoffPage, self).__init__(wizard, xstr("takeoff_title"),
1338 xstr("takeoff_help"),
1339 completedHelp = xstr("takeoff_chelp"))
1340
1341 self._forwardAllowed = False
1342
1343 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1344 xscale = 0.0, yscale = 0.0)
1345
1346 table = gtk.Table(5, 4)
1347 table.set_row_spacings(4)
1348 table.set_col_spacings(16)
1349 table.set_homogeneous(False)
1350 alignment.add(table)
1351 self.setMainWidget(alignment)
1352
1353 label = gtk.Label(xstr("takeoff_runway"))
1354 label.set_use_underline(True)
1355 label.set_alignment(0.0, 0.5)
1356 table.attach(label, 0, 1, 0, 1)
1357
1358 self._runway = gtk.Entry()
1359 self._runway.set_width_chars(10)
1360 self._runway.set_tooltip_text(xstr("takeoff_runway_tooltip"))
1361 self._runway.connect("changed", self._upperChanged)
1362 table.attach(self._runway, 1, 3, 0, 1)
1363 label.set_mnemonic_widget(self._runway)
1364
1365 label = gtk.Label(xstr("takeoff_sid"))
1366 label.set_use_underline(True)
1367 label.set_alignment(0.0, 0.5)
1368 table.attach(label, 0, 1, 1, 2)
1369
1370 self._sid = gtk.Entry()
1371 self._sid.set_width_chars(10)
1372 self._sid.set_tooltip_text(xstr("takeoff_sid_tooltip"))
1373 self._sid.connect("changed", self._upperChanged)
1374 table.attach(self._sid, 1, 3, 1, 2)
1375 label.set_mnemonic_widget(self._sid)
1376
1377 label = gtk.Label(xstr("takeoff_v1"))
1378 label.set_use_markup(True)
1379 label.set_use_underline(True)
1380 label.set_alignment(0.0, 0.5)
1381 table.attach(label, 0, 1, 2, 3)
1382
1383 self._v1 = IntegerEntry()
1384 self._v1.set_width_chars(4)
1385 self._v1.set_tooltip_markup(xstr("takeoff_v1_tooltip"))
1386 self._v1.connect("integer-changed", self._valueChanged)
1387 table.attach(self._v1, 2, 3, 2, 3)
1388 label.set_mnemonic_widget(self._v1)
1389
1390 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 2, 3)
1391
1392 label = gtk.Label(xstr("takeoff_vr"))
1393 label.set_use_markup(True)
1394 label.set_use_underline(True)
1395 label.set_alignment(0.0, 0.5)
1396 table.attach(label, 0, 1, 3, 4)
1397
1398 self._vr = IntegerEntry()
1399 self._vr.set_width_chars(4)
1400 self._vr.set_tooltip_markup(xstr("takeoff_vr_tooltip"))
1401 self._vr.connect("integer-changed", self._valueChanged)
1402 table.attach(self._vr, 2, 3, 3, 4)
1403 label.set_mnemonic_widget(self._vr)
1404
1405 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 3, 4)
1406
1407 label = gtk.Label(xstr("takeoff_v2"))
1408 label.set_use_markup(True)
1409 label.set_use_underline(True)
1410 label.set_alignment(0.0, 0.5)
1411 table.attach(label, 0, 1, 4, 5)
1412
1413 self._v2 = IntegerEntry()
1414 self._v2.set_width_chars(4)
1415 self._v2.set_tooltip_markup(xstr("takeoff_v2_tooltip"))
1416 self._v2.connect("integer-changed", self._valueChanged)
1417 table.attach(self._v2, 2, 3, 4, 5)
1418 label.set_mnemonic_widget(self._v2)
1419
1420 table.attach(gtk.Label(xstr("label_knots")), 3, 4, 4, 5)
1421
1422 self.addPreviousButton(clicked = self._backClicked)
1423
1424 self._button = self.addNextButton(clicked = self._forwardClicked)
1425
1426 @property
1427 def runway(self):
1428 """Get the runway."""
1429 return self._runway.get_text()
1430
1431 @property
1432 def sid(self):
1433 """Get the SID."""
1434 return self._sid.get_text()
1435
1436 @property
1437 def v1(self):
1438 """Get the v1 speed."""
1439 return self._v1.get_int()
1440
1441 @property
1442 def vr(self):
1443 """Get the vr speed."""
1444 return self._vr.get_int()
1445
1446 @property
1447 def v2(self):
1448 """Get the v2 speed."""
1449 return self._v2.get_int()
1450
1451 def activate(self):
1452 """Activate the page."""
1453 self._runway.set_text("")
1454 self._runway.set_sensitive(True)
1455 self._sid.set_text("")
1456 self._sid.set_sensitive(True)
1457 self._v1.set_int(None)
1458 self._v1.set_sensitive(True)
1459 self._vr.set_int(None)
1460 self._vr.set_sensitive(True)
1461 self._v2.set_int(None)
1462 self._v2.set_sensitive(True)
1463 self._button.set_sensitive(False)
1464
1465 def finalize(self):
1466 """Finalize the page."""
1467 self._runway.set_sensitive(False)
1468 self._sid.set_sensitive(False)
1469 self._v1.set_sensitive(False)
1470 self._vr.set_sensitive(False)
1471 self._v2.set_sensitive(False)
1472 self._wizard.gui.flight.aircraft.updateV1R2()
1473
1474 def allowForward(self):
1475 """Allow going to the next page."""
1476 self._forwardAllowed = True
1477 self._updateForwardButton()
1478
1479 def _updateForwardButton(self):
1480 """Update the sensitivity of the forward button based on some conditions."""
1481 sensitive = self._forwardAllowed and \
1482 self._runway.get_text()!="" and \
1483 self._sid.get_text()!="" and \
1484 self.v1 is not None and \
1485 self.vr is not None and \
1486 self.v2 is not None and \
1487 self.v1 <= self.vr and \
1488 self.vr <= self.v2
1489 self._button.set_sensitive(sensitive)
1490
1491 def _valueChanged(self, widget, arg = None):
1492 """Called when the value of some widget has changed."""
1493 self._updateForwardButton()
1494
1495 def _upperChanged(self, entry, arg = None):
1496 """Called when the value of some entry widget has changed and the value
1497 should be converted to uppercase."""
1498 entry.set_text(entry.get_text().upper())
1499 self._valueChanged(entry, arg)
1500
1501 def _backClicked(self, button):
1502 """Called when the Back button is pressed."""
1503 self.goBack()
1504
1505 def _forwardClicked(self, button):
1506 """Called when the forward button is clicked."""
1507 self._wizard.nextPage()
1508
1509#-----------------------------------------------------------------------------
1510
1511class LandingPage(Page):
1512 """Page for entering landing data."""
1513 def __init__(self, wizard):
1514 """Construct the landing page."""
1515 super(LandingPage, self).__init__(wizard, xstr("landing_title"),
1516 xstr("landing_help"),
1517 completedHelp = xstr("landing_chelp"))
1518
1519 self._flightEnded = False
1520
1521 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1522 xscale = 0.0, yscale = 0.0)
1523
1524 table = gtk.Table(5, 5)
1525 table.set_row_spacings(4)
1526 table.set_col_spacings(16)
1527 table.set_homogeneous(False)
1528 alignment.add(table)
1529 self.setMainWidget(alignment)
1530
1531 self._starButton = gtk.CheckButton()
1532 self._starButton.connect("clicked", self._starButtonClicked)
1533 table.attach(self._starButton, 0, 1, 0, 1)
1534
1535 label = gtk.Label(xstr("landing_star"))
1536 label.set_use_underline(True)
1537 label.set_alignment(0.0, 0.5)
1538 table.attach(label, 1, 2, 0, 1)
1539
1540 self._star = gtk.Entry()
1541 self._star.set_width_chars(10)
1542 self._star.set_tooltip_text(xstr("landing_star_tooltip"))
1543 self._star.connect("changed", self._upperChanged)
1544 self._star.set_sensitive(False)
1545 table.attach(self._star, 2, 4, 0, 1)
1546 label.set_mnemonic_widget(self._starButton)
1547
1548 self._transitionButton = gtk.CheckButton()
1549 self._transitionButton.connect("clicked", self._transitionButtonClicked)
1550 table.attach(self._transitionButton, 0, 1, 1, 2)
1551
1552 label = gtk.Label(xstr("landing_transition"))
1553 label.set_use_underline(True)
1554 label.set_alignment(0.0, 0.5)
1555 table.attach(label, 1, 2, 1, 2)
1556
1557 self._transition = gtk.Entry()
1558 self._transition.set_width_chars(10)
1559 self._transition.set_tooltip_text(xstr("landing_transition_tooltip"))
1560 self._transition.connect("changed", self._upperChanged)
1561 self._transition.set_sensitive(False)
1562 table.attach(self._transition, 2, 4, 1, 2)
1563 label.set_mnemonic_widget(self._transitionButton)
1564
1565 label = gtk.Label(xstr("landing_runway"))
1566 label.set_use_underline(True)
1567 label.set_alignment(0.0, 0.5)
1568 table.attach(label, 1, 2, 2, 3)
1569
1570 self._runway = gtk.Entry()
1571 self._runway.set_width_chars(10)
1572 self._runway.set_tooltip_text(xstr("landing_runway_tooltip"))
1573 self._runway.connect("changed", self._upperChanged)
1574 table.attach(self._runway, 2, 4, 2, 3)
1575 label.set_mnemonic_widget(self._runway)
1576
1577 label = gtk.Label(xstr("landing_approach"))
1578 label.set_use_underline(True)
1579 label.set_alignment(0.0, 0.5)
1580 table.attach(label, 1, 2, 3, 4)
1581
1582 self._approachType = gtk.Entry()
1583 self._approachType.set_width_chars(10)
1584 self._approachType.set_tooltip_text(xstr("landing_approach_tooltip"))
1585 self._approachType.connect("changed", self._upperChanged)
1586 table.attach(self._approachType, 2, 4, 3, 4)
1587 label.set_mnemonic_widget(self._approachType)
1588
1589 label = gtk.Label(xstr("landing_vref"))
1590 label.set_use_markup(True)
1591 label.set_use_underline(True)
1592 label.set_alignment(0.0, 0.5)
1593 table.attach(label, 1, 2, 5, 6)
1594
1595 self._vref = IntegerEntry()
1596 self._vref.set_width_chars(5)
1597 self._vref.set_tooltip_markup(xstr("landing_vref_tooltip"))
1598 self._vref.connect("integer-changed", self._vrefChanged)
1599 table.attach(self._vref, 3, 4, 5, 6)
1600 label.set_mnemonic_widget(self._vref)
1601
1602 table.attach(gtk.Label(xstr("label_knots")), 4, 5, 5, 6)
1603
1604 self.addPreviousButton(clicked = self._backClicked)
1605
1606 self._button = self.addNextButton(clicked = self._forwardClicked)
1607
1608 # These are needed for correct size calculations
1609 self._starButton.set_active(True)
1610 self._transitionButton.set_active(True)
1611
1612 @property
1613 def star(self):
1614 """Get the STAR or None if none entered."""
1615 return self._star.get_text() if self._starButton.get_active() else None
1616
1617 @property
1618 def transition(self):
1619 """Get the transition or None if none entered."""
1620 return self._transition.get_text() \
1621 if self._transitionButton.get_active() else None
1622
1623 @property
1624 def approachType(self):
1625 """Get the approach type."""
1626 return self._approachType.get_text()
1627
1628 @property
1629 def runway(self):
1630 """Get the runway."""
1631 return self._runway.get_text()
1632
1633 @property
1634 def vref(self):
1635 """Return the landing reference speed."""
1636 return self._vref.get_int()
1637
1638 def activate(self):
1639 """Called when the page is activated."""
1640 self._starButton.set_sensitive(True)
1641 self._starButton.set_active(False)
1642 self._star.set_text("")
1643
1644 self._transitionButton.set_sensitive(True)
1645 self._transitionButton.set_active(False)
1646 self._transition.set_text("")
1647
1648 self._runway.set_text("")
1649 self._runway.set_sensitive(True)
1650
1651 self._approachType.set_text("")
1652 self._approachType.set_sensitive(True)
1653
1654 self._vref.set_int(None)
1655 self._vref.set_sensitive(True)
1656
1657 self._updateForwardButton()
1658
1659 def flightEnded(self):
1660 """Called when the flight has ended."""
1661 self._flightEnded = True
1662 self._updateForwardButton()
1663
1664 def finalize(self):
1665 """Finalize the page."""
1666 self._starButton.set_sensitive(False)
1667 self._star.set_sensitive(False)
1668
1669 self._transitionButton.set_sensitive(False)
1670 self._transition.set_sensitive(False)
1671
1672 self._runway.set_sensitive(False)
1673
1674 self._approachType.set_sensitive(False)
1675
1676 self._vref.set_sensitive(False)
1677 self._wizard.gui.flight.aircraft.updateVRef()
1678 # FIXME: Perhaps a separate initialize() call which would set up
1679 # defaults? -> use reset()
1680 self._flightEnded = False
1681
1682 def _starButtonClicked(self, button):
1683 """Called when the STAR button is clicked."""
1684 active = button.get_active()
1685 self._star.set_sensitive(active)
1686 if active:
1687 self._star.grab_focus()
1688 self._updateForwardButton()
1689
1690 def _transitionButtonClicked(self, button):
1691 """Called when the Transition button is clicked."""
1692 active = button.get_active()
1693 self._transition.set_sensitive(active)
1694 if active:
1695 self._transition.grab_focus()
1696 self._updateForwardButton()
1697
1698 def _updateForwardButton(self):
1699 """Update the sensitivity of the forward button."""
1700 sensitive = self._flightEnded and \
1701 (self._starButton.get_active() or \
1702 self._transitionButton.get_active()) and \
1703 (self._star.get_text()!="" or
1704 not self._starButton.get_active()) and \
1705 (self._transition.get_text()!="" or
1706 not self._transitionButton.get_active()) and \
1707 self._runway.get_text()!="" and \
1708 self._approachType.get_text()!="" and \
1709 self.vref is not None
1710 self._button.set_sensitive(sensitive)
1711
1712 def _upperChanged(self, entry):
1713 """Called for entry widgets that must be converted to uppercase."""
1714 entry.set_text(entry.get_text().upper())
1715 self._updateForwardButton()
1716
1717 def _vrefChanged(self, widget, value):
1718 """Called when the Vref has changed."""
1719 self._updateForwardButton()
1720
1721 def _backClicked(self, button):
1722 """Called when the Back button is pressed."""
1723 self.goBack()
1724
1725 def _forwardClicked(self, button):
1726 """Called when the forward button is clicked."""
1727 if self._wizard.gui.config.onlineGateSystem and \
1728 not self._completed and \
1729 self._wizard.bookedFlight.arrivalICAO=="LHBP":
1730 self._wizard.getFleet(callback = self._fleetRetrieved,
1731 force = True)
1732 else:
1733 self._wizard.nextPage()
1734
1735 def _fleetRetrieved(self, fleet):
1736 """Callback for the fleet retrieval."""
1737 self._wizard.nextPage()
1738
1739#-----------------------------------------------------------------------------
1740
1741class FinishPage(Page):
1742 """Flight finish page."""
1743 _flightTypes = [ ("flighttype_scheduled", const.FLIGHTTYPE_SCHEDULED),
1744 ("flighttype_ot", const.FLIGHTTYPE_OLDTIMER),
1745 ("flighttype_vip", const.FLIGHTTYPE_VIP),
1746 ("flighttype_charter", const.FLIGHTTYPE_CHARTER) ]
1747
1748 def __init__(self, wizard):
1749 """Construct the finish page."""
1750 super(FinishPage, self).__init__(wizard, xstr("finish_title"),
1751 xstr("finish_help"))
1752
1753 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
1754 xscale = 0.0, yscale = 0.0)
1755
1756 table = gtk.Table(8, 2)
1757 table.set_row_spacings(4)
1758 table.set_col_spacings(16)
1759 table.set_homogeneous(False)
1760 alignment.add(table)
1761 self.setMainWidget(alignment)
1762
1763 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1764 label = gtk.Label(xstr("finish_rating"))
1765 labelAlignment.add(label)
1766 table.attach(labelAlignment, 0, 1, 0, 1)
1767
1768 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1769 self._flightRating = gtk.Label()
1770 self._flightRating.set_width_chars(7)
1771 self._flightRating.set_alignment(0.0, 0.5)
1772 self._flightRating.set_use_markup(True)
1773 labelAlignment.add(self._flightRating)
1774 table.attach(labelAlignment, 1, 2, 0, 1)
1775
1776 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1777 label = gtk.Label(xstr("finish_flight_time"))
1778 labelAlignment.add(label)
1779 table.attach(labelAlignment, 0, 1, 1, 2)
1780
1781 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1782 self._flightTime = gtk.Label()
1783 self._flightTime.set_width_chars(10)
1784 self._flightTime.set_alignment(0.0, 0.5)
1785 self._flightTime.set_use_markup(True)
1786 labelAlignment.add(self._flightTime)
1787 table.attach(labelAlignment, 1, 2, 1, 2)
1788
1789 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1790 label = gtk.Label(xstr("finish_block_time"))
1791 labelAlignment.add(label)
1792 table.attach(labelAlignment, 0, 1, 2, 3)
1793
1794 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1795 self._blockTime = gtk.Label()
1796 self._blockTime.set_width_chars(10)
1797 self._blockTime.set_alignment(0.0, 0.5)
1798 self._blockTime.set_use_markup(True)
1799 labelAlignment.add(self._blockTime)
1800 table.attach(labelAlignment, 1, 2, 2, 3)
1801
1802 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1803 label = gtk.Label(xstr("finish_distance"))
1804 labelAlignment.add(label)
1805 table.attach(labelAlignment, 0, 1, 3, 4)
1806
1807 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1808 self._distanceFlown = gtk.Label()
1809 self._distanceFlown.set_width_chars(10)
1810 self._distanceFlown.set_alignment(0.0, 0.5)
1811 self._distanceFlown.set_use_markup(True)
1812 labelAlignment.add(self._distanceFlown)
1813 table.attach(labelAlignment, 1, 2, 3, 4)
1814
1815 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
1816 label = gtk.Label(xstr("finish_fuel"))
1817 labelAlignment.add(label)
1818 table.attach(labelAlignment, 0, 1, 4, 5)
1819
1820 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1821 self._fuelUsed = gtk.Label()
1822 self._fuelUsed.set_width_chars(10)
1823 self._fuelUsed.set_alignment(0.0, 0.5)
1824 self._fuelUsed.set_use_markup(True)
1825 labelAlignment.add(self._fuelUsed)
1826 table.attach(labelAlignment, 1, 2, 4, 5)
1827
1828 labelAlignment = gtk.Alignment(xalign = 1.0, xscale = 0.0,
1829 yalign = 0.5, yscale = 0.0)
1830 label = gtk.Label(xstr("finish_type"))
1831 label.set_use_underline(True)
1832 labelAlignment.add(label)
1833 table.attach(labelAlignment, 0, 1, 5, 6)
1834
1835 flightTypeModel = gtk.ListStore(str, int)
1836 for (name, type) in FinishPage._flightTypes:
1837 flightTypeModel.append([xstr(name), type])
1838
1839 self._flightType = gtk.ComboBox(model = flightTypeModel)
1840 renderer = gtk.CellRendererText()
1841 self._flightType.pack_start(renderer, True)
1842 self._flightType.add_attribute(renderer, "text", 0)
1843 self._flightType.set_tooltip_text(xstr("finish_type_tooltip"))
1844 self._flightType.set_active(0)
1845 self._flightType.connect("changed", self._flightTypeChanged)
1846 flightTypeAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1847 flightTypeAlignment.add(self._flightType)
1848 table.attach(flightTypeAlignment, 1, 2, 5, 6)
1849 label.set_mnemonic_widget(self._flightType)
1850
1851 self._onlineFlight = gtk.CheckButton(xstr("finish_online"))
1852 self._onlineFlight.set_use_underline(True)
1853 self._onlineFlight.set_tooltip_text(xstr("finish_online_tooltip"))
1854 onlineFlightAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
1855 onlineFlightAlignment.add(self._onlineFlight)
1856 table.attach(onlineFlightAlignment, 1, 2, 6, 7)
1857
1858 labelAlignment = gtk.Alignment(xalign = 1.0, xscale = 0.0,
1859 yalign = 0.5, yscale = 0.0)
1860 self._gateLabel = gtk.Label(xstr("finish_gate"))
1861 self._gateLabel.set_use_underline(True)
1862 labelAlignment.add(self._gateLabel)
1863 table.attach(labelAlignment, 0, 1, 7, 8)
1864
1865 self._gatesModel = gtk.ListStore(str)
1866
1867 self._gate = gtk.ComboBox(model = self._gatesModel)
1868 renderer = gtk.CellRendererText()
1869 self._gate.pack_start(renderer, True)
1870 self._gate.add_attribute(renderer, "text", 0)
1871 self._gate.set_tooltip_text(xstr("finish_gate_tooltip"))
1872 self._gate.connect("changed", self._gateChanged)
1873 gateAlignment = gtk.Alignment(xalign=0.0, xscale=1.0)
1874 gateAlignment.add(self._gate)
1875 table.attach(gateAlignment, 1, 2, 7, 8)
1876 self._gateLabel.set_mnemonic_widget(self._gate)
1877
1878 self.addPreviousButton(clicked = self._backClicked)
1879
1880 self._saveButton = self.addButton(xstr("finish_save"),
1881 sensitive = False,
1882 tooltip = xstr("finish_send_tooltip"))
1883
1884 self._sendButton = self.addButton(xstr("finish_send"), default = True,
1885 sensitive = False,
1886 clicked = self._sendClicked,
1887 tooltip = xstr("finish_send_tooltip"))
1888
1889 @property
1890 def flightType(self):
1891 """Get the flight type."""
1892 index = self._flightType.get_active()
1893 return None if index<0 else self._flightType.get_model()[index][1]
1894
1895 @property
1896 def online(self):
1897 """Get whether the flight was an online flight or not."""
1898 return self._onlineFlight.get_active()
1899
1900 def activate(self):
1901 """Activate the page."""
1902 flight = self._wizard.gui._flight
1903 rating = flight.logger.getRating()
1904 if rating<0:
1905 self._flightRating.set_markup('<b><span foreground="red">NO GO</span></b>')
1906 else:
1907 self._flightRating.set_markup("<b>%.1f %%</b>" % (rating,))
1908
1909 flightLength = flight.flightTimeEnd - flight.flightTimeStart
1910 self._flightTime.set_markup("<b>%s</b>" % \
1911 (util.getTimeIntervalString(flightLength),))
1912
1913 blockLength = flight.blockTimeEnd - flight.blockTimeStart
1914 self._blockTime.set_markup("<b>%s</b>" % \
1915 (util.getTimeIntervalString(blockLength),))
1916
1917 self._distanceFlown.set_markup("<b>%.2f NM</b>" % \
1918 (flight.flownDistance,))
1919
1920 self._fuelUsed.set_markup("<b>%.0f kg</b>" % \
1921 (flight.startFuel - flight.endFuel,))
1922
1923 self._flightType.set_active(-1)
1924 self._onlineFlight.set_active(True)
1925
1926 self._gatesModel.clear()
1927 if self._wizard.gui.config.onlineGateSystem and \
1928 self._wizard.bookedFlight.arrivalICAO=="LHBP":
1929 occupiedGates = self._wizard._fleet.getOccupiedGateNumbers()
1930 for gateNumber in const.lhbpGateNumbers:
1931 if gateNumber not in occupiedGates:
1932 self._gatesModel.append([gateNumber])
1933 self._gateLabel.set_sensitive(True)
1934 self._gate.set_sensitive(True)
1935 self._gate.set_active(-1)
1936 else:
1937 self._gateLabel.set_sensitive(False)
1938 self._gate.set_sensitive(False)
1939
1940 def _backClicked(self, button):
1941 """Called when the Back button is pressed."""
1942 self.goBack()
1943
1944 def _updateButtons(self):
1945 """Update the sensitivity state of the buttons."""
1946 sensitive = self._flightType.get_active()>=0 and \
1947 (self._gatesModel.get_iter_first() is None or
1948 self._gate.get_active()>=0)
1949
1950 #self._saveButton.set_sensitive(sensitive)
1951 self._sendButton.set_sensitive(sensitive)
1952
1953 def _flightTypeChanged(self, comboBox):
1954 """Called when the flight type has changed."""
1955 self._updateButtons()
1956
1957 def _gateChanged(self, comboBox):
1958 """Called when the arrival gate has changed."""
1959 self._updateButtons()
1960
1961 def _sendClicked(self, button):
1962 """Called when the Send button is clicked."""
1963 pirep = PIREP(self._wizard.gui)
1964 gui = self._wizard.gui
1965 gui.beginBusy(xstr("finish_send_busy"))
1966 gui.webHandler.sendPIREP(self._pirepSentCallback, pirep)
1967
1968 def _pirepSentCallback(self, returned, result):
1969 """Callback for the PIREP sending result."""
1970 gobject.idle_add(self._handlePIREPSent, returned, result)
1971
1972 def _handlePIREPSent(self, returned, result):
1973 """Callback for the PIREP sending result."""
1974 self._wizard.gui.endBusy()
1975 secondaryMarkup = None
1976 type = MESSAGETYPE_ERROR
1977 if returned:
1978 if result.success:
1979 type = MESSAGETYPE_INFO
1980 messageFormat = xstr("finish_send_success")
1981 secondaryMarkup = xstr("finish_send_success_sec")
1982 elif result.alreadyFlown:
1983 messageFormat = xstr("finish_send_already")
1984 secondaryMarkup = xstr("finish_send_already_sec")
1985 elif result.notAvailable:
1986 messageFormat = xstr("finish_send_notavail")
1987 else:
1988 messageFormat = xstr("finish_send_unknown")
1989 secondaryMarkup = xstr("finish_send_unknown_sec")
1990 else:
1991 print "PIREP sending failed", result
1992 messageFormat = xstr("finish_send_failed")
1993 secondaryMarkup = xstr("finish_send_failed_sec")
1994
1995 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
1996 type = type, message_format = messageFormat)
1997 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
1998 dialog.set_title(WINDOW_TITLE_BASE)
1999 if secondaryMarkup is not None:
2000 dialog.format_secondary_markup(secondaryMarkup)
2001
2002 dialog.run()
2003 dialog.hide()
2004
2005 if self._wizard.gui.config.onlineGateSystem and returned and result.success:
2006 bookedFlight = self._wizard.bookedFlight
2007 if bookedFlight.arrivalICAO=="LHBP":
2008 iter = self._gate.get_active_iter()
2009 gateNumber = None if iter is None \
2010 else self._gatesModel.get_value(iter, 0)
2011
2012 status = const.PLANE_PARKING if gateNumber is None \
2013 else const.PLANE_HOME
2014 else:
2015 gateNumber = None
2016 status = const.PLANE_AWAY
2017
2018 self._wizard.updatePlane(self._planeUpdated,
2019 bookedFlight.tailNumber,
2020 status, gateNumber = gateNumber)
2021
2022 def _planeUpdated(self, success):
2023 """Callback for the plane updating."""
2024 pass
2025
2026#-----------------------------------------------------------------------------
2027
2028class Wizard(gtk.VBox):
2029 """The flight wizard."""
2030 def __init__(self, gui):
2031 """Construct the wizard."""
2032 super(Wizard, self).__init__()
2033
2034 self.gui = gui
2035
2036 self._pages = []
2037 self._currentPage = None
2038
2039 self._pages.append(LoginPage(self))
2040 self._pages.append(FlightSelectionPage(self))
2041 self._pages.append(GateSelectionPage(self))
2042 self._pages.append(ConnectPage(self))
2043 self._payloadPage = PayloadPage(self)
2044 self._pages.append(self._payloadPage)
2045 self._payloadIndex = len(self._pages)
2046 self._pages.append(TimePage(self))
2047 self._routePage = RoutePage(self)
2048 self._pages.append(self._routePage)
2049 self._departureBriefingPage = BriefingPage(self, True)
2050 self._pages.append(self._departureBriefingPage)
2051 self._arrivalBriefingPage = BriefingPage(self, False)
2052 self._pages.append(self._arrivalBriefingPage)
2053 self._arrivalBriefingIndex = len(self._pages)
2054 self._takeoffPage = TakeoffPage(self)
2055 self._pages.append(self._takeoffPage)
2056 self._landingPage = LandingPage(self)
2057 self._pages.append(self._landingPage)
2058 self._finishPage = FinishPage(self)
2059 self._pages.append(self._finishPage)
2060
2061 maxWidth = 0
2062 maxHeight = 0
2063 for page in self._pages:
2064 page.show_all()
2065 pageSizeRequest = page.size_request()
2066 width = pageSizeRequest.width if pygobject else pageSizeRequest[0]
2067 height = pageSizeRequest.height if pygobject else pageSizeRequest[1]
2068 maxWidth = max(maxWidth, width)
2069 maxHeight = max(maxHeight, height)
2070 maxWidth += 16
2071 maxHeight += 32
2072 self.set_size_request(maxWidth, maxHeight)
2073
2074 self._initialize()
2075
2076 @property
2077 def loginResult(self):
2078 """Get the login result."""
2079 return self._loginResult
2080
2081 def setCurrentPage(self, index, finalize = False):
2082 """Set the current page to the one with the given index."""
2083 assert index < len(self._pages)
2084
2085 fromPage = self._currentPage
2086 if fromPage is not None:
2087 page = self._pages[fromPage]
2088 if finalize and not page._completed:
2089 page.complete()
2090 self.remove(page)
2091
2092 self._currentPage = index
2093 page = self._pages[index]
2094 self.add(page)
2095 if page._fromPage is None:
2096 page._fromPage = fromPage
2097 page.initialize()
2098 self.show_all()
2099 if fromPage is not None:
2100 self.grabDefault()
2101
2102 @property
2103 def bookedFlight(self):
2104 """Get the booked flight selected."""
2105 return self._bookedFlight
2106
2107 @property
2108 def cargoWeight(self):
2109 """Get the calculated ZFW value."""
2110 return self._payloadPage.cargoWeight
2111
2112 @property
2113 def zfw(self):
2114 """Get the calculated ZFW value."""
2115 return 0 if self._bookedFlight is None \
2116 else self._payloadPage.calculateZFW()
2117
2118 @property
2119 def filedCruiseAltitude(self):
2120 """Get the filed cruise altitude."""
2121 return self._routePage.filedCruiseLevel * 100
2122
2123 @property
2124 def cruiseAltitude(self):
2125 """Get the cruise altitude."""
2126 return self._routePage.cruiseLevel * 100
2127
2128 @property
2129 def route(self):
2130 """Get the route."""
2131 return self._routePage.route
2132
2133 @property
2134 def departureMETAR(self):
2135 """Get the METAR of the departure airport."""
2136 return self._departureBriefingPage.metar
2137
2138 @property
2139 def arrivalMETAR(self):
2140 """Get the METAR of the arrival airport."""
2141 return self._arrivalBriefingPage.metar
2142
2143 @property
2144 def departureRunway(self):
2145 """Get the departure runway."""
2146 return self._takeoffPage.runway
2147
2148 @property
2149 def sid(self):
2150 """Get the SID."""
2151 return self._takeoffPage.sid
2152
2153 @property
2154 def v1(self):
2155 """Get the V1 speed."""
2156 return self._takeoffPage.v1
2157
2158 @property
2159 def vr(self):
2160 """Get the Vr speed."""
2161 return self._takeoffPage.vr
2162
2163 @property
2164 def v2(self):
2165 """Get the V2 speed."""
2166 return self._takeoffPage.v2
2167
2168 @property
2169 def arrivalRunway(self):
2170 """Get the arrival runway."""
2171 return self._landingPage.runway
2172
2173 @property
2174 def star(self):
2175 """Get the STAR."""
2176 return self._landingPage.star
2177
2178 @property
2179 def transition(self):
2180 """Get the transition."""
2181 return self._landingPage.transition
2182
2183 @property
2184 def approachType(self):
2185 """Get the approach type."""
2186 return self._landingPage.approachType
2187
2188 @property
2189 def vref(self):
2190 """Get the Vref speed."""
2191 return self._landingPage.vref
2192
2193 @property
2194 def flightType(self):
2195 """Get the flight type."""
2196 return self._finishPage.flightType
2197
2198 @property
2199 def online(self):
2200 """Get whether the flight was online or not."""
2201 return self._finishPage.online
2202
2203 def nextPage(self, finalize = True):
2204 """Go to the next page."""
2205 self.jumpPage(1, finalize)
2206
2207 def jumpPage(self, count, finalize = True):
2208 """Go to the page which is 'count' pages after the current one."""
2209 self.setCurrentPage(self._currentPage + count, finalize = finalize)
2210
2211 def grabDefault(self):
2212 """Make the default button of the current page the default."""
2213 self._pages[self._currentPage].grabDefault()
2214
2215 def connected(self, fsType, descriptor):
2216 """Called when the connection could be made to the simulator."""
2217 self.nextPage()
2218
2219 def reset(self):
2220 """Resets the wizard to go back to the login page."""
2221 self._initialize()
2222
2223 def setStage(self, stage):
2224 """Set the flight stage to the given one."""
2225 if stage==const.STAGE_TAKEOFF:
2226 self._takeoffPage.allowForward()
2227 elif stage==const.STAGE_LANDING:
2228 if not self._arrivalBriefingPage.metarEdited:
2229 print "Downloading arrival METAR again"
2230 self.gui.webHandler.getMETARs(self._arrivalMETARCallback,
2231 [self._bookedFlight.arrivalICAO])
2232
2233 elif stage==const.STAGE_END:
2234 self._landingPage.flightEnded()
2235
2236 def _initialize(self):
2237 """Initialize the wizard."""
2238 self._fleet = None
2239 self._fleetCallback = None
2240
2241 self._loginResult = None
2242 self._bookedFlight = None
2243 self._departureGate = "-"
2244 self._departureNOTAMs = None
2245 self._departureMETAR = None
2246 self._arrivalNOTAMs = None
2247 self._arrivalMETAR = None
2248
2249 for page in self._pages:
2250 page.reset()
2251
2252 self.setCurrentPage(0)
2253
2254 def getFleet(self, callback, force = False):
2255 """Get the fleet via the GUI and call the given callback."""
2256 self._fleetCallback = callback
2257 self.gui.getFleet(callback = self._fleetRetrieved, force = force)
2258
2259 def _fleetRetrieved(self, fleet):
2260 """Callback for the fleet retrieval."""
2261 self._fleet = fleet
2262 if self._fleetCallback is not None:
2263 self._fleetCallback(fleet)
2264 self._fleetCallback = None
2265
2266 def updatePlane(self, callback, tailNumber, status, gateNumber = None):
2267 """Update the given plane's gate information."""
2268 self.gui.updatePlane(tailNumber, status, gateNumber = gateNumber,
2269 callback = callback)
2270
2271 def _connectSimulator(self):
2272 """Connect to the simulator."""
2273 self.gui.connectSimulator(self._bookedFlight.aircraftType)
2274
2275 def _arrivalMETARCallback(self, returned, result):
2276 """Called when the METAR of the arrival airport is retrieved."""
2277 gobject.idle_add(self._handleArrivalMETAR, returned, result)
2278
2279 def _handleArrivalMETAR(self, returned, result):
2280 """Called when the METAR of the arrival airport is retrieved."""
2281 icao = self._bookedFlight.arrivalICAO
2282 if returned and icao in result.metars:
2283 metar = result.metars[icao]
2284 if metar!="":
2285 self._arrivalBriefingPage.setMETAR(metar)
2286
2287#-----------------------------------------------------------------------------
2288
Note: See TracBrowser for help on using the repository browser.