예제 #1
0
    def __createBDTemporary(self):
        ''' '''
        pt = PathTools()
        ruta = pt.getPathDatabasesDir() + "MySourceCode.db"
        self.fragmentos.BDU.newDataBase(ruta)

        self.setSM(ruta)
예제 #2
0
    def __init__(self):

        PT = PathTools()
        # ubicacion del archivo de configuracion
        self.cfgFile = PT.getPathCFGFile()

        # instancia de configparser

        self.config = ConfigParser.RawConfigParser()
        self.config.read(self.cfgFile)

        self.__searchPresitionTags = None
        self.__windowStateStartup = None
        self.__userUploader = None
        self.__expandTree = None
        self.__defaultBdName = None
        self.__referencesToBds = None

        # valores dentro de la seccion configurations
        configurations_values = {"searchpresitiontags": 0, "windowstatestartup": 0, "useruploader": "", "expandtree": 0}

        # valores dentro de la seccion database
        database_values = {"defaultbdName": "", "referencestobds": ""}

        couchdb_values = {"urls": "", "names": ""}
        # diccionario con las secciones
        self.__sections = {
            "configurations": configurations_values,
            "database": database_values,
            "couchdb": couchdb_values,
        }
예제 #3
0
class Validator :
    ''' Clase que valida el estado de distintas partes del programa. '''

    def __init__(self) :
        self.pt = PathTools()
        self.config = Configurations()


    def checkFolders (self) :
        """ Verifica que existan los directorios de la aplicación """

        # obtiene la ruta del directorio /databases
        databases_dir = self.pt.getPathDatabasesDir()

        # si no existe el directorio, lo crea
        if not os.path.exists(databases_dir) :
            print 'El directorio /databases no existia, ha sido creado nuevamente.'
            os.mkdir(databases_dir)

        # obtiene la ruta del directorio /data
        data_dir = self.pt.getPathDataDir()

        # si no existe el directorio, lo crea
        if not os.path.exists(data_dir) :
            print 'El directorio /data no existia, ha sido creado nuevamente.'
            os.mkdir(data_dir)

    def checkExistCfg (self) :
        """ Verifica la existencia del archivo de configuracion """

        existe = False
        path_cfg = self.pt.getPathCFGFile()

        if not os.path.exists(path_cfg):
            self.config.regenerateNewCFG()
            existe = True
        return existe

    def checkIntegrityCfg (self) :
        """ Verifica la integridad del archivo de configuracion """
        pass

    def check (self) :

        # verifica la existencia de los directorios
        self.checkFolders()

        # verifica la existencia del archivo de configuracion
        self.checkExistCfg()
예제 #4
0
    def __init__(self, parent, configs, dbutils):
        # carga la interfaz desded el archivo ui
        FILENAME = 'uis/wOpciones.ui'
        uifile = os.path.join(os.path.abspath(os.path.dirname(__file__)),FILENAME)
        QtGui.QMainWindow.__init__(self)
        uic.loadUi(uifile, self)
        self.setWindowIcon(QtGui.QIcon(':/toolbar/gear32.png'))

        # centra la ventana
        self.__centerOnScreen()

        # instancias desde la clase fragmentos
        self.__Config = configs
        self.__DBU = dbutils
        self.__PT = PathTools()
        self.__Padre = parent

        # usado para saber si hay que refrescar el combo
        # de bds de la interfaz principal, en caso
        # de que se haya agregado alguna
        self.__countBdsIsChanged = False
        #
        self.__cargarValoresEnGUI()

        self.tabWidget.setCurrentIndex(0)

        self.cbBDsCargaInicio.setEnabled(False)
예제 #5
0
 def __init__(self):
     self.pt = PathTools()
     self.config = Configurations()
예제 #6
0
 def __validar_file(self):
     p = PathTools()
     return p.getPathProgramFolder() + 'cliente_dbus.py'
예제 #7
0
class Opciones(QtGui.QMainWindow):
    """Clase que maneja las interacciones entre la interfaz grafica y
    la logica de las configuraciones del programa."""

    def __init__(self, parent, configs, dbutils):
        # carga la interfaz desded el archivo ui
        FILENAME = 'uis/wOpciones.ui'
        uifile = os.path.join(os.path.abspath(os.path.dirname(__file__)),FILENAME)
        QtGui.QMainWindow.__init__(self)
        uic.loadUi(uifile, self)
        self.setWindowIcon(QtGui.QIcon(':/toolbar/gear32.png'))

        # centra la ventana
        self.__centerOnScreen()

        # instancias desde la clase fragmentos
        self.__Config = configs
        self.__DBU = dbutils
        self.__PT = PathTools()
        self.__Padre = parent

        # usado para saber si hay que refrescar el combo
        # de bds de la interfaz principal, en caso
        # de que se haya agregado alguna
        self.__countBdsIsChanged = False
        #
        self.__cargarValoresEnGUI()

        self.tabWidget.setCurrentIndex(0)

        self.cbBDsCargaInicio.setEnabled(False)

