source: src/mlx/gui/gui.py@ 50:19d4098081e8

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

Added environment variable to display the more natural size of the window

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