source: src/mlx/gui/gui.py@ 47:004e3163bdd8

Last change on this file since 47:004e3163bdd8 was 47:004e3163bdd8, checked in by István Váradi <locvais@…>, 12 years ago

Still further enhancements

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