########################
## Metodos de Eventos ##
########################

    #~
    #~ BOTONES GENERALES
    #~

    @QtCore.pyqtSlot()
    def on_btAgregarBDReferencia_clicked(self):
        self.__agregarBDReferencia()

    @QtCore.pyqtSlot()
    def on_btQuitarBDReferencia_clicked(self):
        self.__quitarBDReferencia()

    @QtCore.pyqtSlot()
    def on_btAceptar_clicked(self):
        pass

    @QtCore.pyqtSlot()
    def on_btAgregarBDDefault_clicked(self):
        self.__agregarBDDefault()

    @QtCore.pyqtSlot()
    def on_btQuitarBDDefault_clicked(self):
        self.__quitarBDDefault()

    def closeEvent(self, event):
        self.on_eNombreUsuario_editingFinished()

    #~
    #~ TAB: GENERALES
    #~

    @QtCore.pyqtSlot(bool)
    def on_cbxBuscarTags_clicked(self, valor):
        # refleja el cambio en el CFG
        self.__Config.searchPresitionTags = int(valor)

    @QtCore.pyqtSlot(bool)
    def on_cbxMaximizado_clicked(self, valor):

        # refleja el cambio en el CFG
        self.__Config.windowStateStartup = int(valor)

    @QtCore.pyqtSlot(bool)
    def on_cbxExpandirArbol_clicked(self, valor):
        # refleja el cambio en el CFG
        self.__Config.expandTree = int(valor)

    def on_eNombreUsuario_editingFinished(self):
        # obtiene el valor actual
        nombre = unicode(self.eNombreUsuario.text(), 'utf-8')
        # lo refleja en el CFG
        self.__Config.userUploader = nombre

    #~
    #~ TAB: BASES DE DATOS
    #~


########################
## Metodos Auxiliares ##
########################

    def __centerOnScreen(self):
        u"""Centers the window on the screen."""
        resolution = QtGui.QDesktopWidget().screenGeometry()
        self.move((resolution.width() / 2) - (self.frameSize().width() / 2),
                  (resolution.height() / 2) - (self.frameSize().height() / 2))

    def __toUnicode(self,myQstring):
        u""" Convierte a UTF8 el objeto QString recibido. """
        #~ print myQstring
        return unicode(myQstring.toUtf8(),'utf-8')

    def __cargarValoresEnGUI(self) :
        ''' Llama a los metodos que se encargan de reflejar los valores
        actuales  de las configuraciones en la interfaz. '''

        # Tab: General

        self.__chequearOpcionesGenerales()
        self.__cargarNombreUsuario()

        # Tab: Bases de datos

        self.__setPathDefaultBDsInGUI()
        self.__cargarBDsDesdeDatabases()
        self.__cargarBDsDesdeCFG()
        self.__cargarComboBDsDefault()

    #~
    #~ TAB: GENERALES
    #~

    def __cargarNombreUsuario(self):
        ''' Recupera el valor para este campo desde el CFG y
        lo muestra en la interfaz. '''
        self.eNombreUsuario.setText(
                self.__Config.userUploader)

    def __chequearOpcionesGenerales(self):

        self.cbxBuscarTags.setChecked(
            int(self.__Config.searchPresitionTags))

        self.cbxMaximizado.setChecked(
            int(self.__Config.windowStateStartup))

        self.cbxExpandirArbol.setChecked(
            int(self.__Config.expandTree))
    #~
    #~ TAB: CATALOGOS
    #~
    def __agregarBDDefault(self):
        filename = QtGui.QFileDialog.getOpenFileName(self, u'Agregar catálogo',filter = '*.db')
        if filename:
            filename = unicode(filename, 'utf-8') # persiste la nueva refrencia en el cfg

            if self.__DBU.validarBD(filename):
                self.__DBU.agregarBDADefault(filename)
                self.__cargarBDsDesdeDatabases()

                # refresca el combo de la interfaz principal
                self.__Padre.refreshBdsInComboMainWindow()
            else:
                QtGui.QMessageBox.critical(self,"Agregar catalogo",
                "Este archivo no es un catalogo valido de Fragmentos.")

    def __agregarBDReferencia(self):
        filename = QtGui.QFileDialog.getOpenFileName(self, u'Agregar referencia a catálogo',filter = '*.db')
        if filename:
            filename = unicode(filename, 'utf-8') # persiste la nueva refrencia en el cfg

            if self.__DBU.validarBD(filename):
                self.__agregarBDReferenciaInCFG(filename) # refresca la gui
                self.__cargarBDsDesdeCFG()

                # refresca el combo de la interfaz principal
                self.__Padre.refreshBdsInComboMainWindow()
            else:
                QtGui.QMessageBox.critical(self,u"Agregar referencia a catálogo",
                u"Este archivo no es un catálogo válido de Fragmentos.")

    def __agregarBDReferenciaInCFG(self, pathCatalogo):
        ''' Agrega el nuevo catalogo seleccionado a en el archivo CFG'''

        # recupera el string guardado en el cfg
        referencias = self.__Config.referencesToBds
        # separa los paths
        referencias = referencias.split(',')
        # agrega el nuevo path a los existentes
        referencias.append(pathCatalogo)
        # vuelve a juntar los path en un solo string
        # y lo guarda nuevamente en el cfg
        self.__Config.referencesToBds = ','.join(referencias)

    def __cargarBDsDesdeDatabases(self):
        ''' Carga en la lista las bds existentes en el directorio
        establecido por defecto. '''

        self.lstBdsDefault.clear()
        bds = self.__DBU.getBDsNamesDatabasesDir()
        if bds :
            map(self.lstBdsDefault.addItem,bds)

    def __cargarBDsDesdeCFG(self):
        ''' '''
        self.lstBdsReferences.clear()
        bds = self.__Config.getDBsInCFGReferences()
        if bds :
            map(self.lstBdsReferences.addItem,bds)

    def __cargarComboBDsDefault(self):
        ''' '''
        databases_dir = self.__DBU.getBDsNamesDatabasesDir()
        cfg_file = self.__Config.getDBsNamesCFGReferences()
        nombres = databases_dir + cfg_file
        map(self.cbBDsCargaInicio.addItem,nombres)

    def __quitarBDDefault(self):
        ''' '''
        if self.lstBdsDefault.currentRow() != -1 :
            pass

    def __quitarBDReferencia(self):
        ''' '''
        if self.lstBdsReferences.currentRow() != -1 :
            ruta_a_quitar = unicode(self.lstBdsReferences.currentItem().text().toUtf8(),'utf-8')
            self.__Config.quitarDBInCFGReference( ruta_a_quitar )
            self.__cargarBDsDesdeCFG()
            # refresca el combo de la interfaz principal
            self.__Padre.refreshBdsInComboMainWindow()

    def __setPathDefaultBDsInGUI(self):
        ''' Obtiene la ruta del directorio por defecto y
        lo muestra en el campo correspondiente en la interfaz. '''
        self.eDefaultDir.setText(
                        self.__PT.getPathDatabasesDir())
