source: src/mlx/gui/gui.py@ 46:43e46847479a

Last change on this file since 46:43e46847479a was 46:43e46847479a, checked in by István Váradi <locvais@…>, 13 years ago

Some further enhancements on the GUI

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 self._connectButton.set_tooltip_text("Push to connect to Flight Simulator and start a new flight.\n"
381 "Push again to disconnect from FS.")
382
383 self._connectButton.connect("toggled", self._connectToggled)
384
385 setupBox.pack_start(self._connectButton, False, False, 0)
386
387 setupBox.pack_start(gtk.VSeparator(), False, False, 8)
388
389 self._quitButton = gtk.Button(label = "_Quit", use_underline = True)
390 self._quitButton.set_can_default(True)
391 self._quitButton.set_tooltip_text("Quit the program.")
392
393 self._quitButton.connect("clicked", self._quit)
394
395 setupBox.pack_start(self._quitButton, False, False, 0)
396
397 return setupFrame
398
399 def _createLabeledEntry(self, label, width = 8, xalign = 1.0):
400 """Create a labeled entry.
401
402 Return a tuple consisting of:
403 - the box
404 - the entry."""
405
406 alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5, xscale = 1.0)
407 alignment.set_padding(padding_top = 0, padding_bottom = 0,
408 padding_left = 0, padding_right = 16)
409 alignment.add(gtk.Label(label))
410
411 entry = gtk.Entry()
412 entry.set_editable(False)
413 entry.set_width_chars(width)
414 entry.set_max_length(width)
415 entry.set_alignment(xalign)
416
417 return (alignment, entry)
418
419 def _buildDataFrame(self):
420 """Build the frame for the data."""
421 dataFrame = gtk.Frame(label = "Data")
422
423 frameAlignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
424
425 frameAlignment.set_padding(padding_top = 4, padding_bottom = 10,
426 padding_left = 16, padding_right = 16)
427
428 table = gtk.Table(rows = 7, columns = 12)
429 table.set_homogeneous(False)
430 table.set_row_spacings(4)
431 table.set_col_spacings(8)
432
433 (label, self._timestamp) = self._createLabeledEntry("Time:")
434 table.attach(label, 0, 1, 0, 1)
435 table.attach(self._timestamp, 1, 2, 0, 1)
436
437 self._paused = gtk.Label("PAUSED")
438 table.attach(self._paused, 2, 4, 0, 1)
439
440 self._trickMode = gtk.Label("TRICKMODE")
441 table.attach(self._trickMode, 4, 6, 0, 1, xoptions = 0)
442
443 self._overspeed = gtk.Label("OVERSPEED")
444 table.attach(self._overspeed, 6, 8, 0, 1)
445
446 self._stalled = gtk.Label("STALLED")
447 table.attach(self._stalled, 8, 10, 0, 1)
448
449 self._onTheGround = gtk.Label("ONTHEGROUND")
450 table.attach(self._onTheGround, 10, 12, 0, 1)
451
452 (label, self._zfw) = self._createLabeledEntry("ZFW:", 6)
453 table.attach(label, 0, 1, 1, 2)
454 table.attach(self._zfw, 1, 2, 1, 2)
455
456 (label, self._grossWeight) = self._createLabeledEntry("Weight:", 6)
457 table.attach(label, 2, 3, 1, 2)
458 table.attach(self._grossWeight, 3, 4, 1, 2)
459
460 (label, self._heading) = self._createLabeledEntry("Heading:", 3)
461 table.attach(label, 4, 5, 1, 2)
462 table.attach(self._heading, 5, 6, 1, 2)
463
464 (label, self._pitch) = self._createLabeledEntry("Pitch:", 3)
465 table.attach(label, 6, 7, 1, 2)
466 table.attach(self._pitch, 7, 8, 1, 2)
467
468 (label, self._bank) = self._createLabeledEntry("Bank:", 3)
469 table.attach(label, 8, 9, 1, 2)
470 table.attach(self._bank, 9, 10, 1, 2)
471
472 (label, self._vs) = self._createLabeledEntry("VS:", 5)
473 table.attach(label, 10, 11, 1, 2)
474 table.attach(self._vs, 11, 12, 1, 2)
475
476 (label, self._ias) = self._createLabeledEntry("IAS:", 4)
477 table.attach(label, 0, 1, 2, 3)
478 table.attach(self._ias, 1, 2, 2, 3)
479
480 (label, self._mach) = self._createLabeledEntry("Mach:", 4)
481 table.attach(label, 2, 3, 2, 3)
482 table.attach(self._mach, 3, 4, 2, 3)
483
484 (label, self._groundSpeed) = self._createLabeledEntry("GS:", 4)
485 table.attach(label, 4, 5, 2, 3)
486 table.attach(self._groundSpeed, 5, 6, 2, 3)
487
488 (label, self._radioAltitude) = self._createLabeledEntry("Radio alt.:", 6)
489 table.attach(label, 6, 7, 2, 3)
490 table.attach(self._radioAltitude, 7, 8, 2, 3)
491
492 (label, self._altitude) = self._createLabeledEntry("Altitude:", 6)
493 table.attach(label, 8, 9, 2, 3)
494 table.attach(self._altitude, 9, 10, 2, 3)
495
496 (label, self._gLoad) = self._createLabeledEntry("G-Load:", 4)
497 table.attach(label, 10, 11, 2, 3)
498 table.attach(self._gLoad, 11, 12, 2, 3)
499
500 (label, self._flapsSet) = self._createLabeledEntry("Flaps set:", 2)
501 table.attach(label, 0, 1, 3, 4)
502 table.attach(self._flapsSet, 1, 2, 3, 4)
503
504 (label, self._flaps) = self._createLabeledEntry("Flaps:", 2)
505 table.attach(label, 2, 3, 3, 4)
506 table.attach(self._flaps, 3, 4, 3, 4)
507
508 (label, self._altimeter) = self._createLabeledEntry("Altimeter:", 4)
509 table.attach(label, 4, 5, 3, 4)
510 table.attach(self._altimeter, 5, 6, 3, 4)
511
512 (label, self._squawk) = self._createLabeledEntry("Squawk:", 4)
513 table.attach(label, 6, 7, 3, 4)
514 table.attach(self._squawk, 7, 8, 3, 4)
515
516 (label, self._nav1) = self._createLabeledEntry("NAV1:", 5)
517 table.attach(label, 8, 9, 3, 4)
518 table.attach(self._nav1, 9, 10, 3, 4)
519
520 (label, self._nav2) = self._createLabeledEntry("NAV2:", 5)
521 table.attach(label, 10, 11, 3, 4)
522 table.attach(self._nav2, 11, 12, 3, 4)
523
524 (label, self._fuel) = self._createLabeledEntry("Fuel:", 40, xalign = 0.0)
525 table.attach(label, 0, 1, 4, 5)
526 table.attach(self._fuel, 1, 4, 4, 5)
527
528 (label, self._n1) = self._createLabeledEntry("N1/RPM:", 20, xalign = 0.0)
529 table.attach(label, 4, 5, 4, 5)
530 table.attach(self._n1, 5, 8, 4, 5)
531
532 (label, self._reverser) = self._createLabeledEntry("Reverser:", 20, xalign = 0.0)
533 table.attach(label, 8, 9, 4, 5)
534 table.attach(self._reverser, 9, 12, 4, 5)
535
536 self._navLightsOn = gtk.Label("NAV")
537 table.attach(self._navLightsOn, 0, 1, 5, 6)
538
539 self._antiCollisionLightsOn = gtk.Label("ANTICOLLISION")
540 table.attach(self._antiCollisionLightsOn, 1, 3, 5, 6)
541
542 self._strobeLightsOn = gtk.Label("STROBE")
543 table.attach(self._strobeLightsOn, 3, 4, 5, 6)
544
545 self._landingLightsOn = gtk.Label("LANDING")
546 table.attach(self._landingLightsOn, 4, 5, 5, 6)
547
548 self._pitotHeatOn = gtk.Label("PITOT HEAT")
549 table.attach(self._pitotHeatOn, 5, 7, 5, 6)
550
551 self._parking = gtk.Label("PARKING")
552 table.attach(self._parking, 7, 8, 5, 6)
553
554 self._gearsDown = gtk.Label("GEARS DOWN")
555 table.attach(self._gearsDown, 8, 10, 5, 6)
556
557 self._spoilersArmed = gtk.Label("SPOILERS ARMED")
558 table.attach(self._spoilersArmed, 10, 12, 5, 6)
559
560 (label, self._spoilersExtension) = self._createLabeledEntry("Spoilers:", 3)
561 table.attach(label, 0, 1, 6, 7)
562 table.attach(self._spoilersExtension, 1, 2, 6, 7)
563
564 (label, self._windSpeed) = self._createLabeledEntry("Wind speed:", 3)
565 table.attach(label, 2, 3, 6, 7)
566 table.attach(self._windSpeed, 3, 4, 6, 7)
567
568 (label, self._windDirection) = self._createLabeledEntry("Wind from:", 3)
569 table.attach(label, 4, 5, 6, 7)
570 table.attach(self._windDirection, 5, 6, 6, 7)
571
572 frameAlignment.add(table)
573
574 dataFrame.add(frameAlignment)
575
576 self._setData()
577
578 return dataFrame
579
580 def _setData(self, aircraftState = None):
581 """Set the data.
582
583 If aircraftState is None, everything will be set to its default."""
584 if aircraftState is None:
585 self._timestamp.set_text("--:--:--")
586 self._paused.set_sensitive(False)
587 self._trickMode.set_sensitive(False)
588 self._overspeed.set_sensitive(False)
589 self._stalled.set_sensitive(False)
590 self._onTheGround.set_sensitive(False)
591 self._zfw.set_text("-")
592 self._grossWeight.set_text("-")
593 self._heading.set_text("-")
594 self._pitch.set_text("-")
595 self._bank.set_text("-")
596 self._vs.set_text("-")
597 self._ias.set_text("-")
598 self._mach.set_text("-")
599 self._groundSpeed.set_text("-")
600 self._radioAltitude.set_text("-")
601 self._altitude.set_text("-")
602 self._gLoad.set_text("-")
603 self._flapsSet.set_text("-")
604 self._flaps.set_text("-")
605 self._altimeter.set_text("-")
606 self._squawk.set_text("-")
607 self._nav1.set_text("-")
608 self._nav2.set_text("-")
609 self._fuel.set_text("-")
610 self._n1.set_text("-")
611 self._reverser.set_text("-")
612 self._navLightsOn.set_sensitive(False)
613 self._antiCollisionLightsOn.set_sensitive(False)
614 self._strobeLightsOn.set_sensitive(False)
615 self._landingLightsOn.set_sensitive(False)
616 self._pitotHeatOn.set_sensitive(False)
617 self._parking.set_sensitive(False)
618 self._gearsDown.set_sensitive(False)
619 self._spoilersArmed.set_sensitive(False)
620 self._spoilersExtension.set_text("-")
621 self._windSpeed.set_text("-")
622 self._windDirection.set_text("-")
623 else:
624 self._timestamp.set_text(time.strftime("%H:%M:%S",
625 time.gmtime(aircraftState.timestamp)))
626 self._paused.set_sensitive(aircraftState.paused)
627 self._trickMode.set_sensitive(aircraftState.trickMode)
628 self._overspeed.set_sensitive(aircraftState.overspeed)
629 self._stalled.set_sensitive(aircraftState.stalled)
630 self._onTheGround.set_sensitive(aircraftState.onTheGround)
631 self._zfw.set_text("%.0f" % (aircraftState.zfw,))
632 self._grossWeight.set_text("%.0f" % (aircraftState.grossWeight,))
633 self._heading.set_text("%03.0f" % (aircraftState.heading,))
634 self._pitch.set_text("%.0f" % (aircraftState.pitch,))
635 self._bank.set_text("%.0f" % (aircraftState.bank,))
636 self._vs.set_text("%.0f" % (aircraftState.vs,))
637 self._ias.set_text("%.0f" % (aircraftState.ias,))
638 self._mach.set_text("%.2f" % (aircraftState.mach,))
639 self._groundSpeed.set_text("%.0f" % (aircraftState.groundSpeed,))
640 self._radioAltitude.set_text("%.0f" % (aircraftState.radioAltitude,))
641 self._altitude.set_text("%.0f" % (aircraftState.altitude,))
642 self._gLoad.set_text("%.2f" % (aircraftState.gLoad,))
643 self._flapsSet.set_text("%.0f" % (aircraftState.flapsSet,))
644 self._flaps.set_text("%.0f" % (aircraftState.flaps,))
645 self._altimeter.set_text("%.0f" % (aircraftState.altimeter,))
646 self._squawk.set_text(aircraftState.squawk)
647 self._nav1.set_text(aircraftState.nav1)
648 self._nav2.set_text(aircraftState.nav2)
649
650 fuelStr = ""
651 for fuel in aircraftState.fuel:
652 if fuelStr: fuelStr += ", "
653 fuelStr += "%.0f" % (fuel,)
654 self._fuel.set_text(fuelStr)
655
656 if hasattr(aircraftState, "n1"):
657 n1Str = ""
658 for n1 in aircraftState.n1:
659 if n1Str: n1Str += ", "
660 n1Str += "%.0f" % (n1,)
661 elif hasattr(aircraftState, "rpm"):
662 n1Str = ""
663 for rpm in aircraftState.rpm:
664 if n1Str: n1Str += ", "
665 n1Str += "%.0f" % (rpm,)
666 else:
667 n1Str = "-"
668 self._n1.set_text(n1Str)
669
670 reverserStr = ""
671 for reverser in aircraftState.reverser:
672 if reverserStr: reverserStr += ", "
673 reverserStr += "ON" if reverser else "OFF"
674 self._reverser.set_text(reverserStr)
675
676 self._navLightsOn.set_sensitive(aircraftState.navLightsOn)
677 self._antiCollisionLightsOn.set_sensitive(aircraftState.antiCollisionLightsOn)
678 self._strobeLightsOn.set_sensitive(aircraftState.strobeLightsOn)
679 self._landingLightsOn.set_sensitive(aircraftState.landingLightsOn)
680 self._pitotHeatOn.set_sensitive(aircraftState.pitotHeatOn)
681 self._parking.set_sensitive(aircraftState.parking)
682 self._gearsDown.set_sensitive(aircraftState.gearsDown)
683 self._spoilersArmed.set_sensitive(aircraftState.spoilersArmed)
684 self._spoilersExtension.set_text("%.0f" % (aircraftState.spoilersExtension,))
685 self._windSpeed.set_text("%.0f" % (aircraftState.windSpeed,))
686 self._windDirection.set_text("%03.0f" % (aircraftState.windDirection,))
687
688 def _buildLogFrame(self):
689 """Build the frame for the log."""
690 logFrame = gtk.Frame(label = "Log")
691
692 frameAlignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
693
694 frameAlignment.set_padding(padding_top = 4, padding_bottom = 10,
695 padding_left = 16, padding_right = 16)
696
697 logFrame.add(frameAlignment)
698
699 logScroller = gtk.ScrolledWindow()
700 self._logView = gtk.TextView()
701 self._logView.set_editable(False)
702 logScroller.add(self._logView)
703
704 logBox = gtk.VBox()
705 logBox.pack_start(logScroller, True, True, 0)
706 logBox.set_size_request(-1, 200)
707
708 frameAlignment.add(logBox)
709
710 return logFrame
711
712 def _writeLog(self, msg):
713 """Write the given message to the log."""
714 buffer = self._logView.get_buffer()
715 buffer.insert(buffer.get_end_iter(), msg)
716 self._logView.scroll_mark_onscreen(buffer.get_insert())
717
718 def _quit(self, what = None):
719 """Quit from the application."""
720 self._statusIcon.destroy()
721 return gtk.main_quit()
722
723 def _notebookPageSwitch(self, notebook, page, page_num):
724 """Called when the current page of the notebook has changed."""
725 if page_num==0:
726 self._wizard.grabDefault()
727 elif page_num==1:
728 self._quitButton.grab_default()
729 else:
730 self._mainWindow.set_default(None)
731
732class TrackerStatusIcon(gtk.StatusIcon):
733 def __init__(self):
734 gtk.StatusIcon.__init__(self)
735 menu = '''
736 <ui>
737 <menubar name="Menubar">
738 <menu action="Menu">
739 <menuitem action="Search"/>
740 <menuitem action="Preferences"/>
741 <separator/>
742 <menuitem action="About"/>
743 </menu>
744 </menubar>
745 </ui>
746 '''
747 actions = [
748 ('Menu', None, 'Menu'),
749 ('Search', None, '_Search...', None, 'Search files with MetaTracker', self.on_activate),
750 ('Preferences', gtk.STOCK_PREFERENCES, '_Preferences...', None, 'Change MetaTracker preferences', self.on_preferences),
751 ('About', gtk.STOCK_ABOUT, '_About...', None, 'About MetaTracker', self.on_about)]
752 ag = gtk.ActionGroup('Actions')
753 ag.add_actions(actions)
754 self.manager = gtk.UIManager()
755 self.manager.insert_action_group(ag, 0)
756 self.manager.add_ui_from_string(menu)
757 self.menu = self.manager.get_widget('/Menubar/Menu/About').props.parent
758 search = self.manager.get_widget('/Menubar/Menu/Search')
759 search.get_children()[0].set_markup('<b>_Search...</b>')
760 search.get_children()[0].set_use_underline(True)
761 search.get_children()[0].set_use_markup(True)
762 #search.get_children()[1].set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_MENU)
763 self.set_from_stock(gtk.STOCK_FIND)
764 self.set_tooltip('Tracker Desktop Search')
765 self.set_visible(True)
766 self.connect('activate', self.on_activate)
767 self.connect('popup-menu', self.on_popup_menu)
768
769 def on_activate(self, data):
770 os.spawnlpe(os.P_NOWAIT, 'tracker-search-tool', os.environ)
771
772 def on_popup_menu(self, status, button, time):
773 self.menu.popup(None, None, None, button, time)
774
775 def on_preferences(self, data):
776 print 'preferences'
777
778 def on_about(self, data):
779 dialog = gtk.AboutDialog()
780 dialog.set_name('Tracker')
781 dialog.set_version('0.5.0')
782 dialog.set_comments('A desktop indexing and search tool')
783 dialog.set_website('www.freedesktop.org/Tracker')
784 dialog.run()
785 dialog.destroy()
Note: See TracBrowser for help on using the repository browser.