source: src/mlx/gui/gui.py@ 45:0938977d6603

Last change on this file since 45:0938977d6603 was 42:f23f648550e9, checked in by István Váradi <ivaradi@…>, 13 years ago

Started the flight wizard and it is now possible to log in

File size: 28.3 KB
Line 
1# The main file for the GUI
2
3from statusicon import StatusIcon
4from statusbar import Statusbar
5from update import Updater
6from mlx.gui.common import *
7from mlx.gui.flight import Wizard
8
9import mlx.const as const
10import mlx.fs as fs
11import mlx.flight as flight
12import mlx.logger as logger
13import mlx.acft as acft
14import mlx.web as web
15
16import time
17import threading
18import sys
19
20acftTypes = [ ("Boeing 737-600", const.AIRCRAFT_B736),
21 ("Boeing 737-700", const.AIRCRAFT_B737),
22 ("Boeing 737-800", const.AIRCRAFT_B738),
23 ("Bombardier Dash 8-Q400", const.AIRCRAFT_DH8D),
24 ("Boeing 737-300", const.AIRCRAFT_B733),
25 ("Boeing 737-400", const.AIRCRAFT_B734),
26 ("Boeing 737-500", const.AIRCRAFT_B735),
27 ("Boeing 767-200", const.AIRCRAFT_B762),
28 ("Boeing 767-300", const.AIRCRAFT_B763),
29 ("Bombardier CRJ200", const.AIRCRAFT_CRJ2),
30 ("Fokker 70", const.AIRCRAFT_F70),
31 ("Lisunov Li-2", const.AIRCRAFT_DC3),
32 ("Tupolev Tu-134", const.AIRCRAFT_T134),
33 ("Tupolev Tu-154", const.AIRCRAFT_T154),
34 ("Yakovlev Yak-40", const.AIRCRAFT_YK40) ]
35
36class GUI(fs.ConnectionListener):
37 """The main GUI class."""
38 def __init__(self, programDirectory, config):
39 """Construct the GUI."""
40 gobject.threads_init()
41
42 self._programDirectory = programDirectory
43 self.config = config
44 self._connecting = False
45 self._connected = False
46 self._logger = logger.Logger(output = self)
47 self._flight = None
48 self._simulator = None
49
50 self._stdioLock = threading.Lock()
51 self._stdioText = ""
52 self._stdioAfterNewLine = True
53
54 self.webHandler = web.Handler()
55 self.webHandler.start()
56
57 self.toRestart = False
58
59 def build(self, iconDirectory):
60 """Build the GUI."""
61
62 window = gtk.Window()
63 window.set_title("MAVA Logger X " + const.VERSION)
64 window.set_icon_from_file(os.path.join(iconDirectory, "logo.ico"))
65 window.connect("delete-event",
66 lambda a, b: self.hideMainWindow())
67 window.connect("window-state-event", self._handleMainWindowState)
68
69 mainVBox = gtk.VBox()
70 window.add(mainVBox)
71
72 notebook = gtk.Notebook()
73 mainVBox.add(notebook)
74
75 notebook.append_page(Wizard(self), gtk.Label("Flight"))
76
77 dataVBox = gtk.VBox()
78 notebook.append_page(dataVBox, gtk.Label("Data"))
79
80 setupFrame = self._buildSetupFrame()
81 setupFrame.set_border_width(8)
82 dataVBox.pack_start(setupFrame, False, False, 0)
83
84 dataFrame = self._buildDataFrame()
85 dataFrame.set_border_width(8)
86 dataVBox.pack_start(dataFrame, False, False, 0)
87
88 logVBox = gtk.VBox()
89 notebook.append_page(logVBox, gtk.Label("Log"))
90
91 logFrame = self._buildLogFrame()
92 logFrame.set_border_width(8)
93 logVBox.pack_start(logFrame, True, True, 0)
94
95 mainVBox.pack_start(gtk.HSeparator(), False, False, 0)
96
97 self._statusbar = Statusbar()
98 mainVBox.pack_start(self._statusbar, False, False, 0)
99
100 window.show_all()
101
102 self._mainWindow = window
103
104 self._statusIcon = StatusIcon(iconDirectory, self)
105
106 def run(self):
107 """Run the GUI."""
108 if self.config.autoUpdate:
109 self._updater = Updater(self,
110 self._programDirectory,
111 self.config.updateURL,
112 self._mainWindow)
113 self._updater.start()
114
115 gtk.main()
116
117 if self._flight is not None:
118 simulator = self._flight.simulator
119 simulator.stopMonitoring()
120 simulator.disconnect()
121
122 def connected(self, fsType, descriptor):
123 """Called when we have connected to the simulator."""
124 self._connected = True
125 self._logger.untimedMessage("Connected to the simulator %s" % (descriptor,))
126 gobject.idle_add(self._statusbar.updateConnection,
127 self._connecting, self._connected)
128
129 def disconnected(self):
130 """Called when we have disconnected from the simulator."""
131 self._connected = False
132 self._logger.untimedMessage("Disconnected from the simulator")
133 gobject.idle_add(self._statusbar.updateConnection,
134 self._connecting, self._connected)
135
136 def write(self, msg):
137 """Write the given message to the log."""
138 gobject.idle_add(self._writeLog, msg)
139
140 def check(self, flight, aircraft, logger, oldState, state):
141 """Update the data."""
142 gobject.idle_add(self._setData, state)
143
144 def resetFlightStatus(self):
145 """Reset the status of the flight."""
146 self._statusbar.resetFlightStatus()
147 self._statusIcon.resetFlightStatus()
148
149 def setStage(self, stage):
150 """Set the stage of the flight."""
151 gobject.idle_add(self._setStage, stage)
152
153 def _setStage(self, stage):
154 """Set the stage of the flight."""
155 self._statusbar.setStage(stage)
156 self._statusIcon.setStage(stage)
157
158 def setRating(self, rating):
159 """Set the rating of the flight."""
160 gobject.idle_add(self._setRating, rating)
161
162 def _setRating(self, rating):
163 """Set the rating of the flight."""
164 self._statusbar.setRating(rating)
165 self._statusIcon.setRating(rating)
166
167 def setNoGo(self, reason):
168 """Set the rating of the flight to No-Go with the given reason."""
169 gobject.idle_add(self._setNoGo, reason)
170
171 def _setNoGo(self, reason):
172 """Set the rating of the flight."""
173 self._statusbar.setNoGo(reason)
174 self._statusIcon.setNoGo(reason)
175
176 def _handleMainWindowState(self, window, event):
177 """Hande a change in the state of the window"""
178 iconified = gdk.WindowState.ICONIFIED if pygobject \
179 else gdk.WINDOW_STATE_ICONIFIED
180 if (event.changed_mask&iconified)!=0 and (event.new_window_state&iconified)!=0:
181 self.hideMainWindow(savePosition = False)
182
183 def hideMainWindow(self, savePosition = True):
184 """Hide the main window and save its position."""
185 if savePosition:
186 (self._mainWindowX, self._mainWindowY) = \
187 self._mainWindow.get_window().get_root_origin()
188 else:
189 self._mainWindowX = self._mainWindowY = None
190 self._mainWindow.hide()
191 self._statusIcon.mainWindowHidden()
192 return True
193
194 def showMainWindow(self):
195 """Show the main window at its former position."""
196 if self._mainWindowX is not None and self._mainWindowY is not None:
197 self._mainWindow.move(self._mainWindowX, self._mainWindowY)
198
199 self._mainWindow.show()
200 self._mainWindow.deiconify()
201
202 self._statusIcon.mainWindowShown()
203
204 def toggleMainWindow(self):
205 """Toggle the main window."""
206 if self._mainWindow.get_visible():
207 self.hideMainWindow()
208 else:
209 self.showMainWindow()
210
211 def restart(self):
212 """Quit and restart the application."""
213 self.toRestart = True
214 self._quit()
215
216 def flushStdIO(self):
217 """Flush any text to the standard error that could not be logged."""
218 if self._stdioText:
219 sys.__stderr__.write(self._stdioText)
220
221 def writeStdIO(self, text):
222 """Write the given text into standard I/O log."""
223 with self._stdioLock:
224 self._stdioText += text
225
226 gobject.idle_add(self._writeStdIO)
227
228 def _writeStdIO(self):
229 """Perform the real writing."""
230 with self._stdioLock:
231 text = self._stdioText
232 self._stdioText = ""
233 if not text: return
234
235 lines = text.splitlines()
236 if text[-1]=="\n":
237 text = ""
238 else:
239 text = lines[-1]
240 lines = lines[:-1]
241
242 for line in lines:
243 if self._stdioAfterNewLine:
244 line = "[STDIO] " + line
245 self._writeLog(line + "\n")
246 self._stdioAfterNewLine = True
247
248 if text:
249 if self._stdioAfterNewLine:
250 text = "[STDIO] " + text
251 self._writeLog(text)
252 self._stdioAfterNewLine = False
253
254 def _connectToggled(self, button):
255 """Callback for the connection button."""
256 if self._connectButton.get_active():
257 self._logger.reset()
258 self._flight = flight.Flight(self._logger, self)
259
260 acftListModel = self._acftList.get_model()
261 self._flight.aircraftType = \
262 acftListModel[self._acftList.get_active()][1]
263 self._flight.aircraft = acft.Aircraft.create(self._flight)
264 self._flight.aircraft._checkers.append(self)
265
266 self._flight.cruiseAltitude = self._flSpinButton.get_value_as_int() * 100
267
268 self._flight.zfw = self._zfwSpinButton.get_value_as_int()
269
270 if self._simulator is None:
271 self._simulator = fs.createSimulator(const.SIM_MSFS9, self)
272
273 self._flight.simulator = self._simulator
274
275 self._connecting = True
276 self._simulator.connect(self._flight.aircraft)
277 self._simulator.startMonitoring()
278 else:
279 self.resetFlightStatus()
280 self._connecting = False
281 self._simulator.stopMonitoring()
282 self._simulator.disconnect()
283 self._flight = None
284
285 self._statusbar.updateConnection(self._connecting, self._connected)
286
287 def _buildSetupFrame(self):
288 """Build the setup frame."""
289 setupFrame = gtk.Frame(label = "Setup")
290
291 frameAlignment = gtk.Alignment(xalign = 0.5)
292
293 frameAlignment.set_padding(padding_top = 4, padding_bottom = 10,
294 padding_left = 16, padding_right = 16)
295
296 setupFrame.add(frameAlignment)
297
298 setupBox = gtk.HBox()
299 frameAlignment.add(setupBox)
300
301 # self._fs9Button = gtk.RadioButton(label = "FS9")
302 # self._fs9Button.set_tooltip_text("Use MS Flight Simulator 2004")
303 # setupBox.pack_start(self._fs9Button, False, False, 0)
304
305 # self._fsxButton = gtk.RadioButton(group = self._fs9Button, label = "FSX")
306 # self._fsxButton.set_tooltip_text("Use MS Flight Simulator X")
307 # setupBox.pack_start(self._fsxButton, False, False, 0)
308
309 # setupBox.pack_start(gtk.VSeparator(), False, False, 8)
310
311 alignment = gtk.Alignment(yalign = 0.5)
312 alignment.set_padding(padding_top = 0, padding_bottom = 0,
313 padding_left = 0, padding_right = 16)
314 alignment.add(gtk.Label("Aicraft:"))
315 setupBox.pack_start(alignment, False, False, 0)
316
317 acftListModel = gtk.ListStore(str, int)
318 for (name, type) in acftTypes:
319 acftListModel.append([name, type])
320
321 self._acftList = gtk.ComboBox(model = acftListModel)
322 renderer_text = gtk.CellRendererText()
323 self._acftList.pack_start(renderer_text, True)
324 self._acftList.add_attribute(renderer_text, "text", 0)
325 self._acftList.set_active(0)
326 self._acftList.set_tooltip_text("Select the type of the aircraft used for the flight.")
327
328 setupBox.pack_start(self._acftList, True, True, 0)
329
330 setupBox.pack_start(gtk.VSeparator(), False, False, 8)
331
332 alignment = gtk.Alignment(yalign = 0.5)
333 alignment.set_padding(padding_top = 0, padding_bottom = 0,
334 padding_left = 0, padding_right = 16)
335 alignment.add(gtk.Label("Cruise FL:"))
336 setupBox.pack_start(alignment, False, False, 0)
337
338 self._flSpinButton = gtk.SpinButton()
339 self._flSpinButton.set_increments(step = 10, page = 100)
340 self._flSpinButton.set_range(min = 0, max = 500)
341 self._flSpinButton.set_value(240)
342 self._flSpinButton.set_tooltip_text("The cruise flight level.")
343 self._flSpinButton.set_numeric(True)
344
345 setupBox.pack_start(self._flSpinButton, False, False, 0)
346
347 setupBox.pack_start(gtk.VSeparator(), False, False, 8)
348
349 alignment = gtk.Alignment(yalign = 0.5)
350 alignment.set_padding(padding_top = 0, padding_bottom = 0,
351 padding_left = 0, padding_right = 16)
352 alignment.add(gtk.Label("ZFW:"))
353 setupBox.pack_start(alignment, False, False, 0)
354
355 self._zfwSpinButton = gtk.SpinButton()
356 self._zfwSpinButton.set_increments(step = 100, page = 1000)
357 self._zfwSpinButton.set_range(min = 0, max = 500000)
358 self._zfwSpinButton.set_value(50000)
359 self._zfwSpinButton.set_tooltip_text("The Zero Fuel Weight for the flight in kgs")
360 self._zfwSpinButton.set_numeric(True)
361
362 setupBox.pack_start(self._zfwSpinButton, False, False, 0)
363
364 setupBox.pack_start(gtk.VSeparator(), False, False, 8)
365
366 self._connectButton = gtk.ToggleButton(label = "Connect")
367 self._connectButton.set_tooltip_text("Push to connect to Flight Simulator and start a new flight.\n"
368 "Push again to disconnect from FS.")
369
370 self._connectButton.connect("toggled", self._connectToggled)
371
372 setupBox.pack_start(self._connectButton, False, False, 0)
373
374 setupBox.pack_start(gtk.VSeparator(), False, False, 8)
375
376 self._quitButton = gtk.Button(label = "Quit")
377 self._quitButton.set_tooltip_text("Quit the program.")
378
379 self._quitButton.connect("clicked", self._quit)
380
381 setupBox.pack_start(self._quitButton, False, False, 0)
382
383 return setupFrame
384
385 def _createLabeledEntry(self, label, width = 8, xalign = 1.0):
386 """Create a labeled entry.
387
388 Return a tuple consisting of:
389 - the box
390 - the entry."""
391
392 alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5, xscale = 1.0)
393 alignment.set_padding(padding_top = 0, padding_bottom = 0,
394 padding_left = 0, padding_right = 16)
395 alignment.add(gtk.Label(label))
396
397 entry = gtk.Entry()
398 entry.set_editable(False)
399 entry.set_width_chars(width)
400 entry.set_max_length(width)
401 entry.set_alignment(xalign)
402
403 return (alignment, entry)
404
405 def _buildDataFrame(self):
406 """Build the frame for the data."""
407 dataFrame = gtk.Frame(label = "Data")
408
409 frameAlignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
410
411 frameAlignment.set_padding(padding_top = 4, padding_bottom = 10,
412 padding_left = 16, padding_right = 16)
413
414 table = gtk.Table(rows = 7, columns = 12)
415 table.set_homogeneous(False)
416 table.set_row_spacings(4)
417 table.set_col_spacings(8)
418
419 (label, self._timestamp) = self._createLabeledEntry("Time:")
420 table.attach(label, 0, 1, 0, 1)
421 table.attach(self._timestamp, 1, 2, 0, 1)
422
423 self._paused = gtk.Label("PAUSED")
424 table.attach(self._paused, 2, 4, 0, 1)
425
426 self._trickMode = gtk.Label("TRICKMODE")
427 table.attach(self._trickMode, 4, 6, 0, 1, xoptions = 0)
428
429 self._overspeed = gtk.Label("OVERSPEED")
430 table.attach(self._overspeed, 6, 8, 0, 1)
431
432 self._stalled = gtk.Label("STALLED")
433 table.attach(self._stalled, 8, 10, 0, 1)
434
435 self._onTheGround = gtk.Label("ONTHEGROUND")
436 table.attach(self._onTheGround, 10, 12, 0, 1)
437
438 (label, self._zfw) = self._createLabeledEntry("ZFW:", 6)
439 table.attach(label, 0, 1, 1, 2)
440 table.attach(self._zfw, 1, 2, 1, 2)
441
442 (label, self._grossWeight) = self._createLabeledEntry("Weight:", 6)
443 table.attach(label, 2, 3, 1, 2)
444 table.attach(self._grossWeight, 3, 4, 1, 2)
445
446 (label, self._heading) = self._createLabeledEntry("Heading:", 3)
447 table.attach(label, 4, 5, 1, 2)
448 table.attach(self._heading, 5, 6, 1, 2)
449
450 (label, self._pitch) = self._createLabeledEntry("Pitch:", 3)
451 table.attach(label, 6, 7, 1, 2)
452 table.attach(self._pitch, 7, 8, 1, 2)
453
454 (label, self._bank) = self._createLabeledEntry("Bank:", 3)
455 table.attach(label, 8, 9, 1, 2)
456 table.attach(self._bank, 9, 10, 1, 2)
457
458 (label, self._vs) = self._createLabeledEntry("VS:", 5)
459 table.attach(label, 10, 11, 1, 2)
460 table.attach(self._vs, 11, 12, 1, 2)
461
462 (label, self._ias) = self._createLabeledEntry("IAS:", 4)
463 table.attach(label, 0, 1, 2, 3)
464 table.attach(self._ias, 1, 2, 2, 3)
465
466 (label, self._mach) = self._createLabeledEntry("Mach:", 4)
467 table.attach(label, 2, 3, 2, 3)
468 table.attach(self._mach, 3, 4, 2, 3)
469
470 (label, self._groundSpeed) = self._createLabeledEntry("GS:", 4)
471 table.attach(label, 4, 5, 2, 3)
472 table.attach(self._groundSpeed, 5, 6, 2, 3)
473
474 (label, self._radioAltitude) = self._createLabeledEntry("Radio alt.:", 6)
475 table.attach(label, 6, 7, 2, 3)
476 table.attach(self._radioAltitude, 7, 8, 2, 3)
477
478 (label, self._altitude) = self._createLabeledEntry("Altitude:", 6)
479 table.attach(label, 8, 9, 2, 3)
480 table.attach(self._altitude, 9, 10, 2, 3)
481
482 (label, self._gLoad) = self._createLabeledEntry("G-Load:", 4)
483 table.attach(label, 10, 11, 2, 3)
484 table.attach(self._gLoad, 11, 12, 2, 3)
485
486 (label, self._flapsSet) = self._createLabeledEntry("Flaps set:", 2)
487 table.attach(label, 0, 1, 3, 4)
488 table.attach(self._flapsSet, 1, 2, 3, 4)
489
490 (label, self._flaps) = self._createLabeledEntry("Flaps:", 2)
491 table.attach(label, 2, 3, 3, 4)
492 table.attach(self._flaps, 3, 4, 3, 4)
493
494 (label, self._altimeter) = self._createLabeledEntry("Altimeter:", 4)
495 table.attach(label, 4, 5, 3, 4)
496 table.attach(self._altimeter, 5, 6, 3, 4)
497
498 (label, self._squawk) = self._createLabeledEntry("Squawk:", 4)
499 table.attach(label, 6, 7, 3, 4)
500 table.attach(self._squawk, 7, 8, 3, 4)
501
502 (label, self._nav1) = self._createLabeledEntry("NAV1:", 5)
503 table.attach(label, 8, 9, 3, 4)
504 table.attach(self._nav1, 9, 10, 3, 4)
505
506 (label, self._nav2) = self._createLabeledEntry("NAV2:", 5)
507 table.attach(label, 10, 11, 3, 4)
508 table.attach(self._nav2, 11, 12, 3, 4)
509
510 (label, self._fuel) = self._createLabeledEntry("Fuel:", 40, xalign = 0.0)
511 table.attach(label, 0, 1, 4, 5)
512 table.attach(self._fuel, 1, 4, 4, 5)
513
514 (label, self._n1) = self._createLabeledEntry("N1/RPM:", 20, xalign = 0.0)
515 table.attach(label, 4, 5, 4, 5)
516 table.attach(self._n1, 5, 8, 4, 5)
517
518 (label, self._reverser) = self._createLabeledEntry("Reverser:", 20, xalign = 0.0)
519 table.attach(label, 8, 9, 4, 5)
520 table.attach(self._reverser, 9, 12, 4, 5)
521
522 self._navLightsOn = gtk.Label("NAV")
523 table.attach(self._navLightsOn, 0, 1, 5, 6)
524
525 self._antiCollisionLightsOn = gtk.Label("ANTICOLLISION")
526 table.attach(self._antiCollisionLightsOn, 1, 3, 5, 6)
527
528 self._strobeLightsOn = gtk.Label("STROBE")
529 table.attach(self._strobeLightsOn, 3, 4, 5, 6)
530
531 self._landingLightsOn = gtk.Label("LANDING")
532 table.attach(self._landingLightsOn, 4, 5, 5, 6)
533
534 self._pitotHeatOn = gtk.Label("PITOT HEAT")
535 table.attach(self._pitotHeatOn, 5, 7, 5, 6)
536
537 self._parking = gtk.Label("PARKING")
538 table.attach(self._parking, 7, 8, 5, 6)
539
540 self._gearsDown = gtk.Label("GEARS DOWN")
541 table.attach(self._gearsDown, 8, 10, 5, 6)
542
543 self._spoilersArmed = gtk.Label("SPOILERS ARMED")
544 table.attach(self._spoilersArmed, 10, 12, 5, 6)
545
546 (label, self._spoilersExtension) = self._createLabeledEntry("Spoilers:", 3)
547 table.attach(label, 0, 1, 6, 7)
548 table.attach(self._spoilersExtension, 1, 2, 6, 7)
549
550 (label, self._windSpeed) = self._createLabeledEntry("Wind speed:", 3)
551 table.attach(label, 2, 3, 6, 7)
552 table.attach(self._windSpeed, 3, 4, 6, 7)
553
554 (label, self._windDirection) = self._createLabeledEntry("Wind from:", 3)
555 table.attach(label, 4, 5, 6, 7)
556 table.attach(self._windDirection, 5, 6, 6, 7)
557
558 frameAlignment.add(table)
559
560 dataFrame.add(frameAlignment)
561
562 self._setData()
563
564 return dataFrame
565
566 def _setData(self, aircraftState = None):
567 """Set the data.
568
569 If aircraftState is None, everything will be set to its default."""
570 if aircraftState is None:
571 self._timestamp.set_text("--:--:--")
572 self._paused.set_sensitive(False)
573 self._trickMode.set_sensitive(False)
574 self._overspeed.set_sensitive(False)
575 self._stalled.set_sensitive(False)
576 self._onTheGround.set_sensitive(False)
577 self._zfw.set_text("-")
578 self._grossWeight.set_text("-")
579 self._heading.set_text("-")
580 self._pitch.set_text("-")
581 self._bank.set_text("-")
582 self._vs.set_text("-")
583 self._ias.set_text("-")
584 self._mach.set_text("-")
585 self._groundSpeed.set_text("-")
586 self._radioAltitude.set_text("-")
587 self._altitude.set_text("-")
588 self._gLoad.set_text("-")
589 self._flapsSet.set_text("-")
590 self._flaps.set_text("-")
591 self._altimeter.set_text("-")
592 self._squawk.set_text("-")
593 self._nav1.set_text("-")
594 self._nav2.set_text("-")
595 self._fuel.set_text("-")
596 self._n1.set_text("-")
597 self._reverser.set_text("-")
598 self._navLightsOn.set_sensitive(False)
599 self._antiCollisionLightsOn.set_sensitive(False)
600 self._strobeLightsOn.set_sensitive(False)
601 self._landingLightsOn.set_sensitive(False)
602 self._pitotHeatOn.set_sensitive(False)
603 self._parking.set_sensitive(False)
604 self._gearsDown.set_sensitive(False)
605 self._spoilersArmed.set_sensitive(False)
606 self._spoilersExtension.set_text("-")
607 self._windSpeed.set_text("-")
608 self._windDirection.set_text("-")
609 else:
610 self._timestamp.set_text(time.strftime("%H:%M:%S",
611 time.gmtime(aircraftState.timestamp)))
612 self._paused.set_sensitive(aircraftState.paused)
613 self._trickMode.set_sensitive(aircraftState.trickMode)
614 self._overspeed.set_sensitive(aircraftState.overspeed)
615 self._stalled.set_sensitive(aircraftState.stalled)
616 self._onTheGround.set_sensitive(aircraftState.onTheGround)
617 self._zfw.set_text("%.0f" % (aircraftState.zfw,))
618 self._grossWeight.set_text("%.0f" % (aircraftState.grossWeight,))
619 self._heading.set_text("%03.0f" % (aircraftState.heading,))
620 self._pitch.set_text("%.0f" % (aircraftState.pitch,))
621 self._bank.set_text("%.0f" % (aircraftState.bank,))
622 self._vs.set_text("%.0f" % (aircraftState.vs,))
623 self._ias.set_text("%.0f" % (aircraftState.ias,))
624 self._mach.set_text("%.2f" % (aircraftState.mach,))
625 self._groundSpeed.set_text("%.0f" % (aircraftState.groundSpeed,))
626 self._radioAltitude.set_text("%.0f" % (aircraftState.radioAltitude,))
627 self._altitude.set_text("%.0f" % (aircraftState.altitude,))
628 self._gLoad.set_text("%.2f" % (aircraftState.gLoad,))
629 self._flapsSet.set_text("%.0f" % (aircraftState.flapsSet,))
630 self._flaps.set_text("%.0f" % (aircraftState.flaps,))
631 self._altimeter.set_text("%.0f" % (aircraftState.altimeter,))
632 self._squawk.set_text(aircraftState.squawk)
633 self._nav1.set_text(aircraftState.nav1)
634 self._nav2.set_text(aircraftState.nav2)
635
636 fuelStr = ""
637 for fuel in aircraftState.fuel:
638 if fuelStr: fuelStr += ", "
639 fuelStr += "%.0f" % (fuel,)
640 self._fuel.set_text(fuelStr)
641
642 if hasattr(aircraftState, "n1"):
643 n1Str = ""
644 for n1 in aircraftState.n1:
645 if n1Str: n1Str += ", "
646 n1Str += "%.0f" % (n1,)
647 elif hasattr(aircraftState, "rpm"):
648 n1Str = ""
649 for rpm in aircraftState.rpm:
650 if n1Str: n1Str += ", "
651 n1Str += "%.0f" % (rpm,)
652 else:
653 n1Str = "-"
654 self._n1.set_text(n1Str)
655
656 reverserStr = ""
657 for reverser in aircraftState.reverser:
658 if reverserStr: reverserStr += ", "
659 reverserStr += "ON" if reverser else "OFF"
660 self._reverser.set_text(reverserStr)
661
662 self._navLightsOn.set_sensitive(aircraftState.navLightsOn)
663 self._antiCollisionLightsOn.set_sensitive(aircraftState.antiCollisionLightsOn)
664 self._strobeLightsOn.set_sensitive(aircraftState.strobeLightsOn)
665 self._landingLightsOn.set_sensitive(aircraftState.landingLightsOn)
666 self._pitotHeatOn.set_sensitive(aircraftState.pitotHeatOn)
667 self._parking.set_sensitive(aircraftState.parking)
668 self._gearsDown.set_sensitive(aircraftState.gearsDown)
669 self._spoilersArmed.set_sensitive(aircraftState.spoilersArmed)
670 self._spoilersExtension.set_text("%.0f" % (aircraftState.spoilersExtension,))
671 self._windSpeed.set_text("%.0f" % (aircraftState.windSpeed,))
672 self._windDirection.set_text("%03.0f" % (aircraftState.windDirection,))
673
674 def _buildLogFrame(self):
675 """Build the frame for the log."""
676 logFrame = gtk.Frame(label = "Log")
677
678 frameAlignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
679
680 frameAlignment.set_padding(padding_top = 4, padding_bottom = 10,
681 padding_left = 16, padding_right = 16)
682
683 logFrame.add(frameAlignment)
684
685 logScroller = gtk.ScrolledWindow()
686 self._logView = gtk.TextView()
687 self._logView.set_editable(False)
688 logScroller.add(self._logView)
689
690 logBox = gtk.VBox()
691 logBox.pack_start(logScroller, True, True, 0)
692 logBox.set_size_request(-1, 200)
693
694 frameAlignment.add(logBox)
695
696 return logFrame
697
698 def _writeLog(self, msg):
699 """Write the given message to the log."""
700 buffer = self._logView.get_buffer()
701 buffer.insert(buffer.get_end_iter(), msg)
702 self._logView.scroll_mark_onscreen(buffer.get_insert())
703
704 def _quit(self, what = None):
705 """Quit from the application."""
706 self._statusIcon.destroy()
707 return gtk.main_quit()
708
709class TrackerStatusIcon(gtk.StatusIcon):
710 def __init__(self):
711 gtk.StatusIcon.__init__(self)
712 menu = '''
713 <ui>
714 <menubar name="Menubar">
715 <menu action="Menu">
716 <menuitem action="Search"/>
717 <menuitem action="Preferences"/>
718 <separator/>
719 <menuitem action="About"/>
720 </menu>
721 </menubar>
722 </ui>
723 '''
724 actions = [
725 ('Menu', None, 'Menu'),
726 ('Search', None, '_Search...', None, 'Search files with MetaTracker', self.on_activate),
727 ('Preferences', gtk.STOCK_PREFERENCES, '_Preferences...', None, 'Change MetaTracker preferences', self.on_preferences),
728 ('About', gtk.STOCK_ABOUT, '_About...', None, 'About MetaTracker', self.on_about)]
729 ag = gtk.ActionGroup('Actions')
730 ag.add_actions(actions)
731 self.manager = gtk.UIManager()
732 self.manager.insert_action_group(ag, 0)
733 self.manager.add_ui_from_string(menu)
734 self.menu = self.manager.get_widget('/Menubar/Menu/About').props.parent
735 search = self.manager.get_widget('/Menubar/Menu/Search')
736 search.get_children()[0].set_markup('<b>_Search...</b>')
737 search.get_children()[0].set_use_underline(True)
738 search.get_children()[0].set_use_markup(True)
739 #search.get_children()[1].set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_MENU)
740 self.set_from_stock(gtk.STOCK_FIND)
741 self.set_tooltip('Tracker Desktop Search')
742 self.set_visible(True)
743 self.connect('activate', self.on_activate)
744 self.connect('popup-menu', self.on_popup_menu)
745
746 def on_activate(self, data):
747 os.spawnlpe(os.P_NOWAIT, 'tracker-search-tool', os.environ)
748
749 def on_popup_menu(self, status, button, time):
750 self.menu.popup(None, None, None, button, time)
751
752 def on_preferences(self, data):
753 print 'preferences'
754
755 def on_about(self, data):
756 dialog = gtk.AboutDialog()
757 dialog.set_name('Tracker')
758 dialog.set_version('0.5.0')
759 dialog.set_comments('A desktop indexing and search tool')
760 dialog.set_website('www.freedesktop.org/Tracker')
761 dialog.run()
762 dialog.destroy()
Note: See TracBrowser for help on using the repository browser.