예제 #8
0
 def __init__(self):
     self.__PT = PathTools()
     self.__new_campos = ['title','language','contens','tags','description',
     'creation','starred','reference','modified','uploader']
     self.__old_campos = ['title','language','contens','tags',
         'comments','date','starred','reference']
예제 #9
0
class DBUtils:
    ''' Clase para el manejo de utilidades de base de datos. '''

    def __init__(self):
        self.__PT = PathTools()
        self.__new_campos = ['title','language','contens','tags','description',
        'creation','starred','reference','modified','uploader']
        self.__old_campos = ['title','language','contens','tags',
            'comments','date','starred','reference']

###############
# METODOS GET #
###############

    def agregarBDADefault(self, pathBD):
        ''' Copia el archivo recibido a la carpeta establecida por defecto
        para los catalogos del programa.'''
        import shutil

        shutil.copy(pathBD, self.__PT.getPathDatabasesDir())

    def actualizarEstructuraBD(self, pathBD):
        ''' Reconfigura la estructura de la bd antigua a la version actual.'''

        import os

        bd = sqlite(pathBD)

        # obtiene todos los snippets de la bd
        todo = bd.getDatosTabla('snippet','title,language,contens,tags,comments,date,starred,reference')

        # elimina el actual archivo de la bd
        os.remove(pathBD)
        # creamos una nueva bd
        self.newDataBase(pathBD)

        bd = sqlite(pathBD)

        orden_campos = {
        'title':0,
        'language':1,
        'contens':2,
        'tags':3,
        'description':4,
        'creation':5,
        'starred':6,
        'reference':7
        }
        # agrega nuevamente los snippets a la bd
        bd.realizarAltas('snippet', orden_campos, todo)

        print 'Estructura de la bd actualizada.'

    def getBDsInDatabasesDir(self):
        ''' Obtiene los path's de las bases de datos ubicadas en el directorio databases.'''

        # obtiene una lista con los archivos que estan en el directorio databases
        archivos_dbs = os.listdir(self.__PT.getPathDatabasesDir())
        bds = []
        # filtra los archivos devueltos por la extencion .db
        for archivo in archivos_dbs:
            # si es un archivo que es alguna de las extenciones permitidas
            if os.path.splitext(archivo)[1] == Members.DB_EXTENCIONS:
                bds.append(self.__PT.convertPath(self.__PT.getPathDatabasesDir() + '/' + archivo))
        return bds

    def getBDsNamesDatabasesDir(self):
        ''' Obtiene una lista con los nombres de los archivos bds,
        del directorio databases.  '''

        # obtienes los paths de las bds en /databases
        bd_rutas = self.getBDsInDatabasesDir()
        bd_names = []
        for ruta in bd_rutas:
            # recupera el nombre del archivo
            nombre_bd = os.path.splitext(os.path.basename(ruta))
            # lo agrega a la lista
            bd_names.append(nombre_bd[0])
        return bd_names

    def getDBNumberInDatabasesDir(self):
        ''' Obtiene la cantidad de archivos de bd en el dir databases '''
        bds = self.getBDsInDatabasesDir()
        return len(bds)

    def __getColumnasTabla(self, nombreTabla) :
        """ Obtiene los nombres de las columnas de la tabla. """
        columnas = []
        self.__cursor.execute('PRAGMA table_info(' + nombreTabla +')')
        infotable = self.__cursor.fetchall()
        #print infotable
        for row in infotable:
            #print row
            columnas.append(row[1])
        return columnas

    #~ def isBDActual(self, pathBD):
        #~ ''' Devuelve TRUE en caso de que sea una base de datos
        #~ Fragmentos con la estructura 'title','language','contens','tags',
        #~ 'description','creation','starred','reference','modified','uploader'.'''
        #~
        #~ # pregunta si es la bd con estructura nueva
        #~ if self.validarBD(pathBD) :
            #~ return True
        #~ elif self.validarBD(pathBD):
            #~ return False

    def newDataBase(self, pathNewBD):
        print pathNewBD
        ''' Crea una nueva base de datos Fragmentos. '''
        # se fija que la bd ya no exista anteriormente
        if not os.path.exists(pathNewBD):
            # crea la conexion para el path asignado
            connection = sqlite3.connect(pathNewBD)
            cursor = connection.cursor()
            # ejecuta la consulta para crear la tabla dentro de la bd
            cursor.execute(Members.SCRIPTSQL_BD_SNIPPET)
            # persiste la consulta
            connection.commit()
            print 'BD creada con exito en : ',pathNewBD
            return True
        else:
            print 'Ya existe una base de datos con el mismo nombre...'
            return False

    def validarBD(self, pathBD):
        ''' Verifica que la estructura de la bd sea una bd tipo Fragmentos.'''

        valido = False
        # crea la conexion para el path asignado
        connection = sqlite3.connect(pathBD)
        cursor = connection.cursor()

        # consulta para obtener las tablas de la bd
        try:
            cursor.execute('Select tbl_name From MAIN.[sqlite_master] where type = "table"')
        except :
            return False
        # recorre las tablas devueltas para verificar que exista la tabla 'snippet'
        for fila in cursor:
            if fila[0] == 'snippet':
                # recupera las
                columnas = []
                cursor.execute('PRAGMA table_info(snippet)')
                infotable = cursor.fetchall()
                for row in infotable:
                    columnas.append(row[1])

                if columnas == self.__new_campos :
                    valido = True
                elif columnas == self.__old_campos :
                    self.actualizarEstructuraBD(pathBD)
                    valido = True
                else: valido = False

        return valido
