# The main file for the GUI from statusicon import StatusIcon from statusbar import Statusbar from update import Updater from mlx.gui.common import * import mlx.const as const import mlx.fs as fs import mlx.flight as flight import mlx.logger as logger import mlx.acft as acft import mlx.web as web import time import threading import sys acftTypes = [ ("Boeing 737-600", const.AIRCRAFT_B736), ("Boeing 737-700", const.AIRCRAFT_B737), ("Boeing 737-800", const.AIRCRAFT_B738), ("Bombardier Dash 8-Q400", const.AIRCRAFT_DH8D), ("Boeing 737-300", const.AIRCRAFT_B733), ("Boeing 737-400", const.AIRCRAFT_B734), ("Boeing 737-500", const.AIRCRAFT_B735), ("Boeing 767-200", const.AIRCRAFT_B762), ("Boeing 767-300", const.AIRCRAFT_B763), ("Bombardier CRJ200", const.AIRCRAFT_CRJ2), ("Fokker 70", const.AIRCRAFT_F70), ("Lisunov Li-2", const.AIRCRAFT_DC3), ("Tupolev Tu-134", const.AIRCRAFT_T134), ("Tupolev Tu-154", const.AIRCRAFT_T154), ("Yakovlev Yak-40", const.AIRCRAFT_YK40) ] class GUI(fs.ConnectionListener): """The main GUI class.""" def __init__(self, programDirectory, config): """Construct the GUI.""" gobject.threads_init() self._programDirectory = programDirectory self._config = config self._connecting = False self._connected = False self._logger = logger.Logger(output = self) self._flight = None self._simulator = None self._stdioLock = threading.Lock() self._stdioText = "" self._stdioAfterNewLine = True self.webHandler = web.Handler() self.webHandler.start() self.toRestart = False def build(self, iconDirectory): """Build the GUI.""" window = gtk.Window() window.set_title("MAVA Logger X " + const.VERSION) window.set_icon_from_file(os.path.join(iconDirectory, "logo.ico")) window.connect("delete-event", lambda a, b: self.hideMainWindow()) window.connect("window-state-event", self._handleMainWindowState) mainVBox = gtk.VBox() window.add(mainVBox) setupFrame = self._buildSetupFrame() setupFrame.set_border_width(8) mainVBox.pack_start(setupFrame, False, False, 0) dataFrame = self._buildDataFrame() dataFrame.set_border_width(8) mainVBox.pack_start(dataFrame, False, False, 0) logFrame = self._buildLogFrame() logFrame.set_border_width(8) mainVBox.pack_start(logFrame, True, True, 0) mainVBox.pack_start(gtk.HSeparator(), False, False, 0) self._statusbar = Statusbar() mainVBox.pack_start(self._statusbar, False, False, 0) window.show_all() self._mainWindow = window self._statusIcon = StatusIcon(iconDirectory, self) def run(self): """Run the GUI.""" if self._config.autoUpdate: self._updater = Updater(self, self._programDirectory, self._config.updateURL, self._mainWindow) self._updater.start() gtk.main() if self._flight is not None: simulator = self._flight.simulator simulator.stopMonitoring() simulator.disconnect() def connected(self, fsType, descriptor): """Called when we have connected to the simulator.""" self._connected = True self._logger.untimedMessage("Connected to the simulator %s" % (descriptor,)) gobject.idle_add(self._statusbar.updateConnection, self._connecting, self._connected) def disconnected(self): """Called when we have disconnected from the simulator.""" self._connected = False self._logger.untimedMessage("Disconnected from the simulator") gobject.idle_add(self._statusbar.updateConnection, self._connecting, self._connected) def write(self, msg): """Write the given message to the log.""" gobject.idle_add(self._writeLog, msg) def check(self, flight, aircraft, logger, oldState, state): """Update the data.""" gobject.idle_add(self._setData, state) def resetFlightStatus(self): """Reset the status of the flight.""" self._statusbar.resetFlightStatus() self._statusIcon.resetFlightStatus() def setStage(self, stage): """Set the stage of the flight.""" gobject.idle_add(self._setStage, stage) def _setStage(self, stage): """Set the stage of the flight.""" self._statusbar.setStage(stage) self._statusIcon.setStage(stage) def setRating(self, rating): """Set the rating of the flight.""" gobject.idle_add(self._setRating, rating) def _setRating(self, rating): """Set the rating of the flight.""" self._statusbar.setRating(rating) self._statusIcon.setRating(rating) def setNoGo(self, reason): """Set the rating of the flight to No-Go with the given reason.""" gobject.idle_add(self._setNoGo, reason) def _setNoGo(self, reason): """Set the rating of the flight.""" self._statusbar.setNoGo(reason) self._statusIcon.setNoGo(reason) def _handleMainWindowState(self, window, event): """Hande a change in the state of the window""" iconified = gdk.WindowState.ICONIFIED if pygobject \ else gdk.WINDOW_STATE_ICONIFIED if (event.changed_mask&iconified)!=0 and (event.new_window_state&iconified)!=0: self.hideMainWindow(savePosition = False) def hideMainWindow(self, savePosition = True): """Hide the main window and save its position.""" if savePosition: (self._mainWindowX, self._mainWindowY) = \ self._mainWindow.get_window().get_root_origin() else: self._mainWindowX = self._mainWindowY = None self._mainWindow.hide() self._statusIcon.mainWindowHidden() return True def showMainWindow(self): """Show the main window at its former position.""" if self._mainWindowX is not None and self._mainWindowY is not None: self._mainWindow.move(self._mainWindowX, self._mainWindowY) self._mainWindow.show() self._mainWindow.deiconify() self._statusIcon.mainWindowShown() def toggleMainWindow(self): """Toggle the main window.""" if self._mainWindow.get_visible(): self.hideMainWindow() else: self.showMainWindow() def restart(self): """Quit and restart the application.""" self.toRestart = True self._quit() def flushStdIO(self): """Flush any text to the standard error that could not be logged.""" if self._stdioText: sys.__stderr__.write(self._stdioText) def writeStdIO(self, text): """Write the given text into standard I/O log.""" with self._stdioLock: self._stdioText += text gobject.idle_add(self._writeStdIO) def _writeStdIO(self): """Perform the real writing.""" with self._stdioLock: text = self._stdioText self._stdioText = "" if not text: return lines = text.splitlines() if text[-1]=="\n": text = "" else: text = lines[-1] lines = lines[:-1] for line in lines: if self._stdioAfterNewLine: line = "[STDIO] " + line self._writeLog(line + "\n") self._stdioAfterNewLine = True if text: if self._stdioAfterNewLine: text = "[STDIO] " + text self._writeLog(text) self._stdioAfterNewLine = False def _connectToggled(self, button): """Callback for the connection button.""" if self._connectButton.get_active(): self._logger.reset() self._flight = flight.Flight(self._logger, self) acftListModel = self._acftList.get_model() self._flight.aircraftType = \ acftListModel[self._acftList.get_active()][1] self._flight.aircraft = acft.Aircraft.create(self._flight) self._flight.aircraft._checkers.append(self) self._flight.cruiseAltitude = self._flSpinButton.get_value_as_int() * 100 self._flight.zfw = self._zfwSpinButton.get_value_as_int() if self._simulator is None: self._simulator = fs.createSimulator(const.SIM_MSFS9, self) self._flight.simulator = self._simulator self._connecting = True self._simulator.connect(self._flight.aircraft) self._simulator.startMonitoring() else: self.resetFlightStatus() self._connecting = False self._simulator.stopMonitoring() self._simulator.disconnect() self._flight = None self._statusbar.updateConnection(self._connecting, self._connected) def _buildSetupFrame(self): """Build the setup frame.""" setupFrame = gtk.Frame(label = "Setup") frameAlignment = gtk.Alignment(xalign = 0.5) frameAlignment.set_padding(padding_top = 4, padding_bottom = 10, padding_left = 16, padding_right = 16) setupFrame.add(frameAlignment) setupBox = gtk.HBox() frameAlignment.add(setupBox) # self._fs9Button = gtk.RadioButton(label = "FS9") # self._fs9Button.set_tooltip_text("Use MS Flight Simulator 2004") # setupBox.pack_start(self._fs9Button, False, False, 0) # self._fsxButton = gtk.RadioButton(group = self._fs9Button, label = "FSX") # self._fsxButton.set_tooltip_text("Use MS Flight Simulator X") # setupBox.pack_start(self._fsxButton, False, False, 0) # setupBox.pack_start(gtk.VSeparator(), False, False, 8) alignment = gtk.Alignment(yalign = 0.5) alignment.set_padding(padding_top = 0, padding_bottom = 0, padding_left = 0, padding_right = 16) alignment.add(gtk.Label("Aicraft:")) setupBox.pack_start(alignment, False, False, 0) acftListModel = gtk.ListStore(str, int) for (name, type) in acftTypes: acftListModel.append([name, type]) self._acftList = gtk.ComboBox(model = acftListModel) renderer_text = gtk.CellRendererText() self._acftList.pack_start(renderer_text, True) self._acftList.add_attribute(renderer_text, "text", 0) self._acftList.set_active(0) self._acftList.set_tooltip_text("Select the type of the aircraft used for the flight.") setupBox.pack_start(self._acftList, True, True, 0) setupBox.pack_start(gtk.VSeparator(), False, False, 8) alignment = gtk.Alignment(yalign = 0.5) alignment.set_padding(padding_top = 0, padding_bottom = 0, padding_left = 0, padding_right = 16) alignment.add(gtk.Label("Cruise FL:")) setupBox.pack_start(alignment, False, False, 0) self._flSpinButton = gtk.SpinButton() self._flSpinButton.set_increments(step = 10, page = 100) self._flSpinButton.set_range(min = 0, max = 500) self._flSpinButton.set_value(240) self._flSpinButton.set_tooltip_text("The cruise flight level.") self._flSpinButton.set_numeric(True) setupBox.pack_start(self._flSpinButton, False, False, 0) setupBox.pack_start(gtk.VSeparator(), False, False, 8) alignment = gtk.Alignment(yalign = 0.5) alignment.set_padding(padding_top = 0, padding_bottom = 0, padding_left = 0, padding_right = 16) alignment.add(gtk.Label("ZFW:")) setupBox.pack_start(alignment, False, False, 0) self._zfwSpinButton = gtk.SpinButton() self._zfwSpinButton.set_increments(step = 100, page = 1000) self._zfwSpinButton.set_range(min = 0, max = 500000) self._zfwSpinButton.set_value(50000) self._zfwSpinButton.set_tooltip_text("The Zero Fuel Weight for the flight in kgs") self._zfwSpinButton.set_numeric(True) setupBox.pack_start(self._zfwSpinButton, False, False, 0) setupBox.pack_start(gtk.VSeparator(), False, False, 8) self._connectButton = gtk.ToggleButton(label = "Connect") self._connectButton.set_tooltip_text("Push to connect to Flight Simulator and start a new flight.\n" "Push again to disconnect from FS.") self._connectButton.connect("toggled", self._connectToggled) setupBox.pack_start(self._connectButton, False, False, 0) setupBox.pack_start(gtk.VSeparator(), False, False, 8) self._quitButton = gtk.Button(label = "Quit") self._quitButton.set_tooltip_text("Quit the program.") self._quitButton.connect("clicked", self._quit) setupBox.pack_start(self._quitButton, False, False, 0) return setupFrame def _createLabeledEntry(self, label, width = 8, xalign = 1.0): """Create a labeled entry. Return a tuple consisting of: - the box - the entry.""" alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5, xscale = 1.0) alignment.set_padding(padding_top = 0, padding_bottom = 0, padding_left = 0, padding_right = 16) alignment.add(gtk.Label(label)) entry = gtk.Entry() entry.set_editable(False) entry.set_width_chars(width) entry.set_max_length(width) entry.set_alignment(xalign) return (alignment, entry) def _buildDataFrame(self): """Build the frame for the data.""" dataFrame = gtk.Frame(label = "Data") frameAlignment = gtk.Alignment(xscale = 1.0, yscale = 1.0) frameAlignment.set_padding(padding_top = 4, padding_bottom = 10, padding_left = 16, padding_right = 16) table = gtk.Table(rows = 7, columns = 12) table.set_homogeneous(False) table.set_row_spacings(4) table.set_col_spacings(8) (label, self._timestamp) = self._createLabeledEntry("Time:") table.attach(label, 0, 1, 0, 1) table.attach(self._timestamp, 1, 2, 0, 1) self._paused = gtk.Label("PAUSED") table.attach(self._paused, 2, 4, 0, 1) self._trickMode = gtk.Label("TRICKMODE") table.attach(self._trickMode, 4, 6, 0, 1, xoptions = 0) self._overspeed = gtk.Label("OVERSPEED") table.attach(self._overspeed, 6, 8, 0, 1) self._stalled = gtk.Label("STALLED") table.attach(self._stalled, 8, 10, 0, 1) self._onTheGround = gtk.Label("ONTHEGROUND") table.attach(self._onTheGround, 10, 12, 0, 1) (label, self._zfw) = self._createLabeledEntry("ZFW:", 6) table.attach(label, 0, 1, 1, 2) table.attach(self._zfw, 1, 2, 1, 2) (label, self._grossWeight) = self._createLabeledEntry("Weight:", 6) table.attach(label, 2, 3, 1, 2) table.attach(self._grossWeight, 3, 4, 1, 2) (label, self._heading) = self._createLabeledEntry("Heading:", 3) table.attach(label, 4, 5, 1, 2) table.attach(self._heading, 5, 6, 1, 2) (label, self._pitch) = self._createLabeledEntry("Pitch:", 3) table.attach(label, 6, 7, 1, 2) table.attach(self._pitch, 7, 8, 1, 2) (label, self._bank) = self._createLabeledEntry("Bank:", 3) table.attach(label, 8, 9, 1, 2) table.attach(self._bank, 9, 10, 1, 2) (label, self._vs) = self._createLabeledEntry("VS:", 5) table.attach(label, 10, 11, 1, 2) table.attach(self._vs, 11, 12, 1, 2) (label, self._ias) = self._createLabeledEntry("IAS:", 4) table.attach(label, 0, 1, 2, 3) table.attach(self._ias, 1, 2, 2, 3) (label, self._mach) = self._createLabeledEntry("Mach:", 4) table.attach(label, 2, 3, 2, 3) table.attach(self._mach, 3, 4, 2, 3) (label, self._groundSpeed) = self._createLabeledEntry("GS:", 4) table.attach(label, 4, 5, 2, 3) table.attach(self._groundSpeed, 5, 6, 2, 3) (label, self._radioAltitude) = self._createLabeledEntry("Radio alt.:", 6) table.attach(label, 6, 7, 2, 3) table.attach(self._radioAltitude, 7, 8, 2, 3) (label, self._altitude) = self._createLabeledEntry("Altitude:", 6) table.attach(label, 8, 9, 2, 3) table.attach(self._altitude, 9, 10, 2, 3) (label, self._gLoad) = self._createLabeledEntry("G-Load:", 4) table.attach(label, 10, 11, 2, 3) table.attach(self._gLoad, 11, 12, 2, 3) (label, self._flapsSet) = self._createLabeledEntry("Flaps set:", 2) table.attach(label, 0, 1, 3, 4) table.attach(self._flapsSet, 1, 2, 3, 4) (label, self._flaps) = self._createLabeledEntry("Flaps:", 2) table.attach(label, 2, 3, 3, 4) table.attach(self._flaps, 3, 4, 3, 4) (label, self._altimeter) = self._createLabeledEntry("Altimeter:", 4) table.attach(label, 4, 5, 3, 4) table.attach(self._altimeter, 5, 6, 3, 4) (label, self._squawk) = self._createLabeledEntry("Squawk:", 4) table.attach(label, 6, 7, 3, 4) table.attach(self._squawk, 7, 8, 3, 4) (label, self._nav1) = self._createLabeledEntry("NAV1:", 5) table.attach(label, 8, 9, 3, 4) table.attach(self._nav1, 9, 10, 3, 4) (label, self._nav2) = self._createLabeledEntry("NAV2:", 5) table.attach(label, 10, 11, 3, 4) table.attach(self._nav2, 11, 12, 3, 4) (label, self._fuel) = self._createLabeledEntry("Fuel:", 40, xalign = 0.0) table.attach(label, 0, 1, 4, 5) table.attach(self._fuel, 1, 4, 4, 5) (label, self._n1) = self._createLabeledEntry("N1/RPM:", 20, xalign = 0.0) table.attach(label, 4, 5, 4, 5) table.attach(self._n1, 5, 8, 4, 5) (label, self._reverser) = self._createLabeledEntry("Reverser:", 20, xalign = 0.0) table.attach(label, 8, 9, 4, 5) table.attach(self._reverser, 9, 12, 4, 5) self._navLightsOn = gtk.Label("NAV") table.attach(self._navLightsOn, 0, 1, 5, 6) self._antiCollisionLightsOn = gtk.Label("ANTICOLLISION") table.attach(self._antiCollisionLightsOn, 1, 3, 5, 6) self._strobeLightsOn = gtk.Label("STROBE") table.attach(self._strobeLightsOn, 3, 4, 5, 6) self._landingLightsOn = gtk.Label("LANDING") table.attach(self._landingLightsOn, 4, 5, 5, 6) self._pitotHeatOn = gtk.Label("PITOT HEAT") table.attach(self._pitotHeatOn, 5, 7, 5, 6) self._parking = gtk.Label("PARKING") table.attach(self._parking, 7, 8, 5, 6) self._gearsDown = gtk.Label("GEARS DOWN") table.attach(self._gearsDown, 8, 10, 5, 6) self._spoilersArmed = gtk.Label("SPOILERS ARMED") table.attach(self._spoilersArmed, 10, 12, 5, 6) (label, self._spoilersExtension) = self._createLabeledEntry("Spoilers:", 3) table.attach(label, 0, 1, 6, 7) table.attach(self._spoilersExtension, 1, 2, 6, 7) (label, self._windSpeed) = self._createLabeledEntry("Wind speed:", 3) table.attach(label, 2, 3, 6, 7) table.attach(self._windSpeed, 3, 4, 6, 7) (label, self._windDirection) = self._createLabeledEntry("Wind from:", 3) table.attach(label, 4, 5, 6, 7) table.attach(self._windDirection, 5, 6, 6, 7) frameAlignment.add(table) dataFrame.add(frameAlignment) self._setData() return dataFrame def _setData(self, aircraftState = None): """Set the data. If aircraftState is None, everything will be set to its default.""" if aircraftState is None: self._timestamp.set_text("--:--:--") self._paused.set_sensitive(False) self._trickMode.set_sensitive(False) self._overspeed.set_sensitive(False) self._stalled.set_sensitive(False) self._onTheGround.set_sensitive(False) self._zfw.set_text("-") self._grossWeight.set_text("-") self._heading.set_text("-") self._pitch.set_text("-") self._bank.set_text("-") self._vs.set_text("-") self._ias.set_text("-") self._mach.set_text("-") self._groundSpeed.set_text("-") self._radioAltitude.set_text("-") self._altitude.set_text("-") self._gLoad.set_text("-") self._flapsSet.set_text("-") self._flaps.set_text("-") self._altimeter.set_text("-") self._squawk.set_text("-") self._nav1.set_text("-") self._nav2.set_text("-") self._fuel.set_text("-") self._n1.set_text("-") self._reverser.set_text("-") self._navLightsOn.set_sensitive(False) self._antiCollisionLightsOn.set_sensitive(False) self._strobeLightsOn.set_sensitive(False) self._landingLightsOn.set_sensitive(False) self._pitotHeatOn.set_sensitive(False) self._parking.set_sensitive(False) self._gearsDown.set_sensitive(False) self._spoilersArmed.set_sensitive(False) self._spoilersExtension.set_text("-") self._windSpeed.set_text("-") self._windDirection.set_text("-") else: self._timestamp.set_text(time.strftime("%H:%M:%S", time.gmtime(aircraftState.timestamp))) self._paused.set_sensitive(aircraftState.paused) self._trickMode.set_sensitive(aircraftState.trickMode) self._overspeed.set_sensitive(aircraftState.overspeed) self._stalled.set_sensitive(aircraftState.stalled) self._onTheGround.set_sensitive(aircraftState.onTheGround) self._zfw.set_text("%.0f" % (aircraftState.zfw,)) self._grossWeight.set_text("%.0f" % (aircraftState.grossWeight,)) self._heading.set_text("%03.0f" % (aircraftState.heading,)) self._pitch.set_text("%.0f" % (aircraftState.pitch,)) self._bank.set_text("%.0f" % (aircraftState.bank,)) self._vs.set_text("%.0f" % (aircraftState.vs,)) self._ias.set_text("%.0f" % (aircraftState.ias,)) self._mach.set_text("%.2f" % (aircraftState.mach,)) self._groundSpeed.set_text("%.0f" % (aircraftState.groundSpeed,)) self._radioAltitude.set_text("%.0f" % (aircraftState.radioAltitude,)) self._altitude.set_text("%.0f" % (aircraftState.altitude,)) self._gLoad.set_text("%.2f" % (aircraftState.gLoad,)) self._flapsSet.set_text("%.0f" % (aircraftState.flapsSet,)) self._flaps.set_text("%.0f" % (aircraftState.flaps,)) self._altimeter.set_text("%.0f" % (aircraftState.altimeter,)) self._squawk.set_text(aircraftState.squawk) self._nav1.set_text(aircraftState.nav1) self._nav2.set_text(aircraftState.nav2) fuelStr = "" for fuel in aircraftState.fuel: if fuelStr: fuelStr += ", " fuelStr += "%.0f" % (fuel,) self._fuel.set_text(fuelStr) if hasattr(aircraftState, "n1"): n1Str = "" for n1 in aircraftState.n1: if n1Str: n1Str += ", " n1Str += "%.0f" % (n1,) elif hasattr(aircraftState, "rpm"): n1Str = "" for rpm in aircraftState.rpm: if n1Str: n1Str += ", " n1Str += "%.0f" % (rpm,) else: n1Str = "-" self._n1.set_text(n1Str) reverserStr = "" for reverser in aircraftState.reverser: if reverserStr: reverserStr += ", " reverserStr += "ON" if reverser else "OFF" self._reverser.set_text(reverserStr) self._navLightsOn.set_sensitive(aircraftState.navLightsOn) self._antiCollisionLightsOn.set_sensitive(aircraftState.antiCollisionLightsOn) self._strobeLightsOn.set_sensitive(aircraftState.strobeLightsOn) self._landingLightsOn.set_sensitive(aircraftState.landingLightsOn) self._pitotHeatOn.set_sensitive(aircraftState.pitotHeatOn) self._parking.set_sensitive(aircraftState.parking) self._gearsDown.set_sensitive(aircraftState.gearsDown) self._spoilersArmed.set_sensitive(aircraftState.spoilersArmed) self._spoilersExtension.set_text("%.0f" % (aircraftState.spoilersExtension,)) self._windSpeed.set_text("%.0f" % (aircraftState.windSpeed,)) self._windDirection.set_text("%03.0f" % (aircraftState.windDirection,)) def _buildLogFrame(self): """Build the frame for the log.""" logFrame = gtk.Frame(label = "Log") frameAlignment = gtk.Alignment(xscale = 1.0, yscale = 1.0) frameAlignment.set_padding(padding_top = 4, padding_bottom = 10, padding_left = 16, padding_right = 16) logFrame.add(frameAlignment) logScroller = gtk.ScrolledWindow() self._logView = gtk.TextView() self._logView.set_editable(False) logScroller.add(self._logView) logBox = gtk.VBox() logBox.pack_start(logScroller, True, True, 0) logBox.set_size_request(-1, 200) frameAlignment.add(logBox) return logFrame def _writeLog(self, msg): """Write the given message to the log.""" buffer = self._logView.get_buffer() buffer.insert(buffer.get_end_iter(), msg) self._logView.scroll_mark_onscreen(buffer.get_insert()) def _quit(self, what = None): """Quit from the application.""" self._statusIcon.destroy() return gtk.main_quit() class TrackerStatusIcon(gtk.StatusIcon): def __init__(self): gtk.StatusIcon.__init__(self) menu = ''' ''' actions = [ ('Menu', None, 'Menu'), ('Search', None, '_Search...', None, 'Search files with MetaTracker', self.on_activate), ('Preferences', gtk.STOCK_PREFERENCES, '_Preferences...', None, 'Change MetaTracker preferences', self.on_preferences), ('About', gtk.STOCK_ABOUT, '_About...', None, 'About MetaTracker', self.on_about)] ag = gtk.ActionGroup('Actions') ag.add_actions(actions) self.manager = gtk.UIManager() self.manager.insert_action_group(ag, 0) self.manager.add_ui_from_string(menu) self.menu = self.manager.get_widget('/Menubar/Menu/About').props.parent search = self.manager.get_widget('/Menubar/Menu/Search') search.get_children()[0].set_markup('_Search...') search.get_children()[0].set_use_underline(True) search.get_children()[0].set_use_markup(True) #search.get_children()[1].set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_MENU) self.set_from_stock(gtk.STOCK_FIND) self.set_tooltip('Tracker Desktop Search') self.set_visible(True) self.connect('activate', self.on_activate) self.connect('popup-menu', self.on_popup_menu) def on_activate(self, data): os.spawnlpe(os.P_NOWAIT, 'tracker-search-tool', os.environ) def on_popup_menu(self, status, button, time): self.menu.popup(None, None, None, button, time) def on_preferences(self, data): print 'preferences' def on_about(self, data): dialog = gtk.AboutDialog() dialog.set_name('Tracker') dialog.set_version('0.5.0') dialog.set_comments('A desktop indexing and search tool') dialog.set_website('www.freedesktop.org/Tracker') dialog.run() dialog.destroy()