Beispiel #1
0
    def initialize(self):
        """
        GUI initialization method
        """        
        # Redirect all console output to console log
        sys.stdout = sys.stderr = ConsoleOutputRedirector(self.widgets.txtConsoleLog)
                
        if evogtk.HAS_APPINDICATOR:
            # Initialize app indicator
            self.trayicon=AppIndicator('django-development-console',icon='ddc-indicator',attention_icon='ddc-indicator-attention',menu=self.widgets.mnuIndicator,iconpath=self.PIXMAPS_DIR)
        else:            
            # Fallback to tray icon
            self.trayicon=TrayIcon(self.PIXMAPS_DIR + '/ddc-icon.png',self.metadata['APP_NAME'],menu=self.widgets.mnuIndicator)
            self.trayicon.show()
        
        # Setup console log text styles
        self.setup_text_styles()

        # Setup projects history treeview
        self.projectshistory=TreeViewFactory('list', ['str','str','str','str'], [_('Name'),_('Settings mod.'),_('Port'),_('Path')],treeview=self.widgets.tvProjectsHistory)

        # Setup project files treeview
        self.projectfiles=TreeViewFactory('tree', [['int','str','pixbuf','str']], [_('File')],[0,1],treeview=self.widgets.tvProjectFiles)

        # Setup application list treeview
        self.projectapps=TreeViewFactory('tree', ['str'], [_('Applications')],menu=self.widgets.mnuAppProperties,showmenucheck=self.applications_menu_check,treeview=self.widgets.tvProjectApps)
        self.update_projects_history()

        # Setup settings list treeview
        self.projectsettings=TreeViewFactory('list', ['str','str'], [_('Setting'),_('Value')],treeview=self.widgets.tvProjectSettings)

        # Setup user list treeview
        self.projectusers=TreeViewFactory('list', ['str','str','str','str','bool','bool','bool'], [_('Username'),_('eMail'),_('First name'),_('Last name'),_('Active'),_('Staff'),_('Superuser')],treeview=self.widgets.tvProjectUsers)

        # Initialize SQL textview widgets
        for i in ['Create','Custom','Indexes','Delete']:
            view=generateSourceWidget('sql', highlightline=False, editable=False, visiblecursor=False)
            view.show()
            self.widgets.add_widget(view, 'txtSQL%s' % i)
            self.widgets.get_widget('scrSQL%s' % i).add(view)
            
        # Setup initial task mode
        self.set_gui_task(evogtk.TASK_MODE_INITIAL)

        # Application has been initialized
        self.__app_initialized=True

        # Show main window
        self.show_mainwindow(self.widgets.winMain)
        
        # Open last project if needed
        last='ddc_project_definition-' + self.preferences.general.lastproject
        if self.preferences.general.openlastproject and last and self.preferences.has_section(last):
            data=self.preferences.get_section(last)
            self.load_project(self.preferences.general.lastproject, data['port'], data['path'], data['settingsmod'])
            # Change task mode to active project
            self.set_gui_task(self.TASK_ACTIVEPROJECT)
Beispiel #2
0
    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
