source: src/mlx/gui/gui.py@ 49:1b5b3d34dd84

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

Implemented busy state notification

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