예제 #10
0
    def __init__(self,parent):
        """ Ventana Principal debe recibir una instancia de GUI """
        FILENAME = 'uis/MainForm.ui'
        uifile = os.path.join(os.path.abspath(os.path.dirname(__file__)),FILENAME)
        QtGui.QMainWindow.__init__(self)
        uic.loadUi(uifile, self)
        self.setWindowIcon(QtGui.QIcon(':/toolbar/logo.png'))
        # centra la ventana en la pantalla
        self.__centerOnScreen()
        self.__PT = PathTools()

        # conectar salir
        self.connect(self, QtCore.SIGNAL('destroyed()'), self.destroyed)

        # agrega y crea el Treeview
        #TODO:
        self.mytreeview = TreeView(self.tvLenguajes,self.on_tvLenguajes_selectedItem,
                                   self.connect,iconSub=QtGui.QIcon(':/toolbar/linedpaper32.png'),
                                                iconRoot=QtGui.QIcon(':/toolbar/lang.png'))
        self.mytreeview.widget.setContextMenuPolicy( QtCore.Qt.CustomContextMenu )
        self.connect(self.mytreeview.widget, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
                      self.on_treecontext_menu)

        # agrega el Widget de codigo
        self.widgetcomoEmpezar = ComoEmpezar()
        self.widgetcodigo = Scintilla()
        self.wgtDetalles.setVisible(False)
        self.vlCodigo.insertWidget(0,self.widgetcodigo.getEditor())
        self.vlCodigo.insertWidget(1,self.widgetcomoEmpezar)
        self.widgetcodigo.getEditor().setVisible(False)
        # Reordenamiento y expancion del separador tree-widgetcodigo
        self.spPrincipal.setSizes([50,900])#ni idea pero no tocar

        # colores x defecto
        self.colorBusqueda = QcolorTextEdit(self.eBusqueda)

        # Instancia y variables usadas
        self.Padre = parent # esto es GUI
        self.SM = parent.SM # esto es GUI.SM
        self.PasePorAca = False
        self.fullScreen = False
        self.historialSnippets = [[],0]

        # establece el trayicon
        self.Padre.setTrayIcon(self)

        #self.refreshTree()

        # carga las bds en el combo
        self.loadBDsInCombo()

        # carga los ShortCuts de la app
        self.__loadAppShortcuts()

        # crea el MenuPrincipal
        self.__createMenu()

        self.eBusqueda.setFocus()
        self.btSptAnterior.setEnabled(False)
        self.btSptSiguiente.setEnabled(False)
        self.btMas.setVisible(False)