Beispiel #3
0
class EVOGTKApp(GUIClass):
    """
    EVOGTK application class
    """
    # Application metadata
    metadata={
        'APP_NAME': _('DDC'),
        'APP_CODENAME': 'ddc',
        'APP_VERSION': '0.5',
        'APP_DESC': _('Django Development Console'),
        'APP_COPYRIGHT': '(C) Oliver Gutiérrez',
        'APP_WEBSITE': 'http://www.evosistemas.com',
        'APP_PREFERENCES': {
            'general': {
                'workspacedir': ('str',['fcbWorkspaceDir'],''),
                'history': ('list',[],[],','),
                'lastproject': ('str',[],''),
                'openlastproject': ('bool',['chkOpenLast'],False),
            },
            'log': {
                'internalcolor': ('str',['clbInternalMessage'],'#000088'),
                'errorcolor': ('str',['clbErrorMessage'],'#880000'),
            }
        }
    }

    # Application task modes
    TASK_SERVERSTOPPED=1
    TASK_SERVERRUNNING=2
    TASK_ACTIVEPROJECT=3

    TASKS_MODES={
        evogtk.TASK_MODE_INITIAL: {
            'enable': [],
            'disable': ['actStopServer','actStartServer','actRestartServer','actOpenBrowser','actCloseProject','actSyncDB','actValidate','actCleanup','actCreateUser'],
            'show': [],
            'hide': [],
            'activate': [],
            'deactivate': [],
            'callback': None
        },
        TASK_ACTIVEPROJECT: {
            'enable': ['actStartServer','actCloseProject','actSyncDB','actValidate','actCleanup','actCreateUser'],
            'disable': [],
            'show': [],
            'hide': [],
            'activate': [],
            'deactivate': [],
            'callback': None
        },
        TASK_SERVERSTOPPED: {
            'enable': ['actStartServer'],
            'disable': ['actStopServer','actRestartServer','actOpenBrowser'],
            'show': [],
            'hide': [],
            'activate': [],
            'deactivate': [],
            'callback': None
        },
        TASK_SERVERRUNNING: {
            'enable': ['actStopServer','actRestartServer','actOpenBrowser'],
            'disable': ['actStartServer'],
            'show': [],
            'hide': [],
            'activate': [],
            'deactivate': [],
            'callback': None
        },
    }

    # Initial values
    __app_initialized=False
    __command_in_progress=False
    currentproject=None
    filemonitor=None

    def initialize(self):
        """
        GUI initialization method
        """        
        # Redirect all console output to console log
        sys.stdout = sys.stderr = ConsoleOutputRedirector(self.widgets.txtConsoleLog)
                
        if evogtk.HAS_APPINDICATOR:
            # Initialize app indicator
            self.trayicon=AppIndicator('django-development-console',icon='ddc-indicator',attention_icon='ddc-indicator-attention',menu=self.widgets.mnuIndicator,iconpath=self.PIXMAPS_DIR)
        else:            
            # Fallback to tray icon
            self.trayicon=TrayIcon(self.PIXMAPS_DIR + '/ddc-icon.png',self.metadata['APP_NAME'],menu=self.widgets.mnuIndicator)
            self.trayicon.show()
        
        # Setup console log text styles
        self.setup_text_styles()

        # Setup projects history treeview
        self.projectshistory=TreeViewFactory('list', ['str','str','str','str'], [_('Name'),_('Settings mod.'),_('Port'),_('Path')],treeview=self.widgets.tvProjectsHistory)

        # Setup project files treeview
        self.projectfiles=TreeViewFactory('tree', [['int','str','pixbuf','str']], [_('File')],[0,1],treeview=self.widgets.tvProjectFiles)

        # Setup application list treeview
        self.projectapps=TreeViewFactory('tree', ['str'], [_('Applications')],menu=self.widgets.mnuAppProperties,showmenucheck=self.applications_menu_check,treeview=self.widgets.tvProjectApps)
        self.update_projects_history()

        # Setup settings list treeview
        self.projectsettings=TreeViewFactory('list', ['str','str'], [_('Setting'),_('Value')],treeview=self.widgets.tvProjectSettings)

        # Setup user list treeview
        self.projectusers=TreeViewFactory('list', ['str','str','str','str','bool','bool','bool'], [_('Username'),_('eMail'),_('First name'),_('Last name'),_('Active'),_('Staff'),_('Superuser')],treeview=self.widgets.tvProjectUsers)

        # Initialize SQL textview widgets
        for i in ['Create','Custom','Indexes','Delete']:
            view=generateSourceWidget('sql', highlightline=False, editable=False, visiblecursor=False)
            view.show()
            self.widgets.add_widget(view, 'txtSQL%s' % i)
            self.widgets.get_widget('scrSQL%s' % i).add(view)
            
        # Setup initial task mode
        self.set_gui_task(evogtk.TASK_MODE_INITIAL)

        # Application has been initialized
        self.__app_initialized=True

        # Show main window
        self.show_mainwindow(self.widgets.winMain)
        
        # Open last project if needed
        last='ddc_project_definition-' + self.preferences.general.lastproject
        if self.preferences.general.openlastproject and last and self.preferences.has_section(last):
            data=self.preferences.get_section(last)
            self.load_project(self.preferences.general.lastproject, data['port'], data['path'], data['settingsmod'])
            # Change task mode to active project
            self.set_gui_task(self.TASK_ACTIVEPROJECT)

    def unload(self):
        """
        Unload application callback
        """
        if self.currentproject:
            self.currentproject.stopserver()

    #===========================================================================
    # GUI event callbacks
    #===========================================================================
    def quitApplication(self,widget,event=None):
        """
        Application quit callback
        """
        if widget == self.widgets.winMain:
            self.ui.actToggleMainWindow=False
        else:
            if self.dialogs.msgDialog(_('Do you want to exit %s?') % self.metadata['APP_NAME'], 'question'):
                self.savePreferences()
                self.quit()
        return True

    def openProject(self,widget=None):
        """
        Open a django project folder
        """
        # Reset open project dialog information
        self.ui.entProjectName =''
        self.ui.spnServerPort = 8000
        self.ui.fcbProjectPath = self.preferences.general.workspacedir
        self.ui.entSettingsMod = 'settings'
        self.widgets.entProjectName.grab_focus()
        # Show open dialog
        while self.dialogs.openDialog(self.widgets.winOpenProject) == 1:
            # Get project information variables
            name=path=self.ui.entProjectName.strip()
            port= int(self.ui.spnServerPort)
            path=self.ui.fcbProjectPath
            settingsmod=self.ui.entSettingsMod.strip()
            # Check if all needed information is OK
            if not name.replace(' ','').isalnum():
                self.dialogs.msgDialog(_('Project name must be an alphanumeric value'),'error')
            else:
                if name and port and path and settingsmod:
                    # Close current project
                    self.closeProject()
                    self.load_project(name,port,path,settingsmod)
                    # Change task mode to active project
                    self.set_gui_task(self.TASK_ACTIVEPROJECT)
                    # Continue when finished loading
                    break
                else:
                    self.dialogs.msgDialog(_('You must fill all the project information fields'),'error')
        # Hide open dialog
        self.widgets.winOpenProject.hide()

    def closeProject(self,widget=None):
        """
        Close current project
        """
        if self.currentproject:
            if self.dialogs.msgDialog(_('Do you want to close current project?'),'question'):
                # Remove project path from python path
                if self.currentproject.path in sys.path:
                    sys.path.remove(self.currentproject.path)
                # Stop django development server
                self.currentproject.stopserver()
                # Remove current project variable
                self.currentproject=None
                # Clear project information treeviews
                self.projectfiles.clear()
                self.projectapps.clear()
                self.projectusers.clear()
                self.projectsettings.clear()
                # Return to initial task mode
                self.set_gui_task(evogtk.TASK_MODE_INITIAL)
                self.widgets.winMain.set_title(_('Django Development Console'))

    def useHistorySettings(self,widget):
        """
        Use selected history row settings into open project dialog fields
        """
        # Get currently selected row
        if self.projectshistory.selected():
            name,settingsmod,port,path=self.projectshistory.selected()        
            self.ui.entProjectName = name
            self.ui.spnServerPort = int(port)
            self.ui.fcbProjectPath = path
            self.ui.entSettingsMod = settingsmod

    def openHistoryProject(self,widget,path,view_column):
        """
        Load selected history project directly
        """
        # Get currently selected row
        if self.projectshistory.selected():
            name,settingsmod,port,path=self.projectshistory.selected()
            # Close current project
            self.closeProject()
            self.load_project(name,port,path,settingsmod)
            # Change task mode to active project
            self.set_gui_task(self.TASK_ACTIVEPROJECT)
            self.widgets.winOpenProject.hide()

    def startServer(self,widget=None):
        """
        Start django development server
        """
        if self.currentproject:
            self.currentproject.runserver()
            self.set_gui_task(self.TASK_SERVERRUNNING)
            gobject.timeout_add(200,self.console_update_loop,priority=gobject.PRIORITY_LOW)
            self.logmsg(_('Django development server started'))
            
    def stopServer(self,widget=None):
        """
        Stop django development server
        """
        if self.currentproject:
            self.currentproject.stopserver()
            self.set_gui_task(self.TASK_SERVERSTOPPED)
            self.logmsg(_('Django development server stopped'))

    def restartServer(self,widget=None):
        """
        Restart django development server
        """
        self.logmsg(_('Restarting django development server'))
        self.stopServer()
        self.startServer()
    
    def syncDB(self,widget=None):
        """
        Synchronize current project database
        """
        if self.currentproject:
            self.run_background_task(self.currentproject.syncdb,_('Synchronizing database'))
    
    def validateModels(self,widget=None):
        """
        Verify project models
        """
        if self.currentproject:
            self.run_background_task(self.currentproject.validate,_('Validating installed models'))
    
    def cleanUp(self,widget=None):
        """
        Clean up database
        """
        if self.currentproject:
            self.run_background_task(self.currentproject.cleanup,_('Cleaning up database'))
    
    def openProjectFile(self,widget,path,view_column):
        """
        Open a project file
        """
        selected=self.projectfiles.selected()
        if selected:
            if selected[0]==0:
                if not widget.row_expanded(path):
                    widget.expand_row(path,False)
                else:
                    widget.collapse_row(path)
            else:
                print "Opening %s" % selected[1]

    def saveConsoleLog(self,widget=None):
        """
        Save log contents into a file
        """
        filename=self.dialogs.fileSelDialog('save', _('Select file to save log text'))
        if filename[0]:
            buf=self.widgets.txtConsoleLog.get_buffer()
            start,end=buf.get_bounds()
            text=buf.get_text(start, end, include_hidden_chars=False)
            fd=open(filename[0][0],'wb')
            fd.write(text)
            fd.close()
            self.logmsg(_('Log contents saved to "%s"') % filename[0][0])
    
    def clearConsoleLog(self,widget=None):
        """
        Clear console log contents
        """
        logbuffer=self.widgets.txtConsoleLog.get_buffer()
        logbuffer.delete(*logbuffer.get_bounds())

    def toggleMainWindow(self,widget=None):
        """
        Toggle main window visibility
        """
        if self.ui.actToggleMainWindow:
            self.widgets.winMain.show()
        else:
            self.widgets.winMain.hide()
            
    def createUser(self,widget=None):
        """
        Create new user
        """
        if self.currentproject:
            while self.dialogs.openDialog(self.widgets.winCreateUser) == 1:
                username=self.ui.entCreateUserName
                password=self.ui.entCreateUserPassword
                passwordconfirm=self.ui.entCreateUserPasswordConfirm
                email=self.ui.entCreateUserEmail
                active=self.ui.chkCreateUserActive
                staff=self.ui.chkCreateUserStaff
                superuser=self.ui.chkCreateUserSuperuser    
                if password != passwordconfirm:
                    self.dialogs.msgDialog(_('Specified passwords do not match'), 'error')
                else:
                    result,msg=self.currentproject.create_user(username,password,email,active,staff,superuser)
                    if not result:
                        self.dialogs.msgDialog(str(msg), 'error')
                    else:
                        self.update_users_information()
                        break
            self.widgets.winCreateUser.hide()
    
    def showSQL(self,widget=None):
        """
        Show SQL for selected application
        """
        appname=self.get_selected_project_app()
        if appname:
            self.ui.txtSQLCreate,self.ui.txtSQLCustom,self.ui.txtSQLIndexes,self.ui.txtSQLDelete = self.currentproject.get_sql(appname)
            self.dialogs.openDialog(self.widgets.winSQL,close=True)

    def resetApp(self,widget=None):
        """
        Reset selected application
        """
        appname=self.get_selected_project_app()
        if appname:
            if self.dialogs.msgDialog(_('Do you really want to reset application "%s"?') % appname, 'question'):
                self.currentproject.resetapp(appname)
                self.logmsg(_('Application "%s" has been reseted') % appname)

    def appProperties(self,widget=None):
        """
        # TODO: Show application properties
        """
        appname=self.get_selected_project_app()
        if appname:
            self.dialogs.msgDialog(_('Application name: %s') % appname, 'info')

    def removeFromHistory(self,widget=None):
        """
        Remove selected project from history list
        """
        if self.projectshistory.selected():
            name=self.projectshistory.selected()[0]
            if self.dialogs.msgDialog(_('Do you really want to remove project "%s" from history?') % name, 'question'):
                if self.preferences.has_section('ddc_project_definition-' + name):
                    self.preferences.remove_section('ddc_project_definition-' + name)
                    history=self.preferences.general.history
                    history.remove(name)
                    self.preferences.general.history=history
                    self.preferences.save()
                self.update_projects_history()

    def clearProjectHistory(self,widget=None):
        """
        Remove all projects from history list
        """
        if self.dialogs.msgDialog(_('Are you sure you really want to remove all projects in history?'), 'question'):
            for name in self.preferences.general.history:
                if self.preferences.has_section('ddc_project_definition-' + name):
                    self.preferences.remove_section('ddc_project_definition-' + name)
            self.preferences.general.history=[]
            self.preferences.save()
            self.update_projects_history()

    def openBrowser(self,widget=None):
        """
        Open web browser pointing to django development server
        """
        openWithDefaultApp('http://localhost:%s' % self.currentproject.port)

    #===========================================================================
    # Utility methods
    #===========================================================================
    def new_editor_tab(self,filename=None):
        """
        Open a new editor tab
        """
        pass

    def applications_menu_check(self,widget,event):
        """
        Applications popup menu checking
        """
        if self.get_selected_project_app():
            return self.widgets.mnuAppProperties
        else:
            # TODO: Create a menu for model properties
            return self.widgets.mnuIndicator

    def get_selected_project_app(self):
        """
        Get treeview selected project application name
        """
        if self.currentproject:
            appname=self.projectapps.selected()
            if appname and appname[0] in self.currentproject.get_apps():
                return appname[0]
        else:
            return None

    def setup_text_styles(self):
        """
        Setup text styles used in application console log
        """
        buf=self.widgets.txtConsoleLog.get_buffer()
        #newTextTag({'name': 'normal','foreground': self.preferences.log.normalcolor},buf)
        newTextTag({'name': 'internal','foreground': self.preferences.log.internalcolor, 'weight': 700},buf)
        #newTextTag({'name': 'info','foreground': self.preferences.log.notifcolor, 'weight': 700},buf)
        newTextTag({'name': 'error','foreground': self.preferences.log.errorcolor, 'weight': 700},buf)

    def logmsg(self,msg,tag='internal'):
        """
        Log a message to console
        """
        logbuffer=self.widgets.txtConsoleLog.get_buffer()
        it=logbuffer.get_end_iter()
        logbuffer.place_cursor(it)
        logbuffer.insert_with_tags_by_name(it,msg + '\n', tag)
        self.widgets.txtConsoleLog.scroll_to_mark(logbuffer.get_insert(),0)
        # Tray icon blinking
        self.trayicon.blink()
        self.notifsys.queue_msg(msg=msg,icon=self.PIXMAPS_DIR + '/ddc-icon.png')
    
    def console_update_loop(self):
        """
        Console update loop
        """
        # Django server monitoring
        if self.currentproject and self.currentproject.django_server_instance and self.currentproject.django_server_instance.isalive():
            bufdata=self.currentproject.get_server_buffer()
            if bufdata:
                print bufdata 
            return self.currentproject.django_server_instance.isalive()
        elif self.currentproject and self.currentproject.django_server_instance and not self.currentproject.django_server_instance.isalive():
            self.logmsg(_('Django development server has exited unexpectedly'),'error')
            self.currentproject.django_server_instance=None
            self.set_gui_task(self.TASK_SERVERSTOPPED)

    def run_background_task(self,callback,msg,*args,**kwargs):
        """
        Run a background task and shows a progress bar with status
        """
        if self.currentproject:
            if not self.__command_in_progress:
                def task(*args,**kwargs):
                    self.widgets.prgCommand.set_text(msg)
                    self.widgets.prgCommand.show()
                    callback(*args,**kwargs)
                
                def gui(*args,**kwargs):
                    self.widgets.prgCommand.pulse()
                    return self.__command_in_progress
                
                def end(*arg,**kwargs):
                    gobject.timeout_add(500,end2,priority=gobject.PRIORITY_HIGH)
                
                def end2():
                    self.widgets.prgCommand.set_text('')
                    self.widgets.prgCommand.hide()
                    self.__command_in_progress=False
                
                self.__command_in_progress=True
                task=threadtasks.ThreadTask(threadtasks.TYPE_SIMPLE,task,gui,end,gui_delay=100)
                task.start(*args,**kwargs)
            else:
                self.dialogs.msgDialog(_('There is another command in progress'),'error')
    
    def load_project(self,name,port,path,settingsmod):
        """
        Load a project
        """
        if not self.currentproject:
            try:
                # Create new django project instance
                self.currentproject=DjangoProject(name,port,path,settingsmod)
            except Exception,e:
                self.currentproject=None
                self.dialogs.msgDialog(_('Error loading project'),'error',str(e))
                return
            # Update files information
            self.update_project_files()
            # Update applications information
            self.update_apps_information()
            # Update users information
            self.update_users_information()
            # Update settings information
            self.update_settings_information()
            # Add project to project history
            history=self.preferences.general.history
            if self.ui.chkAddToHistory and name not in history:
                # Create new config section for new project
                self.preferences.add_section('ddc_project_definition-' + name,{'port': port,'path': path,'settingsmod': settingsmod})
                # Add project to history list
                history.append(name)
                self.preferences.general.history=history
            # Set window title
            self.widgets.winMain.set_title(_('Django Development Console') + ' - '  + name)
            # Add project as last opened one
            self.preferences.general.lastproject = name
            # Save preferences
            self.preferences.save()
            # Update projects history
            self.update_projects_history()
Beispiel #4
0
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)