source: src/mlx/gui/gui.py@ 51:f0f99ac21935

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

Fleet retrieval and gate selection works, started new connection handling and the fsuipc simulator

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