예제 #11
0
class Main(QtGui.QMainWindow):
    """La ventana principal de la aplicación."""

    def __init__(self,parent):
        """ Ventana Principal debe recibir una instancia de GUI """
        FILENAME = 'uis/MainForm.ui'
        uifile = os.path.join(os.path.abspath(os.path.dirname(__file__)),FILENAME)
        QtGui.QMainWindow.__init__(self)
        uic.loadUi(uifile, self)
        self.setWindowIcon(QtGui.QIcon(':/toolbar/logo.png'))
        # centra la ventana en la pantalla
        self.__centerOnScreen()
        self.__PT = PathTools()

        # conectar salir
        self.connect(self, QtCore.SIGNAL('destroyed()'), self.destroyed)

        # agrega y crea el Treeview
        #TODO:
        self.mytreeview = TreeView(self.tvLenguajes,self.on_tvLenguajes_selectedItem,
                                   self.connect,iconSub=QtGui.QIcon(':/toolbar/linedpaper32.png'),
                                                iconRoot=QtGui.QIcon(':/toolbar/lang.png'))
        self.mytreeview.widget.setContextMenuPolicy( QtCore.Qt.CustomContextMenu )
        self.connect(self.mytreeview.widget, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
                      self.on_treecontext_menu)

        # agrega el Widget de codigo
        self.widgetcomoEmpezar = ComoEmpezar()
        self.widgetcodigo = Scintilla()
        self.wgtDetalles.setVisible(False)
        self.vlCodigo.insertWidget(0,self.widgetcodigo.getEditor())
        self.vlCodigo.insertWidget(1,self.widgetcomoEmpezar)
        self.widgetcodigo.getEditor().setVisible(False)
        # Reordenamiento y expancion del separador tree-widgetcodigo
        self.spPrincipal.setSizes([50,900])#ni idea pero no tocar

        # colores x defecto
        self.colorBusqueda = QcolorTextEdit(self.eBusqueda)

        # Instancia y variables usadas
        self.Padre = parent # esto es GUI
        self.SM = parent.SM # esto es GUI.SM
        self.PasePorAca = False
        self.fullScreen = False
        self.historialSnippets = [[],0]

        # establece el trayicon
        self.Padre.setTrayIcon(self)

        #self.refreshTree()

        # carga las bds en el combo
        self.loadBDsInCombo()

        # carga los ShortCuts de la app
        self.__loadAppShortcuts()

        # crea el MenuPrincipal
        self.__createMenu()

        self.eBusqueda.setFocus()
        self.btSptAnterior.setEnabled(False)
        self.btSptSiguiente.setEnabled(False)
        self.btMas.setVisible(False)

