source: src/mlx/gui/flight.py@ 60:110237fed44b

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

Implemented the payload setup page.

File size: 31.4 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
8
9#-----------------------------------------------------------------------------
10
11class Page(gtk.Alignment):
12 """A page in the flight wizard."""
13 def __init__(self, wizard, title, help):
14 """Construct the page."""
15 super(Page, self).__init__(xalign = 0.0, yalign = 0.0,
16 xscale = 1.0, yscale = 1.0)
17 self.set_padding(padding_top = 4, padding_bottom = 4,
18 padding_left = 12, padding_right = 12)
19
20 frame = gtk.Frame()
21 self.add(frame)
22
23 style = self.get_style() if pygobject else self.rc_get_style()
24
25 self._vbox = gtk.VBox()
26 self._vbox.set_homogeneous(False)
27 frame.add(self._vbox)
28
29 eventBox = gtk.EventBox()
30 eventBox.modify_bg(0, style.bg[3])
31
32 alignment = gtk.Alignment(xalign = 0.0, xscale = 0.0)
33
34 label = gtk.Label(title)
35 label.modify_fg(0, style.fg[3])
36 label.modify_font(pango.FontDescription("bold 24"))
37 alignment.set_padding(padding_top = 4, padding_bottom = 4,
38 padding_left = 6, padding_right = 0)
39
40 alignment.add(label)
41 eventBox.add(alignment)
42
43 self._vbox.pack_start(eventBox, False, False, 0)
44
45 table = gtk.Table(3, 1)
46 table.set_homogeneous(True)
47
48 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
49 xscale = 1.0, yscale = 1.0)
50 alignment.set_padding(padding_top = 16, padding_bottom = 16,
51 padding_left = 16, padding_right = 16)
52 alignment.add(table)
53 self._vbox.pack_start(alignment, True, True, 0)
54
55 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
56 xscale = 0, yscale = 0.0)
57 alignment.set_padding(padding_top = 0, padding_bottom = 16,
58 padding_left = 0, padding_right = 0)
59
60 label = gtk.Label(help)
61 label.set_justify(gtk.Justification.CENTER if pygobject
62 else gtk.JUSTIFY_CENTER)
63 alignment.add(label)
64 table.attach(alignment, 0, 1, 0, 1)
65
66 self._mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
67 xscale = 1.0, yscale = 1.0)
68 table.attach(self._mainAlignment, 0, 1, 1, 3)
69
70 buttonAlignment = gtk.Alignment(xalign = 1.0, xscale=0.0, yscale = 0.0)
71 buttonAlignment.set_padding(padding_top = 4, padding_bottom = 10,
72 padding_left = 16, padding_right = 16)
73
74 self._buttonBox = gtk.HButtonBox()
75 self._defaultButton = None
76 buttonAlignment.add(self._buttonBox)
77
78 self._vbox.pack_start(buttonAlignment, False, False, 0)
79
80 self._wizard = wizard
81
82 def setMainWidget(self, widget):
83 """Set the given widget as the main one."""
84 self._mainAlignment.add(widget)
85
86 def addButton(self, label, default = False):
87 """Add a button with the given label.
88
89 Return the button object created."""
90 button = gtk.Button(label)
91 self._buttonBox.add(button)
92 button.set_use_underline(True)
93 if default:
94 button.set_can_default(True)
95 self._defaultButton = button
96 return button
97
98 def activate(self):
99 """Called when this page becomes active.
100
101 This default implementation does nothing."""
102 pass
103
104 def grabDefault(self):
105 """If the page has a default button, make it the default one."""
106 if self._defaultButton is not None:
107 self._defaultButton.grab_default()
108
109#-----------------------------------------------------------------------------
110
111class LoginPage(Page):
112 """The login page."""
113 def __init__(self, wizard):
114 """Construct the login page."""
115 help = "Enter your MAVA pilot's ID and password to\n" \
116 "log in to the MAVA website and download\n" \
117 "your booked flights."
118 super(LoginPage, self).__init__(wizard, "Login", help)
119
120 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
121 xscale = 0.0, yscale = 0.0)
122
123 table = gtk.Table(2, 3)
124 table.set_row_spacings(4)
125 table.set_col_spacings(32)
126 alignment.add(table)
127 self.setMainWidget(alignment)
128
129 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
130 label = gtk.Label("Pilot _ID:")
131 label.set_use_underline(True)
132 labelAlignment.add(label)
133 table.attach(labelAlignment, 0, 1, 0, 1)
134
135 self._pilotID = gtk.Entry()
136 self._pilotID.connect("changed", self._setLoginButton)
137 self._pilotID.set_tooltip_text("Enter your MAVA pilot's ID. This "
138 "usually starts with a "
139 "'P' followed by 3 digits.")
140 table.attach(self._pilotID, 1, 2, 0, 1)
141 label.set_mnemonic_widget(self._pilotID)
142
143 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
144 label = gtk.Label("_Password:")
145 label.set_use_underline(True)
146 labelAlignment.add(label)
147 table.attach(labelAlignment, 0, 1, 1, 2)
148
149 self._password = gtk.Entry()
150 self._password.set_visibility(False)
151 self._password.connect("changed", self._setLoginButton)
152 self._password.set_tooltip_text("Enter the password for your pilot's ID")
153 table.attach(self._password, 1, 2, 1, 2)
154 label.set_mnemonic_widget(self._password)
155
156 self._rememberButton = gtk.CheckButton("_Remember password")
157 self._rememberButton.set_use_underline(True)
158 self._rememberButton.set_tooltip_text("If checked, your password will "
159 "be stored, so that you should "
160 "not have to enter it every time. "
161 "Note, however, that the password "
162 "is stored as text, and anybody "
163 "who can access your files will "
164 "be able to read it.")
165 table.attach(self._rememberButton, 1, 2, 2, 3, ypadding = 8)
166
167 self._loginButton = self.addButton("_Login", default = True)
168 self._loginButton.set_sensitive(False)
169 self._loginButton.connect("clicked", self._loginClicked)
170 self._loginButton.set_tooltip_text("Click to log in.")
171
172 config = self._wizard.gui.config
173 self._pilotID.set_text(config.pilotID)
174 self._password.set_text(config.password)
175 self._rememberButton.set_active(config.rememberPassword)
176
177 def _setLoginButton(self, entry):
178 """Set the login button's sensitivity.
179
180 The button is sensitive only if both the pilot ID and the password
181 fields contain values."""
182 self._loginButton.set_sensitive(self._pilotID.get_text()!="" and
183 self._password.get_text()!="")
184
185 def _loginClicked(self, button):
186 """Called when the login button was clicked."""
187 self._wizard.gui.beginBusy("Logging in...")
188 self._wizard.gui.webHandler.login(self._loginResultCallback,
189 self._pilotID.get_text(),
190 self._password.get_text())
191
192 def _loginResultCallback(self, returned, result):
193 """The login result callback, called in the web handler's thread."""
194 gobject.idle_add(self._handleLoginResult, returned, result)
195
196 def _handleLoginResult(self, returned, result):
197 """Handle the login result."""
198 self._wizard.gui.endBusy()
199 if returned:
200 if result.loggedIn:
201 config = self._wizard.gui.config
202
203 config.pilotID = self._pilotID.get_text()
204
205 rememberPassword = self._rememberButton.get_active()
206 config.password = self._password.get_text() if rememberPassword \
207 else ""
208
209 config.rememberPassword = rememberPassword
210
211 config.save()
212 self._wizard._loginResult = result
213 self._wizard.nextPage()
214 else:
215 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
216 buttons = BUTTONSTYPE_OK,
217 message_format =
218 "Invalid pilot's ID or password.")
219 dialog.format_secondary_markup("Check the ID and try to reenter"
220 " the password.")
221 dialog.run()
222 dialog.hide()
223 else:
224 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
225 buttons = BUTTONSTYPE_OK,
226 message_format =
227 "Failed to connect to the MAVA website.")
228 dialog.format_secondary_markup("Try again in a few minutes.")
229 dialog.run()
230 dialog.hide()
231
232#-----------------------------------------------------------------------------
233
234class FlightSelectionPage(Page):
235 """The page to select the flight."""
236 def __init__(self, wizard):
237 """Construct the flight selection page."""
238 super(FlightSelectionPage, self).__init__(wizard, "Flight selection",
239 "Select the flight you want "
240 "to perform.")
241
242
243 self._listStore = gtk.ListStore(str, str, str, str)
244 self._flightList = gtk.TreeView(self._listStore)
245 column = gtk.TreeViewColumn("Flight no.", gtk.CellRendererText(),
246 text = 1)
247 column.set_expand(True)
248 self._flightList.append_column(column)
249 column = gtk.TreeViewColumn("Departure time [UTC]", gtk.CellRendererText(),
250 text = 0)
251 column.set_expand(True)
252 self._flightList.append_column(column)
253 column = gtk.TreeViewColumn("From", gtk.CellRendererText(),
254 text = 2)
255 column.set_expand(True)
256 self._flightList.append_column(column)
257 column = gtk.TreeViewColumn("To", gtk.CellRendererText(),
258 text = 3)
259 column.set_expand(True)
260 self._flightList.append_column(column)
261
262 flightSelection = self._flightList.get_selection()
263 flightSelection.connect("changed", self._selectionChanged)
264
265 scrolledWindow = gtk.ScrolledWindow()
266 scrolledWindow.add(self._flightList)
267 scrolledWindow.set_size_request(400, -1)
268 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
269 else gtk.POLICY_AUTOMATIC,
270 gtk.PolicyType.ALWAYS if pygobject
271 else gtk.POLICY_ALWAYS)
272
273 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 0.0, yscale = 1.0)
274 alignment.add(scrolledWindow)
275
276 self.setMainWidget(alignment)
277
278 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
279 self._button.set_use_stock(True)
280 self._button.set_sensitive(False)
281 self._button.connect("clicked", self._forwardClicked)
282
283 self._activated = False
284
285 def activate(self):
286 """Fill the flight list."""
287 if not self._activated:
288 for flight in self._wizard.loginResult.flights:
289 self._listStore.append([str(flight.departureTime),
290 flight.callsign,
291 flight.departureICAO,
292 flight.arrivalICAO])
293 self._activated = True
294
295 def _selectionChanged(self, selection):
296 """Called when the selection is changed."""
297 self._button.set_sensitive(selection.count_selected_rows()==1)
298
299 def _forwardClicked(self, button):
300 """Called when the forward button was clicked."""
301 selection = self._flightList.get_selection()
302 (listStore, iter) = selection.get_selected()
303 path = listStore.get_path(iter)
304 [index] = path.get_indices() if pygobject else path
305
306 flight = self._wizard.loginResult.flights[index]
307 self._wizard._bookedFlight = flight
308
309 self._updateDepartureGate()
310
311 def _updateDepartureGate(self):
312 """Update the departure gate for the booked flight."""
313 flight = self._wizard._bookedFlight
314 if flight.departureICAO=="LHBP":
315 self._wizard._getFleet(self._fleetRetrieved)
316 else:
317 self._wizard.jumpPage(2)
318
319 def _fleetRetrieved(self, fleet):
320 """Called when the fleet has been retrieved."""
321 if fleet is None:
322 self._wizard.jumpPage(2)
323 else:
324 plane = fleet[self._wizard._bookedFlight.tailNumber]
325 if plane is None:
326 self._wizard.jumpPage(2)
327
328 if plane.gateNumber is not None and \
329 not fleet.isGateConflicting(plane):
330 self._wizard._departureGate = plane.gateNumber
331 self._wizard.jumpPage(2)
332 else:
333 self._wizard.nextPage()
334
335#-----------------------------------------------------------------------------
336
337class GateSelectionPage(Page):
338 """Page to select a free gate at LHBP.
339
340 This page should be displayed only if we have fleet information!."""
341 def __init__(self, wizard):
342 """Construct the gate selection page."""
343 help = "The airplane's gate position is invalid.\n\n" \
344 "Select the gate from which you\n" \
345 "would like to begin the flight."
346 super(GateSelectionPage, self).__init__(wizard,
347 "LHBP gate selection",
348 help)
349
350 self._listStore = gtk.ListStore(str)
351 self._gateList = gtk.TreeView(self._listStore)
352 column = gtk.TreeViewColumn(None, gtk.CellRendererText(),
353 text = 0)
354 column.set_expand(True)
355 self._gateList.append_column(column)
356 self._gateList.set_headers_visible(False)
357
358 gateSelection = self._gateList.get_selection()
359 gateSelection.connect("changed", self._selectionChanged)
360
361 scrolledWindow = gtk.ScrolledWindow()
362 scrolledWindow.add(self._gateList)
363 scrolledWindow.set_size_request(50, -1)
364 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
365 else gtk.POLICY_AUTOMATIC,
366 gtk.PolicyType.ALWAYS if pygobject
367 else gtk.POLICY_ALWAYS)
368
369 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 0.0, yscale = 1.0)
370 alignment.add(scrolledWindow)
371
372 self.setMainWidget(alignment)
373
374 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
375 self._button.set_use_stock(True)
376 self._button.set_sensitive(False)
377 self._button.connect("clicked", self._forwardClicked)
378
379 def activate(self):
380 """Fill the gate list."""
381 self._listStore.clear()
382 occupiedGateNumbers = self._wizard._fleet.getOccupiedGateNumbers()
383 for gateNumber in const.lhbpGateNumbers:
384 if gateNumber not in occupiedGateNumbers:
385 self._listStore.append([gateNumber])
386
387 def _selectionChanged(self, selection):
388 """Called when the selection is changed."""
389 self._button.set_sensitive(selection.count_selected_rows()==1)
390
391 def _forwardClicked(self, button):
392 """Called when the forward button is clicked."""
393 selection = self._gateList.get_selection()
394 (listStore, iter) = selection.get_selected()
395 (gateNumber,) = listStore.get(iter, 0)
396
397 self._wizard._departureGate = gateNumber
398
399 #self._wizard._updatePlane(self._planeUpdated,
400 # self._wizard._bookedFlight.tailNumber,
401 # const.PLANE_HOME,
402 # gateNumber)
403 self._wizard.nextPage()
404
405 def _planeUpdated(self, success):
406 """Callback for the plane updating call."""
407 if success is None or success:
408 self._wizard.nextPage()
409 else:
410 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
411 buttons = BUTTONSTYPE_OK,
412 message_format = "Gate conflict detected again")
413 dialog.format_secondary_markup("Try to select a different gate.")
414 dialog.run()
415 dialog.hide()
416
417 self._wizard._getFleet(self._fleetRetrieved)
418
419 def _fleetRetrieved(self, fleet):
420 """Called when the fleet has been retrieved."""
421 if fleet is None:
422 self._wizard.nextPage()
423 else:
424 self.activate()
425
426#-----------------------------------------------------------------------------
427
428class ConnectPage(Page):
429 """Page which displays the departure airport and gate (if at LHBP)."""
430 def __init__(self, wizard):
431 """Construct the connect page."""
432 help = "The flight begins at the airport given below.\n" \
433 "Park your aircraft there, at the gate below, if given.\n\n" \
434 "Then press the Connect button to connect to the simulator."
435 super(ConnectPage, self).__init__(wizard,
436 "Connect to the simulator",
437 help)
438
439 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
440 xscale = 0.0, yscale = 0.0)
441
442 table = gtk.Table(2, 2)
443 table.set_row_spacings(4)
444 table.set_col_spacings(16)
445 table.set_homogeneous(True)
446 alignment.add(table)
447 self.setMainWidget(alignment)
448
449 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
450 label = gtk.Label("ICAO code:")
451 labelAlignment.add(label)
452 table.attach(labelAlignment, 0, 1, 0, 1)
453
454 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
455 self._departureICAO = gtk.Label()
456 self._departureICAO.set_width_chars(5)
457 self._departureICAO.set_alignment(0.0, 0.5)
458 labelAlignment.add(self._departureICAO)
459 table.attach(labelAlignment, 1, 2, 0, 1)
460
461 labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
462 label = gtk.Label("Gate:")
463 labelAlignment.add(label)
464 table.attach(labelAlignment, 0, 1, 1, 2)
465
466 labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
467 self._departureGate = gtk.Label()
468 self._departureGate.set_width_chars(5)
469 self._departureGate.set_alignment(0.0, 0.5)
470 labelAlignment.add(self._departureGate)
471 table.attach(labelAlignment, 1, 2, 1, 2)
472
473 self._button = self.addButton("_Connect", default = True)
474 self._button.set_use_underline(True)
475 self._button.connect("clicked", self._connectClicked)
476
477 def activate(self):
478 """Setup the departure information."""
479 icao = self._wizard._bookedFlight.departureICAO
480 self._departureICAO.set_markup("<b>" + icao + "</b>")
481 gate = self._wizard._departureGate
482 if gate!="-":
483 gate = "<b>" + gate + "</b>"
484 self._departureGate.set_markup(gate)
485
486 def _connectClicked(self, button):
487 """Called when the Connect button is pressed."""
488 self._wizard._connectSimulator()
489
490#-----------------------------------------------------------------------------
491
492class PayloadPage(Page):
493 """Page to allow setting up the payload."""
494 def __init__(self, wizard):
495 """Construct the page."""
496 help = "The briefing contains the weights below.\n" \
497 "Setup the cargo weight here and the payload weight in the simulator.\n\n" \
498 "You can also check here what the simulator reports as ZFW."
499
500 super(PayloadPage, self).__init__(wizard, "Payload", help)
501
502 alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
503 xscale = 0.0, yscale = 0.0)
504
505 table = gtk.Table(7, 3)
506 table.set_row_spacings(4)
507 table.set_col_spacings(16)
508 table.set_homogeneous(False)
509 alignment.add(table)
510 self.setMainWidget(alignment)
511
512 label = gtk.Label("Crew:")
513 label.set_alignment(0.0, 0.5)
514 table.attach(label, 0, 1, 0, 1)
515
516 self._numCrew = gtk.Label()
517 self._numCrew.set_width_chars(6)
518 self._numCrew.set_alignment(1.0, 0.5)
519 table.attach(self._numCrew, 1, 2, 0, 1)
520
521 label = gtk.Label("Passengers:")
522 label.set_alignment(0.0, 0.5)
523 table.attach(label, 0, 1, 1, 2)
524
525 self._numPassengers = gtk.Label()
526 self._numPassengers.set_width_chars(6)
527 self._numPassengers.set_alignment(1.0, 0.5)
528 table.attach(self._numPassengers, 1, 2, 1, 2)
529
530 label = gtk.Label("Baggage:")
531 label.set_alignment(0.0, 0.5)
532 table.attach(label, 0, 1, 2, 3)
533
534 self._bagWeight = gtk.Label()
535 self._bagWeight.set_width_chars(6)
536 self._bagWeight.set_alignment(1.0, 0.5)
537 table.attach(self._bagWeight, 1, 2, 2, 3)
538
539 table.attach(gtk.Label("kg"), 2, 3, 2, 3)
540
541 label = gtk.Label("_Cargo:")
542 label.set_use_underline(True)
543 label.set_alignment(0.0, 0.5)
544 table.attach(label, 0, 1, 3, 4)
545
546 self._cargoWeight = gtk.Entry()
547 self._cargoWeight.set_width_chars(6)
548 self._cargoWeight.set_alignment(1.0)
549 self._cargoWeight.connect("changed", self._cargoWeightChanged)
550 self._cargoWeight.set_tooltip_text("The weight of the cargo for your flight.")
551 table.attach(self._cargoWeight, 1, 2, 3, 4)
552 self._cargoWeightValue = 0
553 label.set_mnemonic_widget(self._cargoWeight)
554
555 table.attach(gtk.Label("kg"), 2, 3, 3, 4)
556
557 label = gtk.Label("Mail:")
558 label.set_alignment(0.0, 0.5)
559 table.attach(label, 0, 1, 4, 5)
560
561 self._mailWeight = gtk.Label()
562 self._mailWeight.set_width_chars(6)
563 self._mailWeight.set_alignment(1.0, 0.5)
564 table.attach(self._mailWeight, 1, 2, 4, 5)
565
566 table.attach(gtk.Label("kg"), 2, 3, 4, 5)
567
568 label = gtk.Label("<b>Calculated ZFW:</b>")
569 label.set_alignment(0.0, 0.5)
570 label.set_use_markup(True)
571 table.attach(label, 0, 1, 5, 6)
572
573 self._calculatedZFW = gtk.Label()
574 self._calculatedZFW.set_width_chars(6)
575 self._calculatedZFW.set_alignment(1.0, 0.5)
576 table.attach(self._calculatedZFW, 1, 2, 5, 6)
577
578 table.attach(gtk.Label("kg"), 2, 3, 5, 6)
579
580 button = gtk.Button("_ZFW from FS:")
581 button.set_use_underline(True)
582 button.connect("clicked", self._zfwRequested)
583 table.attach(button, 0, 1, 6, 7)
584
585 self._simulatorZFW = gtk.Label("-")
586 self._simulatorZFW.set_width_chars(6)
587 self._simulatorZFW.set_alignment(1.0, 0.5)
588 table.attach(self._simulatorZFW, 1, 2, 6, 7)
589 self._simulatorZFWValue = None
590
591 table.attach(gtk.Label("kg"), 2, 3, 6, 7)
592
593 self._button = self.addButton(gtk.STOCK_GO_FORWARD, default = True)
594 self._button.set_use_stock(True)
595 self._button.connect("clicked", self._forwardClicked)
596
597 def activate(self):
598 """Setup the information."""
599 bookedFlight = self._wizard._bookedFlight
600 self._numCrew.set_text(str(bookedFlight.numCrew))
601 self._numPassengers.set_text(str(bookedFlight.numPassengers))
602 self._bagWeight.set_text(str(bookedFlight.bagWeight))
603 self._cargoWeightValue = bookedFlight.cargoWeight
604 self._cargoWeight.set_text(str(bookedFlight.cargoWeight))
605 self._mailWeight.set_text(str(bookedFlight.mailWeight))
606 self._updateCalculatedZFW()
607
608 def _calculateZFW(self):
609 """Calculate the ZFW value."""
610 zfw = self._wizard.gui._flight.aircraft.dow
611 bookedFlight = self._wizard._bookedFlight
612 zfw += (bookedFlight.numCrew + bookedFlight.numPassengers) * 82
613 zfw += bookedFlight.bagWeight
614 zfw += self._cargoWeightValue
615 zfw += bookedFlight.mailWeight
616 return zfw
617
618 def _updateCalculatedZFW(self):
619 """Update the calculated ZFW"""
620 zfw = self._calculateZFW()
621
622 markupBegin = "<b>"
623 markupEnd = "</b>"
624 if self._simulatorZFWValue is not None and \
625 PayloadChecker.isZFWFaulty(self._simulatorZFWValue, zfw):
626 markupBegin += '<span foreground="red">'
627 markupEnd = "</span>" + markupEnd
628 self._calculatedZFW.set_markup(markupBegin + str(zfw) + markupEnd)
629
630 def _cargoWeightChanged(self, entry):
631 """Called when the cargo weight has changed."""
632 text = self._cargoWeight.get_text()
633 if text=="":
634 self._cargoWeightValue = 0
635 else:
636 try:
637 self._cargoWeightValue = int(text)
638 except:
639 self._cargoWeight.set_text(str(self._cargoWeightValue))
640 self._updateCalculatedZFW()
641
642 def _zfwRequested(self, button):
643 """Called when the ZFW is requested from the simulator."""
644 self._wizard.gui.simulator.requestZFW(self._handleZFW)
645
646 def _handleZFW(self, zfw):
647 """Called when the ZFW value is retrieved."""
648 gobject.idle_add(self._processZFW, zfw)
649
650 def _processZFW(self, zfw):
651 """Process the given ZFW value received from the simulator."""
652 self._simulatorZFWValue = zfw
653 self._simulatorZFW.set_text("%.0f" % (zfw,))
654 self._updateCalculatedZFW()
655
656 def _forwardClicked(self, button):
657 """Called when the forward button is clicked."""
658 self._wizard._zfw = self._calculateZFW()
659 self._wizard.nextPage()
660
661#-----------------------------------------------------------------------------
662
663class Wizard(gtk.VBox):
664 """The flight wizard."""
665 def __init__(self, gui):
666 """Construct the wizard."""
667 super(Wizard, self).__init__()
668
669 self.gui = gui
670
671 self._pages = []
672 self._currentPage = None
673
674 self._pages.append(LoginPage(self))
675 self._pages.append(FlightSelectionPage(self))
676 self._pages.append(GateSelectionPage(self))
677 self._pages.append(ConnectPage(self))
678 self._pages.append(PayloadPage(self))
679
680 maxWidth = 0
681 maxHeight = 0
682 for page in self._pages:
683 page.show_all()
684 pageSizeRequest = page.size_request()
685 width = pageSizeRequest.width if pygobject else pageSizeRequest[0]
686 height = pageSizeRequest.height if pygobject else pageSizeRequest[1]
687 maxWidth = max(maxWidth, width)
688 maxHeight = max(maxHeight, height)
689 maxWidth += 16
690 maxHeight += 32
691 self.set_size_request(maxWidth, maxHeight)
692
693 self._initialize()
694
695 @property
696 def loginResult(self):
697 """Get the login result."""
698 return self._loginResult
699
700 def setCurrentPage(self, index):
701 """Set the current page to the one with the given index."""
702 assert index < len(self._pages)
703
704 if self._currentPage is not None:
705 self.remove(self._pages[self._currentPage])
706
707 self._currentPage = index
708 self.add(self._pages[index])
709 self._pages[index].activate()
710 self.show_all()
711
712 def nextPage(self):
713 """Go to the next page."""
714 self.jumpPage(1)
715
716 def jumpPage(self, count):
717 """Go to the page which is 'count' pages after the current one."""
718 self.setCurrentPage(self._currentPage + count)
719 self.grabDefault()
720
721 def grabDefault(self):
722 """Make the default button of the current page the default."""
723 self._pages[self._currentPage].grabDefault()
724
725 def connected(self, fsType, descriptor):
726 """Called when the connection could be made to the simulator."""
727 self.nextPage()
728
729 def connectionFailed(self):
730 """Called when the connection could not be made to the simulator."""
731 self._initialize()
732
733 def disconnected(self):
734 """Called when we have disconnected from the simulator."""
735 self._initialize()
736
737 def _initialize(self):
738 """Initialize the wizard."""
739 self._fleet = None
740 self._fleetCallback = None
741 self._updatePlaneCallback = None
742
743 self._loginResult = None
744 self._bookedFlight = None
745 self._departureGate = "-"
746 self._zfw = None
747
748 self.setCurrentPage(0)
749
750 def _getFleet(self, callback, force = False):
751 """Get the fleet, if needed.
752
753 callback is function that will be called, when the feet is retrieved,
754 or the retrieval fails. It should have a single argument that will
755 receive the fleet object on success, None otherwise.
756 """
757 if self._fleet is not None and not force:
758 callback(self._fleet)
759
760 self.gui.beginBusy("Retrieving fleet...")
761 self._fleetCallback = callback
762 self.gui.webHandler.getFleet(self._fleetResultCallback)
763
764 def _fleetResultCallback(self, returned, result):
765 """Called when the fleet has been queried."""
766 gobject.idle_add(self._handleFleetResult, returned, result)
767
768 def _handleFleetResult(self, returned, result):
769 """Handle the fleet result."""
770 self.gui.endBusy()
771 if returned:
772 self._fleet = result.fleet
773 else:
774 self._fleet = None
775
776 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
777 buttons = BUTTONSTYPE_OK,
778 message_format =
779 "Failed to retrieve the information on "
780 "the fleet.")
781 dialog.run()
782 dialog.hide()
783
784 self._fleetCallback(self._fleet)
785
786 def _updatePlane(self, callback, tailNumber, status, gateNumber = None):
787 """Update the given plane's gate information."""
788 self.gui.beginBusy("Updating plane status...")
789 self._updatePlaneCallback = callback
790 self.gui.webHandler.updatePlane(self._updatePlaneResultCallback,
791 tailNumber, status, gateNumber)
792
793 def _updatePlaneResultCallback(self, returned, result):
794 """Callback for the plane updating operation."""
795 gobject.idle_add(self._handleUpdatePlaneResult, returned, result)
796
797 def _handleUpdatePlaneResult(self, returned, result):
798 """Handle the result of a plane update operation."""
799 self.gui.endBusy()
800 if returned:
801 success = result.success
802 else:
803 success = None
804
805 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
806 buttons = BUTTONSTYPE_OK,
807 message_format =
808 "Failed to update the statuis of "
809 "the airplane.")
810 dialog.run()
811 dialog.hide()
812
813 self._updatePlaneCallback(success)
814
815 def _connectSimulator(self):
816 """Connect to the simulator."""
817 self.gui.connectSimulator(self._bookedFlight.aircraftType)
818
819#-----------------------------------------------------------------------------
820
Note: See TracBrowser for help on using the repository browser.