def initialize(self): """ GUI initialization method """ self.currentlog={ 'filename': None, 'age': 0, 'manual': False, } # Create info bar self.setupInfoBar() # Tray icon setup self.trayicon=TrayIcon('pixmaps/lotroassist.png',self.metadata['APP_NAME'],menu=self.widgets.mnuTrayIcon,action=self.trayIconActivate) # Load Application preferences self.preferences.load() # Move info window self.widgets.winInfoBar.move(self.preferences.general.infobarposx,self.preferences.general.infobarposy) # Log window setup self.setupLogWindow() self.setupTextStyles() self.widgets.scrConsole.add(self.widgets.txtLog) # Show log message for app initialization self.logMessage('Initialising LOTROAssist','internal') # Set preferences self.logMessage('Loading preferences','internal') self.setPreferences() # Dialog module initialization self.dialogs=DialogFactory(self.widgets.winMain) # Load Application plugins self.logMessage('Initialising Plugin system','internal') self.plugins=PluginLoader() self.loadPlugins() # Add main loop callback gobject.timeout_add(self.preferences.log.delay,self.mainLoop,priority=gobject.PRIORITY_LOW) # Test def validatetext(val): if val != 'HOLA': return "<b>Error</b> de texto" return None def validateint(val): if int(val) != 10: return "<b>Error</b> de entero" return None def validatebool(val): if not bool(val): return "<b>Error</b> de booleano" return None def validatefloat(val): if float(val) != 10.10: return "<b>Error</b> de float" return None def validatedate(val): from datetime import datetime if datetime(2010,10,21)>val: return "<b>Error</b> de fecha" return None self.widgets.dbentTest.add_validators(validatetext,validatebool) self.widgets.dbcmbTest.add_validators(validatetext,validatebool) self.widgets.dbspnTest.add_validators(validateint,validatefloat) self.widgets.dbchkTest.add_validators(validatebool) self.widgets.dbreentTest.add_validators(validatetext) self.widgets.dbdtpTest.add_validators(validatedate) self.widgets.dbcalTest.add_validators(validatedate) print 'Entry',self.ui.dbentTest print 'ComboBox',self.ui.dbcmbTest print 'SpinButton',self.ui.dbspnTest print 'CheckButton',self.ui.dbchkTest print 'RegExpEntry',self.ui.dbreentTest print 'DatePicker',self.ui.dbdtpTest print 'Calendar',self.ui.dbcalTest
def __init__(self,guifiles=[],configfile=None,mainapp=True,env=None,controlled_quit=True,dialogs=True,splash=True,debug=False,localedir='locale',pixmapsdir='pixmaps',disablenotifsys=False,forceinternalnotifsys=False,**kwargs): """ Class constructor """ # Setting up variables self.__guifiles=guifiles self.__main_app=mainapp self.__debug=debug self.__splashscreen=None self.APP_DIR=os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe().f_back))) self.PIXMAPS_DIR=self.APP_DIR + '/' + pixmapsdir self.LOCALE_DIR=self.APP_DIR + '/' + localedir # Main app initialization if mainapp: # Setup glib application name glib.set_application_name(self.metadata['APP_CODENAME']) # Set up exception handler if this is the main app self.excepthandler=_ExceptionHandler(catch_all=debug) # If controlled quit is enabled set a handler self.excepthandler.set_handler(KeyboardInterrupt,self.__control_c_handler) # Initialize notifications system if disablenotifsys: # No graphical notifications system. Fallback to dummy notification system self.notifsys=notifsystem.DummyNotificationSystem(self.metadata['APP_NAME']) else: if not forceinternalnotifsys and evogtk.HAS_PYNOTIFY: # Use PyNotify as notification system self.notifsys=notifsystem.PyNotifyNotificationSystem(self.metadata['APP_NAME']) else: # Use internal notification system self.notifsys=notifsystem.NotificationSystem(self.metadata['APP_NAME']) if splash: self.show_splash() # Create GtkBuilder instance self.__builder_instance=gtk.Builder() # Setup internationalization gettext.textdomain(self.metadata['APP_CODENAME']) gettext.bindtextdomain(self.metadata['APP_CODENAME'], self.LOCALE_DIR) gtk.glade.bindtextdomain(self.metadata['APP_CODENAME'], self.LOCALE_DIR) gtk.glade.textdomain(self.metadata['APP_CODENAME']) self.__builder_instance.set_translation_domain(self.metadata['APP_CODENAME']) # Load GUI files for guifile in guifiles: self.__builder_instance.add_from_file(self.APP_DIR + '/' + guifile) # Prepare widgets for easy access self.widgets=GUIWidgets(self.__builder_instance) # Load default widget access shortcuts self.ui=WidgetAccess(self.widgets) # Connect GUI signals self.__connect_signals() # Load shortcuts helper self.shortcuts=ShortcutsHelper(self) # Set application environment if env: self.set_environment(env) # Create preferences helper if needed if self.metadata.has_key('APP_PREFERENCES'): self.preferences=_PreferencesHelper(self.metadata['APP_PREFERENCES'],'%s/settings.conf' % self.metadata['APP_NAME'],self.ui) # Load Application preferences self.preferences.load() else: self.preferences=None # Load current icon theme self.icon_theme=gtk.icon_theme_get_default() # Set current task mode to unknown self.__current_task_mode=None # Set class as initialized self.__initialised=True self.__quit=False # Dialog module initialization if dialogs: self.dialogs=DialogFactory(self,self.widgets.winMain) # Call application initialization method passing extra parameters self.initialize(**kwargs)
class LOTROAssistClass(GUIClass): """ LOTROAssist main class """ # Application metadata metadata={ 'APP_NAME': 'LOTROAssist', 'APP_CODENAME': 'lotroassist', 'APP_VERSION': '0.1', 'APP_DESC': 'Lord Of The Rings Online Assistant Application', 'APP_COPYRIGHT': '(C) 2010 Oliver Gutiérrez <*****@*****.**>', 'APP_WEBSITE': 'http://www.evosistemas.com', 'APP_PREFERENCES': { 'general': { 'closetotray': ('bool',['chkCloseToTray'],True), 'alwaysshowtrayicon': ('bool',['chkAlwaysShowTrayIcon'],True), 'shownotifications': ('bool',['chkShowNotifications'],True), 'datadir': ('str',['fcbDataDir'],'./'), 'monitorlogs': ('bool',['tactMonitorLogs'],False), 'showinfobar': ('bool',['tactShowInfoBar'],False), 'showconsole': ('bool',['tactShowConsole'],False), 'infobarposx': ('int',[],0), 'infobarposy': ('int',[],0), }, 'log': { 'forcesimplelog': ('bool',['chkForceSimpleLog'],False), 'delay': ('int',['spnLogDelay'],20), 'normalcolor': ('str',['cbNormalColor'],'#000000'), 'internalcolor': ('str',['cbInternalColor'],'#00FF00'), 'logopencolor': ('str',['cbLogOpenColor'],'#0000FF'), 'plugincolor': ('str',['cbPluginColor'],'#FF0000'), }, } } def initialize(self): """ GUI initialization method """ self.currentlog={ 'filename': None, 'age': 0, 'manual': False, } # Create info bar self.setupInfoBar() # Tray icon setup self.trayicon=TrayIcon('pixmaps/lotroassist.png',self.metadata['APP_NAME'],menu=self.widgets.mnuTrayIcon,action=self.trayIconActivate) # Load Application preferences self.preferences.load() # Move info window self.widgets.winInfoBar.move(self.preferences.general.infobarposx,self.preferences.general.infobarposy) # Log window setup self.setupLogWindow() self.setupTextStyles() self.widgets.scrConsole.add(self.widgets.txtLog) # Show log message for app initialization self.logMessage('Initialising LOTROAssist','internal') # Set preferences self.logMessage('Loading preferences','internal') self.setPreferences() # Dialog module initialization self.dialogs=DialogFactory(self.widgets.winMain) # Load Application plugins self.logMessage('Initialising Plugin system','internal') self.plugins=PluginLoader() self.loadPlugins() # Add main loop callback gobject.timeout_add(self.preferences.log.delay,self.mainLoop,priority=gobject.PRIORITY_LOW) # Test def validatetext(val): if val != 'HOLA': return "<b>Error</b> de texto" return None def validateint(val): if int(val) != 10: return "<b>Error</b> de entero" return None def validatebool(val): if not bool(val): return "<b>Error</b> de booleano" return None def validatefloat(val): if float(val) != 10.10: return "<b>Error</b> de float" return None def validatedate(val): from datetime import datetime if datetime(2010,10,21)>val: return "<b>Error</b> de fecha" return None self.widgets.dbentTest.add_validators(validatetext,validatebool) self.widgets.dbcmbTest.add_validators(validatetext,validatebool) self.widgets.dbspnTest.add_validators(validateint,validatefloat) self.widgets.dbchkTest.add_validators(validatebool) self.widgets.dbreentTest.add_validators(validatetext) self.widgets.dbdtpTest.add_validators(validatedate) self.widgets.dbcalTest.add_validators(validatedate) print 'Entry',self.ui.dbentTest print 'ComboBox',self.ui.dbcmbTest print 'SpinButton',self.ui.dbspnTest print 'CheckButton',self.ui.dbchkTest print 'RegExpEntry',self.ui.dbreentTest print 'DatePicker',self.ui.dbdtpTest print 'Calendar',self.ui.dbcalTest def setupInfoBar(self): """ Setups the information bar """ infobar=FloatingWindow(title='LOTROAssist info bar',color='#999',rounded=True,alwaysontop=True,dragable=True,maximize=evogtk.MAXIMIZE_HORIZONTAL) hbxinfobar=gtk.HBox(spacing=5) infobar.add(hbxinfobar) # Add info bar to widget access self.widgets.add_widget(infobar,'winInfoBar') self.widgets.add_widget(hbxinfobar,'hbxInfoBar') def setupLogWindow(self): """ Setup the log window """ # Check if we use GTK Sourceview for log widget if evogtk.EVOGTK_HAS_GTKSOURCEVIEW and not self.preferences.log.forcesimplelog: # Use GTK Sourceview import gtksourceview2 buffer=gtksourceview2.Buffer() view=gtksourceview2.View(buffer) view.set_show_line_numbers(True) view.set_show_line_marks(True) else: # Use GTK TextView buffer=gtk.TextBuffer() view=gtk.TextView(buffer) # Show log view and set basic parameters self.widgets.add_widget(view,'txtLog') view.set_editable(False) view.set_cursor_visible(False) view.show() def setupTextStyles(self): """ Setup text styles used by application """ buffer=self.widgets.txtLog.get_buffer() tools.newTextTag({'name': 'normal','foreground': self.preferences.log.normalcolor},buffer) tools.newTextTag({'name': 'internal','foreground': self.preferences.log.internalcolor, 'weight': 700},buffer) tools.newTextTag({'name': 'logopen','foreground': self.preferences.log.logopencolor, 'weight': 700},buffer) tools.newTextTag({'name': 'plugin','foreground': self.preferences.log.plugincolor, 'weight': 700},buffer) def openLogFile(self,widget): """ Manually select the logfile to load """ # Open file selection dialog logfile=self.dialogs.fileSelDialog('open','Log File Selection',False,self.preferences.general.datadir) # Check if has selected a log file if logfile[0]: logfile=logfile[0][0] self.currentlog={ 'filename': logfile, 'age': 0, 'fd': open(logfile,'r'), 'manual': True, } # Show desktop notification self.showNotification('Opening selected log: %s' % logfile,True) self.logMessage('Opened Log File: %s' % logfile,'logopen') self.ui.tlbtMonitorLogs=False # Do a burst read of log self.burstRead() def quitApplication(self,widget,event=None): """ Application quit callback """ if self.preferences.general.closetotray and widget == self.widgets.winMain: self.trayIconActivate() else: if self.dialogs.msgDialog('¿Do you want to exit LOTRO Assist?', 'question'): self.savePreferences() self.unloadPlugins() self.quit() return True def showPreferences(self,widget=None): """ Show preferences dialog """ self.widgets.winPreferences.show() def showAbout(self,widget=None): """ Show about dialog """ self.dialogs.aboutDialog(self.metadata) def trayIconActivate(self,widget=None): """ Toggles main window visible status """ if self.widgets.winMain.get_property('visible'): self.widgets.winMain.hide() self.trayicon.show() else: self.widgets.winMain.show() self.trayicon.set_visible(self.preferences.general.alwaysshowtrayicon) def savePreferences(self,widget=None,other=None): """ Save application preferences """ self.widgets.winPreferences.hide() self.preferences.general.infobarposx,self.preferences.general.infobarposy=self.widgets.winInfoBar.get_position() self.preferences.save() self.setPreferences() return True def setPreferences(self): """ Set preferences """ # Tray Icon preferences self.trayicon.set_visible(self.preferences.general.alwaysshowtrayicon) def mainLoop(self): """ Starts main log process loop """ # Check if a new log has been created if self.ui.tlbtMonitorLogs: self.checkLogFiles() if self.currentlog.has_key('fd'): # Check new lines in current log line=self.currentlog['fd'].readline().strip() if line: # Call new line callback self.newLogLine(line) # Return true for loop repeat return True def toggleConsole(self,widget,event=None): """ Toggle log monitoring """ if widget==self.widgets.winConsole: self.preferences.general.showconsole=False else: self.preferences.general.showconsole=widget.get_active() if self.preferences.general.showconsole: self.widgets.winConsole.show() else: self.widgets.winConsole.hide() return True def toggleInfoBar(self,widget,event=None): """ Toggle log monitoring """ if widget==self.widgets.winInfoBar: self.preferences.general.showinfobar=False else: self.preferences.general.showinfobar=widget.get_active() if self.preferences.general.showinfobar: self.widgets.winInfoBar.show_all() else: self.widgets.winInfoBar.hide() return True def toggleMonitorLogs(self,widget): """ Toggle log monitoring """ self.preferences.general.monitorlogs=widget.get_active() self.currentlog['manual']=not self.preferences.general.monitorlogs def checkLogFiles(self): """ Check if new log files has been created and replaces current by the new one """ logage=self.currentlog['age'] logfile=self.currentlog['filename'] # Get last log filename files=os.listdir(self.preferences.general.datadir) for file in files: filename=file.split('.') if len(filename)==2 and filename[1]=='txt': fileage=os.stat('%s/%s' % (self.preferences.general.datadir,file))[8] if logage<=fileage: logfile='%s/%s' % (self.preferences.general.datadir,file) logage=fileage # Check if current log is the newest one if logfile != self.currentlog['filename']: # Close older log and open the new one if self.currentlog.has_key('fd'): self.currentlog['fd'].close() self.currentlog={ 'filename': logfile, 'age': logage, 'fd': open(logfile,'r'), 'manual': False, } # Show desktop notification self.showNotification('Opened Log File: %s' % logfile,True) self.logMessage('Opened Log File: %s' % logfile,'logopen') # Do a burst read of log self.burstRead() def burstRead(self): """ Burst read of a log file """ notif=self.preferences.general.shownotifications self.preferences.general.shownotifications=False self.logMessage('Doing burst read of lofgile %s' % self.currentlog['filename'],'internal') lines=self.currentlog['fd'].readlines() for line in lines: tools.processPendingEvents() self.newLogLine(line.strip(),burst=True) self.preferences.general.shownotifications=notif self.logMessage('Burst read of lofgile %s finished for a total of %s lines' % (self.currentlog['filename'],len(lines)),'internal') def showNotification(self,msg,statusbar=False,icon=None): """ Show notification """ if statusbar: self.ui.stbMain=msg if self.preferences.general.shownotifications: self.trayicon.blink() self.notifsys.queue_msg(msg=msg,color='#444444',icon=icon) def logMessage(self,msg,tag='normal'): """ Log Message function """ # TODO: lotroassist: limit log buffer to X lines/bytes logbuffer=self.widgets.txtLog.get_buffer() iter=logbuffer.get_end_iter() logbuffer.insert_with_tags_by_name(iter,msg + '\n', tag) iter=logbuffer.get_end_iter() self.widgets.txtLog.scroll_to_iter(iter,0) def newLogLine(self,line,burst=False): """ New line callback """ # Pass the line to plugins for plugin in self.plugins.loaded_plugins(): result=self.plugins.get_plugin_instance(plugin).newLine(line) if result and evogtk.EVOGTK_HAS_GTKSOURCEVIEW: # TODO: lotroassist: Line marking with custom icons in log pass # Add line to main log window if not burst: self.logMessage(line) def loadPlugins(self): """ Load plugins """ self.logMessage('Loading plugins','internal') pluginlist=self.plugins.plugin_list() self.logMessage('Found %s plugins' % len(pluginlist),'plugin') for plugin in pluginlist: self.plugins.load_plugin(plugin,env={'maingui':self}) # Add plugin to interface if needed pluginclass=self.plugins.get_plugin_instance(plugin) if pluginclass.metadata.has_key('PLUGIN_DOCK'): pluginclass.widgets.vbxMain.unparent() pluginlabel=gtk.Label(pluginclass.metadata['PLUGIN_NAME']) if pluginclass.metadata['PLUGIN_DOCK']=='main': self.widgets.ntbMain.append_page(pluginclass.widgets.vbxMain,pluginlabel) elif pluginclass.metadata['PLUGIN_DOCK']=='lists': self.widgets.ntbLists.append_page(pluginclass.widgets.vbxMain,pluginlabel) elif pluginclass.metadata['PLUGIN_DOCK']=='console': self.widgets.ntbConsole.append_page(pluginclass.widgets.vbxMain,pluginlabel) elif pluginclass.metadata['PLUGIN_DOCK']=='status': self.widgets.hbxInfoBar.pack_end(pluginclass.widgets.vbxMain,False,False) else: raise Exception('Plugin %s have no position for GUI docking' % plugin) self.logMessage('\tPlugin %s v%s initialized' % (pluginclass.metadata['PLUGIN_NAME'],pluginclass.metadata['PLUGIN_VERSION']),'plugin') def unloadPlugins(self): """ Unload Plugins """ for plugin in self.plugins.loaded_plugins(): self.plugins.unload_plugin(plugin)
class GUIClass(object): """ **GUI helper base class** *This class will allow you to start the application* .. note:: You always want to subclass this class. There are some methods you would like to redefine such as initialize .. code-block:: python :emphasize-lines: 1,2 class MyAppClass(GUIClass): pass """ # Application metadata metadata={ 'APP_NAME': 'EVOGTK Project', 'APP_CODENAME': 'evogtkproject', 'APP_VERSION': '1.0', 'APP_DESC': 'EVOGTK application project', 'APP_COPYRIGHT': '(C) 2010 Oliver Gutiérrez <*****@*****.**>', 'APP_WEBSITE': 'http://www.evosistemas.com', } # Task modes TASKS_MODES={ evogtk.TASK_MODE_INITIAL: { 'enable': [], 'disable': [], 'show': [], 'hide': [], 'activate': [], 'deactivate': [], 'callback': None }, } def __init__(self,guifiles=[],configfile=None,mainapp=True,env=None,controlled_quit=True,dialogs=True,splash=True,debug=False,localedir='locale',pixmapsdir='pixmaps',disablenotifsys=False,forceinternalnotifsys=False,**kwargs): """ Class constructor """ # Setting up variables self.__guifiles=guifiles self.__main_app=mainapp self.__debug=debug self.__splashscreen=None self.APP_DIR=os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe().f_back))) self.PIXMAPS_DIR=self.APP_DIR + '/' + pixmapsdir self.LOCALE_DIR=self.APP_DIR + '/' + localedir # Main app initialization if mainapp: # Setup glib application name glib.set_application_name(self.metadata['APP_CODENAME']) # Set up exception handler if this is the main app self.excepthandler=_ExceptionHandler(catch_all=debug) # If controlled quit is enabled set a handler self.excepthandler.set_handler(KeyboardInterrupt,self.__control_c_handler) # Initialize notifications system if disablenotifsys: # No graphical notifications system. Fallback to dummy notification system self.notifsys=notifsystem.DummyNotificationSystem(self.metadata['APP_NAME']) else: if not forceinternalnotifsys and evogtk.HAS_PYNOTIFY: # Use PyNotify as notification system self.notifsys=notifsystem.PyNotifyNotificationSystem(self.metadata['APP_NAME']) else: # Use internal notification system self.notifsys=notifsystem.NotificationSystem(self.metadata['APP_NAME']) if splash: self.show_splash() # Create GtkBuilder instance self.__builder_instance=gtk.Builder() # Setup internationalization gettext.textdomain(self.metadata['APP_CODENAME']) gettext.bindtextdomain(self.metadata['APP_CODENAME'], self.LOCALE_DIR) gtk.glade.bindtextdomain(self.metadata['APP_CODENAME'], self.LOCALE_DIR) gtk.glade.textdomain(self.metadata['APP_CODENAME']) self.__builder_instance.set_translation_domain(self.metadata['APP_CODENAME']) # Load GUI files for guifile in guifiles: self.__builder_instance.add_from_file(self.APP_DIR + '/' + guifile) # Prepare widgets for easy access self.widgets=GUIWidgets(self.__builder_instance) # Load default widget access shortcuts self.ui=WidgetAccess(self.widgets) # Connect GUI signals self.__connect_signals() # Load shortcuts helper self.shortcuts=ShortcutsHelper(self) # Set application environment if env: self.set_environment(env) # Create preferences helper if needed if self.metadata.has_key('APP_PREFERENCES'): self.preferences=_PreferencesHelper(self.metadata['APP_PREFERENCES'],'%s/settings.conf' % self.metadata['APP_NAME'],self.ui) # Load Application preferences self.preferences.load() else: self.preferences=None # Load current icon theme self.icon_theme=gtk.icon_theme_get_default() # Set current task mode to unknown self.__current_task_mode=None # Set class as initialized self.__initialised=True self.__quit=False # Dialog module initialization if dialogs: self.dialogs=DialogFactory(self,self.widgets.winMain) # Call application initialization method passing extra parameters self.initialize(**kwargs) def __setattr__(self,name,value): """ Set attribute method overload for protecting of class specific attributes """ # Check if we are trying to set a protected property if name not in ['widgets','ui','preferences','__notifications'] or not self.__dict__.has_key('_GUIClass__initialised'): return super(GUIClass,self).__setattr__(name,value) else: raise Exception(_('EVOGTK: Setting to %s property is not allowed') % name) def __connect_signals(self): """ Connects the GUI signals """ # Add default handlers to callbacks defaulthandlerlist=['gtk_widget_show','gtk_widget_hide','gtk_widget_grab_focus','gtk_widget_destroy','gtk_true','gtk_false','gtk_main_quit'] for handler in defaulthandlerlist: if not vars(self).has_key(handler): vars(self)[handler]=vars(defaulthandlers)[handler] # Connect signals self.__builder_instance.connect_signals(self) def __control_c_handler(self,*args,**kwargs): """ Catches when the user uses Ctrl+C to finish application and launchs the quit method """ self.quit(userbreak=True) def show_splash(self,splashimg='splash.png',seconds=3): """ Shows an splash screen using an image """ if not self.__debug: splash=gtk.Window(type=gtk.WINDOW_POPUP) splash.set_resizable(False) splash.set_keep_above(True) splash.set_position(gtk.WIN_POS_CENTER) splash.add(gtk.image_new_from_file(self.PIXMAPS_DIR + '/' + splashimg)) splash.show_all() self.__splashscreen=(splash,seconds) def hide_splash(self,callback=None): """ Hides the splash screen """ if self.__splashscreen: self.__splashscreen[0].destroy() if callback: callback() def show_mainwindow(self,window): """ Show main window ant take care about splash screen hiding """ if self.__debug: window.show() else: gobject.timeout_add_seconds(self.__splashscreen[1],self.hide_splash,window.show) def set_gui_task(self,mode): """ Setups GUI for an specified task """ if self.TASKS_MODES.has_key(mode): self.__current_task_mode=mode task=self.TASKS_MODES[mode] # Disable widgets for widget in task['disable']: self.widgets.get_widget(widget).set_sensitive(False) # Hide widgets for widget in task['hide']: self.widgets.get_widget(widget).hide() # Enable widgets for widget in task['enable']: self.widgets.get_widget(widget).set_sensitive(True) # Show widgets for widget in task['show']: self.widgets.get_widget(widget).show() # Activate widgets for widget in task['activate']: self.widgets.get_widget(widget).set_active(True) # Deactivate widgets for widget in task['deactivate']: self.widgets.get_widget(widget).set_active(False) # Call specific callback if task['callback']: getattr(self,task['callback'])() else: raise Exception(_('EVOGTK: Trying to setup unspecified GUI task mode: %s') % mode) def get_gui_task(self): """ Returns current GUI task mode """ return self.__current_task_mode def initialize(self): """ Dummy initialize method for application """ pass def set_environment(self,env,strict=True): """ Set application environment if needed """ for var in env: if self.__dict__.has_key(var): if not strict: print _('EVOGTK: Setting member %s from environment initialization to an already set property or method') % var if strict: raise Exception(_('EVOGTK: Setting member %s from environment initialization to an already set property or method') % var) elif var in ['widgets','ui','preferences','trayicon','notify']: raise Exception(_('EVOGTK: Setting varable %s from environment initialization to a protected property is not allowed') % var) self.__dict__[var]=env[var] def run(self): """ Launch main application loop """ if self.__main_app: EVOGTK_SETTINGS=gtk.settings_get_default() EVOGTK_SETTINGS.set_property('gtk-button-images',True) gtk.main() else: raise Exception(_('EVOGTK: Trying to run an application that is not a main application')) def quit(self,userbreak=False,status=0): """ Finish application :param userbreak: Allow user to use Ctrl-C to finish application :type userbreak: bool :param status: Specifies which status code is returned on application quit :type status: int .. warning:: This method will try to quit application, and will wait for all threads to finish. So if you have threads working, application will remain stopped while waiting. """ # Call application unload callback self.unload() # Quit application if not self.__quit: self.__quit=(True,userbreak) # Check if there are pending tasks if self.__main_app and threadtasks.pending_tasks()>1: # Generate the progress bar align=gtk.Alignment(xalign=0.5, yalign=0.5, xscale=1, yscale=1) align.set_padding(25,25,25,25) progress=gtk.ProgressBar() progress.set_text(_('Waiting for pending tasks to finish')) align.add(progress) # Callback for not quit until all pending tasks are finished def wait_for_tasks(progress): if threadtasks.pending_tasks()==1: if gtk.main_level(): gtk.main_quit() sys.exit(status) progress.pulse() return True # Set all widgets to insensitive status self.widgets.disable_toplevels() # Callback for timeout on waiting for tasks gobject.timeout_add(100,wait_for_tasks,progress,priority=gobject.PRIORITY_HIGH) # Launch a permanent notification if self.notifsys: self.notifsys.queue_custom(align,permanent=True) # If the user used CTRL+C to quit, show message and run gtk loop to make application responsive if userbreak: print _('EVOGTK: Finishing tasks, please wait or press CTRL+C again to finish') gtk.main() elif self.__main_app: if gtk.main_level(): gtk.main_quit() sys.exit(status) else: if not self.__quit[1]: print _('EVOGTK: Finishing tasks, please wait or press CTRL+C again to finish') gtk.main() def unload(self): """ Dummy cleanup method for application finish .. note:: This method should be overloaded mostly for use in plugins """ pass def debug_status(self): """ Returns debug setting """ return self.__debug #=========================================================================== # Default application event handlers #=========================================================================== def showAbout(self,widget=None): """ Show default about dialog """ self.dialogs.aboutDialog(self.metadata) return True def quitApplication(self,widget,event=None): """ Show default quit dialog """ if self.dialogs.msgDialog(_('¿Do you want to exit %s?') % self.metadata['APP_NAME'], 'question',default=gtk.RESPONSE_NO): self.savePreferences() self.quit() return True def showPreferences(self,widget=None): """ Show preferences dialog """ if self.widgets.widget_exists('winPreferences'): if self.dialogs.openDialog(self.widgets.winPreferences, close=True)==1: self.savePreferences() def savePreferences(self,widget=None): """ Save application preferences """ if self.preferences: self.preferences.save() return True