######################
## Metodos de clase ##
######################

    def __addKeytoBusqueda(self,cadena):
        """Soporte de atajos generico.Manipula los atajos
        en la barra de busqueda"""

        ubicacion = self.__convertir_a_unicode(self.eBusqueda.text)
        self.eBusqueda.setFocus()
        if ubicacion.find(cadena) == -1:
            if not len(ubicacion.strip()):
                self.eBusqueda.setText(cadena)
            else:
                self.eBusqueda.setText(ubicacion+u","+cadena)
            self.eBusqueda.setCursorPosition(self.__convertir_a_unicode(self.eBusqueda.text).find(cadena)+2)
        else:
            self.eBusqueda.setCursorPosition(ubicacion.find(cadena)+2)

    def __agregarSnippet(self):
        if self.SM.getDB():
            self.Padre.showAgregarSnippet()
        else:
            QtGui.QMessageBox.warning(self, "Fragmentos",
            "No se ha seleccionado una base de datos donde guardar snippets.")

    def __convertir_a_unicode(self,myQstring):
        return str(myQstring.toUtf8())

    def __cargarBDSeleccionada(self, indice):
        """ Al seleccionar otra base de datos desde el combo,
        reflejar los cambios en la interfaz. """

        #obtiene la ruta de la bd segun el indice
        rutaNueva = self.SM.getPathDB(indice)

        if rutaNueva.find('|') == -1 :
            self.SM.usecouch = False
            argumentos = rutaNueva,
        else:
            # couchdb
            self.SM.usecouch = True
            argumentos = rutaNueva.split('|')

        # vuelva a crear la instancia de bd con la nueva ruta
        self.Padre.setSM(*argumentos)

        # carga los snippets en el arbol
        self.refreshTree()
        self.historialSnippets = [[],0]

    def loadBDsInCombo(self):
        ''' '''
        #if self.SM.getDB() :
        # recarga la lista de paths a bds
        self.SM.loadAllPathDBs()

        # limpia las items insertados
        self.cbBD.clear()

        #  obtiene los nombres de las bds
        bds = self.SM.getBDNames()
        if bds :
            map(self.cbBD.addItem, bds)

        self.cbBD.setCurrentIndex(-1)
        if bds :
            self.cbBD.setCurrentIndex(0)

    def __centerOnScreen (self):
        """Centers the window on the screen."""
        resolution = QtGui.QDesktopWidget().screenGeometry()
        self.move((resolution.width() / 2) - (self.frameSize().width() / 2),
                  (resolution.height() / 2) - (self.frameSize().height() / 2))

    def __createMenu(self):
        """Crea el main menu"""

        menu = QtGui.QMenu(self.btMenu)

        menusnippet = menu.addMenu("Snippet")
        menusnippet.addAction("Agregar",self.__agregarSnippet,QtGui.QKeySequence("F9"))
        menusnippet.addAction("Editar", self.__modificarSnippet,QtGui.QKeySequence("Ctrl+M"))
        menusnippet.addAction("Eliminar", self.__eliminarSnippet,QtGui.QKeySequence("Del"))

        menudatabase= menu.addMenu(u"Catálogo")
        menudatabase.addAction("Nuevo... ", self.__nuevaBDFragmentos)

        menubusqueda = menu.addMenu("Busqueda")
        menubusqueda.addAction("'t=' Por Titulo", lambda : self.__cargarCriterioBusquedaEnBarra('t'),QtGui.QKeySequence("Alt+T"))
        menubusqueda.addAction("'g=' Por Tags", lambda : self.__cargarCriterioBusquedaEnBarra('g'),QtGui.QKeySequence("Alt+G"))
        menubusqueda.addAction("'l=' Por Lenguaje", lambda : self.__cargarCriterioBusquedaEnBarra('l'),QtGui.QKeySequence("Alt+L"))
        menubusqueda.addAction("'n=' Por Fecha creacion", lambda : self.__cargarCriterioBusquedaEnBarra('n'),QtGui.QKeySequence("Alt+N"))
        menubusqueda.addAction("'m=' Por Fecha modificacion", lambda : self.__cargarCriterioBusquedaEnBarra('m'),QtGui.QKeySequence("Alt+M"))
        menubusqueda.addAction("'a=' Por Autor", lambda : self.__cargarCriterioBusquedaEnBarra('a'),QtGui.QKeySequence("Alt+A"))
        menubusqueda.addAction("'c=' Por Contenido", lambda : self.__cargarCriterioBusquedaEnBarra('c'),QtGui.QKeySequence("Alt+C"))

        menu.addSeparator()

        # menucompartir = menu.addMenu("Compartir")
        # menucompartir.addAction("Enviar a Pastebin", self.__enviarAPastebin)
        # menucompartir.addAction(u"¿Que es Pastebin?", self.__helpPastebin)

        menu.addSeparator()

        menu.addAction("Opciones", self.__showOptions, QtGui.QKeySequence("Ctrl+O"))
        menu.addAction("Ayuda", self.__mostrarAyuda)

        menu.addSeparator()

        menu.addAction("Acerca de...", self.__mostrarAcercaDe)

        menu.addSeparator()

        menu.addAction("Salir", self.__destroyed, QtGui.QKeySequence("Ctrl+Q"))


        self.btMenu.setMenu(menu)

    def __cargarCriterioBusquedaEnBarra(self, criterio):
        valor_a_cargar = unicode(self.eBusqueda.text().toUtf8(),'utf-8')
        index = valor_a_cargar.find(criterio + "=")
        if index == -1 :
            valor_a_cargar += "," + criterio + "=" if len(valor_a_cargar) > 0 else criterio + "="
            self.eBusqueda.setText( valor_a_cargar )
        else:
            self.eBusqueda.setCursorPosition( index + 2 )

    def __destroyed(self):
        ''' Hace volar la ventana. '''
        #TODO: hacer que cierre todas las ventanas
        sys.exit(0)

    def __eliminarSnippet(self):
        """Ejecuta las instrucciones para eliminar el snippet actual."""

        actual = self.SM.getSnippetActual()

        if actual is None:
            QtGui.QMessageBox.warning(self, "Eliminar snippet",
        "Debes seleccionar un snippet para eliminarlo.")
        else:
            result = QtGui.QMessageBox.warning(self, "Eliminar snippet",
            "Esta seguro que desea eliminar este snippet?.\n\n" + \
            actual.titulo + '\n' + actual.lenguaje,
            QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)

            if result == QtGui.QMessageBox.Yes:
                if self.SM.eliminarSnippet(actual):
                    QtGui.QMessageBox.information(self, "Eliminar snippet",
                    "Snippet eliminado.")
                    self.refreshTree()
                else:
                    QtGui.QMessageBox.critical(self, "Eliminar snippet",
                    "Se produjo un error al intentar eliminar este snippet.")

    def __loadAppShortcuts(self):
        u""" Load shortcuts used in the application. """

        QtGui.QShortcut(QtGui.QKeySequence("F11"), self, self.__toogleFullScreen)
        QtGui.QShortcut(QtGui.QKeySequence("Ctrl+L"), self, self.eBusqueda.setFocus)
        # atajo : cerrar/salir
        QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self, self.close)

    def __cleanFields(self) :

        self.widgetcodigo.clearCode()
        self.txtDescripcion.setText("")
        self.btPonerComoFavorito.setChecked(False)
        self.leLenguaje.setText("")
        self.leTitulo.setText("")
        self.leTags.setText("")

    def __modificarSnippet(self):
        """ Ejecuta las instrucciones para modificar el snippet actual. """

        actual = self.SM.getSnippetActual()
        if actual is None:
            QtGui.QMessageBox.warning(self, "Modificar snippet",
        "Debes seleccionar un snippet para modificarlo.")
        else:
            self.Padre.showModificarSnippet(actual)
            #~ self.refreshTree()

    def __showSnippet(self, lenguaje, titulo):
        self.widgetcomoEmpezar.setVisible(False)
        self.widgetcodigo.getEditor().setVisible(True)

        # obtiene el snippet segun titulo y lenguaje
        snippet = self.SM.getSnippet(lenguaje,titulo)

        # muestra el codigo en el visor de codigo
        self.widgetcodigo.setFullCode(snippet.codigo,snippet.lenguaje)

        # carga en los campos los datos del snippet
        self.leTags.setText(snippet.tags)
        self.leTitulo.setText(snippet.titulo)
        self.leLenguaje.setText(snippet.lenguaje)
        self.txtDescripcion.setText('Descripcion: '+snippet.descripcion)
        self.lbFechaCreacion.setText('Creado: '+snippet.fechaCreacion)
        if not snippet.fechaModificacion is None:
            # si existe una fecha de modificado
            self.lbFechaModificacion.setVisible(True)
            self.lbFechaModificacion.setText('Modificado: '+str(snippet.fechaModificacion))
        else:
            #oculta el label
            self.lbFechaModificacion.setVisible(False)

        # si es favorito, cambia el estado del boton
        if snippet.favorito == "0":
            self.btPonerComoFavorito.setChecked(False)
        elif snippet.favorito == "1":
            self.btPonerComoFavorito.setChecked(True)

    def __setAsFavorite(self):

        #obtiene la instancia actual del snippet
        snippetActual = self.SM.getSnippetActual()

        #establece el nuevo valor
        if not snippetActual is None:
            #~ print str(int(self.btPonerComoFavorito.isChecked()))
            # refleja este cambio en los datos del snippet
            snippetActual.favorito = str(int(self.btPonerComoFavorito.isChecked()))

            # establece el nuevo estado del snippet
            self.SM.setSnippetActual(snippetActual)
            self.lbEstado.setText("Establecido como favorito.")
        else:
            # permite que el boton no sea chequeado
            self.btPonerComoFavorito.setChecked(False)

    def __historial(self,tipo,tLengTit=None):
        historial = self.historialSnippets[0]
        indice = self.historialSnippets[1]
        if tipo == 'add':
            historial = historial[:indice+1]
            historial.append(tLengTit)
            indice = len(historial)-1

        elif tipo == 'forw':
            if (len(historial)-1) > indice:
                lenguaje,titulo = historial[indice+1]
                indice += 1
                self.__showSnippet(lenguaje,titulo)

        elif tipo == 'back':
            if indice:
                lenguaje,titulo = historial[indice-1]
                indice += -1
                self.__showSnippet(lenguaje,titulo)
        else:
            print "opcion incorrecta"
        self.historialSnippets = [historial,indice]

    def __enviarAPastebin(self):
        actual = self.SM.getSnippetActual()
        if actual is None:
            QtGui.QMessageBox.warning(self, "Enviar snippet a Pastebin",
        "Debes seleccionar un snippet para poder enviarlo.")
        else:
            #TODO:configurable
            url = self.Padre.fragmentos.Pastebin.submit(
                        paste_code = actual.codigo,
                        paste_name = actual.titulo,
                        paste_expire_date = '1D',
                        paste_format = actual.lenguaje)
            # copia el link al portapapeles
            self.Padre.clipboard.setText(url)
            mensaje = '''Snippet enviado correctamente.

            Puede encontrar su snippet en la siguiente direccion:\n
            %s
            \nLink disponible en el portapapeles.''' % url
            QtGui.QMessageBox.information(self, "Enviar Snippet a Pastebin",
            mensaje)

    def refreshTree(self):
        """ A partir de la instancia actual de SM,
        refresca el arbol cargando nuevamente los snippets. """
        self.SM = self.Padre.SM
        lengs_and_titles = self.SM.getLengsAndTitles()

        self.mytreeview.insertarEnArbol(lengs_and_titles)

        self.lbEstado.setText(
            str(self.SM.getSnippetsCount()) + ' snippet(s) cargados.')

    def __toogleFullScreen(self):
        ''' '''
        if not self.fullScreen :
            self.showFullScreen()
        else:
            self.showNormal()
        self.fullScreen = not self.fullScreen

    ################################################################
    #   Metodos usados en el menu de la aplicacion
    ###############################################################

    def __helpPastebin(self):
        ''' '''
        mensaje = u'''Pastebin es una aplicación web que permite a sus usuarios subir pequeños textos, generalmente ejemplos de código fuente, para que estén visibles al público en general.

        Enlace: http://pastebin.com
        Fuente: http://es.wikipedia.org/wiki/Pastebin'''

        QtGui.QMessageBox.information(self, u"¿Que es Pastebin?",mensaje)

    def __showOptions(self):
        ''' '''
        self.Padre.showOpciones()

    def __mostrarAyuda(self) :
        ''' '''
#        QtGui.QMessageBox.information(self, "Ayuda",
#                "Opcion todavia no disponible en esta version.")
        self.widgetcomoEmpezar.setVisible(True)
        self.widgetcodigo.getEditor().setVisible(False)

    def __mostrarAcercaDe(self):
        ''' '''
        self.Padre.showAcercaDe()

    def __nuevaBDFragmentos(self) :
        ''' Abre un dialogo de archivos, para guardar el
        archivo de la bd creada.'''

        catalogs_dir = self.__PT.getPathDatabasesDir()
        filename = QtGui.QFileDialog.getSaveFileName(
            self, 'Nuevo catalogo de Fragmentos', directory=catalogs_dir, filter='*.db')
        if filename:
            filename = self.__convertir_a_unicode(filename)
            if filename[-3:] != '.db' :
                filename = filename + '.db'
            # llamamos al metodo que crea la bd
            estado = self.Padre.fragmentos.BDU.newDataBase(filename)
            if estado :
                QtGui.QMessageBox.information(self, u"Nuevo catálogo",
                u"Catálogo creado con exito en : \n\n" + filename)
                self.loadBDsInCombo()
            else:
                QtGui.QMessageBox.critical(self, u"Nuevo catálogo",
                u"Se ha producido un error al intentar crear el catálogo.")

############
## Events ##
############

    ###############
    ### BOTONES ###
    ###############

    @QtCore.pyqtSlot()
    def on_btAgregarSnippet_clicked(self):
        self.__agregarSnippet()

    @QtCore.pyqtSlot()
    def on_btCopiarAlPortapapeles_clicked(self):
        self.Padre.clipboard.setText(self.widgetcodigo.getCode())

    @QtCore.pyqtSlot()
    def on_btBuscarEnFavoritos_clicked(self):
        ''' carga en el arbol los snippets favoritos'''

        if self.btBuscarEnFavoritos.isChecked():
            #obtiene solo los favoritos
            datos = self.SM.getLengsAndTitles("s=1",True)
        else:
            datos = self.SM.getLengsAndTitles()
        #carga los snippets en el arbol
        self.mytreeview.insertarEnArbol(datos)

    @QtCore.pyqtSlot()
    def on_btPonerComoFavorito_clicked(self):
        self.__setAsFavorite()

    @QtCore.pyqtSlot()
    def on_btSptAnterior_clicked(self):
        self.__historial('back')
        self.btSptSiguiente.setEnabled(True)
        if not self.historialSnippets[1]:#si no hay cosas para volver
            self.btSptAnterior.setEnabled(False)


    @QtCore.pyqtSlot()
    def on_btSptSiguiente_clicked(self):
        self.__historial('forw')
        self.btSptAnterior.setEnabled(True)
        if (len(self.historialSnippets[0])-1)==self.historialSnippets[1]:#si no hay cosas para adelantar
            self.btSptSiguiente.setEnabled(False)

    ###############
    ### ENTRYES ###
    ###############

    def loadSearchResult(self):
        def cambiarColorBarra(barra, rojo = False):
            style = '''
            QLineEdit { border: 2px groove gray; border-radius: 8px; padding: 1px 2px;
            border-top-left-radius: 8px ; border-top-right-radius: 0px solid white;
            border-bottom-right-radius: 0px ; border-bottom-left-radius: 8px; /**/}'''
            barra.setStyleSheet( style.replace('/**/','background-color: #FF6666;')) if rojo else barra.setStyleSheet( style )
        datos = []
        cadena = str(self.eBusqueda.text().toUtf8())
        datos = self.SM.getLengsAndTitles(
            cadena,
            self.btBuscarEnFavoritos.isChecked()
        )
        if datos :
            # si hubieron resultados en la busqueda
            cambiarColorBarra(self.eBusqueda, False)
            self.mytreeview.insertarEnArbol(datos)
            # si en las configuraciones este valor es true
            # el arbol se expandira al realizar una busqueda
            if self.Padre.fragmentos.ConfigsApp.expandTree == '1' :
                self.tvLenguajes.expandAll()

        else:
            cambiarColorBarra(self.eBusqueda, True)
            self.mytreeview.model.clear()
        try:
            self.lbEstado.setText(str(len(datos))+' snippet(s) encontrados...')
        except TypeError:
            self.lbEstado.setText('0 snippet(s) encontrados...')
        if cadena == "":
            self.lbEstado.setText(
                str(self.SM.getSnippetsCount()) + ' snippet(s) cargados...')

    def on_eBusqueda_textChanged(self,cadena):
        QtCore.QTimer().singleShot(300, self.loadSearchResult)

    def on_eBusqueda_textEdited(self,cadena):
        posicion_cursor = self.eBusqueda.cursorPosition()
        self.eBusqueda.setText(
            self.__convertir_a_unicode(cadena).lower())
        self.eBusqueda.setCursorPosition( posicion_cursor )

    ################
    ### TREEVIEW ###
    ################
    def on_treecontext_menu(self, point):
        #TODO: hacer menu
        menu = QtGui.QMenu()
        menu.addAction("Editar", self.__modificarSnippet,QtGui.QKeySequence("Ctrl+M"))
        menu.exec_( self.mytreeview.widget.mapToGlobal(point) )

    def on_tvLenguajes_selectedItem(self,indice,b):
        if indice.parent().row() != -1:
            lenguaje =  unicode(
                            indice.parent().data().toString().toUtf8(),
                            'utf-8')
            titulo =  unicode(
                            indice.data().toString().toUtf8(),
                            'utf-8')
        #History zone
            self.btSptAnterior.setEnabled(True)
            self.btSptSiguiente.setEnabled(False)
            self.__historial('add', (lenguaje,titulo))
            self.__showSnippet(lenguaje,titulo)

    ################
    ### COMBOBOX ###
    ################

    @QtCore.pyqtSlot(int)
    def on_cbBD_currentIndexChanged(self,index):
        if self.PasePorAca:
            self.__cargarBDSeleccionada(self.cbBD.currentIndex())
        else:
            self.PasePorAca = True

    def closeEvent(self, event):
        event.ignore()
        self.hide()