Example #1
0
 def __init__(self):
     '''
     Constructor
     '''
     super(SpatialiteDb, self).__init__()
     self.db = QSqlDatabase('QSQLITE')
     self.gen = SqlGeneratorFactory().createSqlGenerator(True)
Example #2
0
    def __init__(self):
        """Constructor.
        """
        super(PostgisDbThread, self).__init__()

        self.factory = SqlGeneratorFactory()
        #setting the sql generator
        self.gen = self.factory.createSqlGenerator(False)

        self.messenger = PostgisDbMessages(self)
Example #3
0
 def __init__(self, parent = None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     # Set up the user interface from Designer.
     # After setupUI you can access any designer object by doing
     # self.<objectname>, and you can use autoconnect slots - see
     # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
     # #widgets-and-dialogs-with-auto-connect
     self.setupUi(self)
     self.utils = Utils()
     self.factory = SqlGeneratorFactory()
     #setting the sql generator
     self.gen = self.factory.createSqlGenerator(False)
     self.serverWidget.populateServersCombo()
     self.serverWidget.abstractDbLoaded.connect(self.populateListWithDatabasesFromServer)
Example #4
0
 def __init__(self, parent=None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.setupUi(self)
     self.utils = Utils()
     self.dbFactory = DbFactory()
     self.factory = SqlGeneratorFactory()
     self.showTabs(show=False)
     #setting the sql generator
     self.serverWidget.populateServersCombo()
     self.serverWidget.abstractDbLoaded.connect(self.checkSuperUser)
     self.serverWidget.abstractDbLoaded.connect(
         self.populateOtherInterfaces)
     self.dbsCustomSelector.setTitle(self.tr('Server Databases'))
     self.dbsCustomSelector.selectionChanged.connect(self.showTabs)
     self.dbsCustomSelector.selectionChanged.connect(
         self.populateStylesInterface)
     self.dbsCustomSelector.selectionChanged.connect(
         self.populateOtherInterfaces)
     self.previousTab = 0
     self.dbDict = {'2.1.3': [], 'FTer_2a_Ed': [], 'Non_EDGV': []}
     self.correspondenceDict = {
         self.tr('Load Database Model EDGV Version 2.1.3'): '2.1.3',
         self.tr('Load Database Model EDGV Version FTer_2a_Ed'):
         'FTer_2a_Ed',
         self.tr('Load Other Database Models'): 'Non_EDGV'
     }
Example #5
0
 def __init__(self):
     '''
     Constructor
     '''
     super(SpatialiteDb,self).__init__()
     self.db = QSqlDatabase('QSQLITE')
     self.gen = SqlGeneratorFactory().createSqlGenerator(True)
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(CreateInomDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        self.iface = iface
        #Sql factory generator
        self.isSpatialite = True
        self.tabWidget.setCurrentIndex(0)
        self.factory = SqlGeneratorFactory()
        self.gen = self.factory.createSqlGenerator(self.isSpatialite)

        QObject.connect(self.tabWidget, SIGNAL(("currentChanged(int)")), self.restoreInitialState)
        QObject.connect(self.pushButtonOpenFile, SIGNAL(("clicked()")), self.loadDatabase)

        self.restoreInitialState()

        self.db = None
        #populating the postgis combobox
        self.populatePostGISConnectionsCombo()

        self.map_index = UtmGrid()

        self.disableAll()

        self.setValidCharacters()

        self.setMask()
Example #7
0
    def __init__(self, iface):
        """Constructor."""
        super(PostgisDBTool, self).__init__()
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)

        self.iface = iface

        self.populateServersCombo()

        self.srs = None

        self.factory = SqlGeneratorFactory()
        #setting the sql generator
        self.gen = self.factory.createSqlGenerator(False)

        self.epsg = 4326
Example #8
0
    def __init__(self, parent=None):
        """Constructor."""
        super(LoadByClass, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.filename = ""
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.selectedClasses = []

        #Sql factory generator
        self.isSpatialite = True

        self.setupUi(self)
        self.tabWidget.setCurrentIndex(0)
        self.factory = SqlGeneratorFactory()
        self.gen = self.factory.createSqlGenerator(self.isSpatialite)
        self.utils = Utils()

        self.bar = QgsMessageBar()
        self.setLayout(QtGui.QGridLayout(self))
        self.layout().setContentsMargins(0,0,0,0)
        self.layout().setAlignment(QtCore.Qt.AlignTop)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
        self.bar.setSizePolicy(sizePolicy)
        self.layout().addWidget(self.bar, 0,0,1,1)

        #Objects Connections
        QtCore.QObject.connect(self.pushButtonOpenFile, QtCore.SIGNAL(("clicked()")), self.loadDatabase)
        QtCore.QObject.connect(self.pushButtonCancel, QtCore.SIGNAL(("clicked()")), self.cancel)
        QtCore.QObject.connect(self.selectAllCheck, QtCore.SIGNAL(("stateChanged(int)")), self.selectAll)
        QtCore.QObject.connect(self.pushButtonOk, QtCore.SIGNAL(("clicked()")), self.okSelected)
        QtCore.QObject.connect(self.tabWidget,QtCore.SIGNAL(("currentChanged(int)")), self.restoreInitialState)

        self.db = None
        #populating the postgis combobox
        self.populatePostGISConnectionsCombo()
 def __init__(self, parent = None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.setupUi(self)
     self.utils = Utils()
     self.dbFactory = DbFactory()
     self.factory = SqlGeneratorFactory()
     self.serverWidget.populateServersCombo()
     self.serverWidget.abstractDbLoaded.connect(self.populatePostgisSelector)
     self.customFileSelector.filesSelected.connect(self.populateSpatialiteSelector)
     self.comboDict = {self.tr('Load Database Model EDGV Version 2.1.3'):'2.1.3', self.tr('Load Database Model EDGV Version FTer_2a_Ed'):'FTer_2a_Ed',self.tr('Load Other Database Models'):'Non_EDGV'}
     self.dbDict = {'2.1.3':[], 'FTer_2a_Ed':[],'Non_EDGV':[]}
     self.selectedDbsDict = dict()
     self.stylesDict = dict()
     self.postgisCustomSelector.selectionChanged.connect(self.selectedDatabases)
     self.spatialiteCustomSelector.selectionChanged.connect(self.selectedFiles)
     self.path = None
     self.customFileSelector.setCaption(self.tr('Select a DSGTools Spatialite file'))
     self.customFileSelector.setFilter(self.tr('Spatialite file databases (*.sqlite)'))
     self.customFileSelector.setType('multi')
     self.edgvType = None
Example #10
0
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(ComplexWindow, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        #self.enderecoLine.setText('186.228.51.52')
        #self.portaLine.setText('2101'
        self.iface = iface

        QObject.connect(self.dbButton, SIGNAL(("clicked()")), self.getDataSources)
        QObject.connect(self.dbCombo, SIGNAL("activated(int)"), self.updateComplexClass)
        QObject.connect(self.complexCombo, SIGNAL("activated(int)"), self.loadAssociatedFeatures)
        QObject.connect(self.iface, SIGNAL("newProjectCreated()"), self.clearDock)

        self.db = None
        self.databases = None
        self.factory = SqlGeneratorFactory()
        self.gen = None
Example #11
0
class SpatialiteDb(AbstractDb):

    def __init__(self):
        '''
        Constructor
        '''
        super(SpatialiteDb,self).__init__()
        self.db = QSqlDatabase('QSQLITE')
        self.gen = SqlGeneratorFactory().createSqlGenerator(True)
    
    def getDatabaseName(self):
        '''
        Gets the database name
        '''
        return self.db.databaseName().split('.sqlite')[0].split('/')[-1]
    
    def connectDatabase(self, conn = None):
        '''
        Connects to database
        conn: Database name
        '''
        if conn is None:
            self.connectDatabaseWithGui()
        else:
            self.db.setDatabaseName(conn)
    
    def connectDatabaseWithGui(self):
        '''
        Connects to database using user interface dialog
        '''
        fd = QFileDialog()
        filename = fd.getOpenFileName(caption=self.tr('Select a DSGTools Spatialite file'),filter=self.tr('Spatialite file databases (*.sqlite)'))
        self.db.setDatabaseName(filename)
    
    def listGeomClassesFromDatabase(self, primitiveFilter = []):
        '''
        Gets a list with geometry classes from database
        '''
        self.checkAndOpenDb()
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(self.tr("Problem listing geom classes: ")+query.lastError().text())
        while query.next():
            tableName = str(query.value(0))
            layerName = tableName
            if tableName.split("_")[-1] == "p" or tableName.split("_")[-1] == "l" \
                or tableName.split("_")[-1] == "a":
                classList.append(layerName)
        return classList
    
    def listComplexClassesFromDatabase(self):
        '''
        Gets a list with complex classes from database
        '''
        self.checkAndOpenDb()
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(self.tr("Problem listing complex classes: ")+query.lastError().text())
        while query.next():
                tableName = str(query.value(0))
                layerName = tableName
                tableSchema = layerName.split('_')[0]
                if tableSchema == 'complexos': 
                    classList.append(layerName)
        return classList    

    def getStructureDict(self):
        '''
        Gets database structure according to the edgv version
        '''
        self.checkAndOpenDb()
        classDict = dict()
        sql = self.gen.getStructure(self.getDatabaseVersion())        
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(self.tr("Problem getting database structure: ")+query.lastError().text())
        while query.next():
            className = str(query.value(0))
            classSql = str(query.value(1))
            if className.split('_')[0] == 'complexos' or className.split('_')[-1] in ['p','l','a']:
                if className not in classDict.keys():
                    classDict[className]=dict()
                classSql = classSql.split(className)[1]
                sqlList = classSql.replace('(','').replace(')','').replace('\"','').replace('\'','').split(',')
                for s in sqlList:
                     fieldName = str(s.strip().split(' ')[0])
                     classDict[className][fieldName]=fieldName

                if 'GEOMETRY' in classDict[className].keys():
                    classDict[className]['GEOMETRY'] = 'geom'
                if 'geometry' in classDict[className].keys():
                    classDict[className]['geometry'] = 'geom'
                if 'OGC_FID' in classDict[className].keys():
                    classDict[className]['OGC_FID'] = 'id'

        return classDict
    
    def makeOgrConn(self):
        '''
        Makes a connection string for spatialite databases (e.g just the name)
        '''
        constring = self.db.databaseName()
        return constring

    def validateWithOutputDatabaseSchema(self, outputAbstractDb):
        '''
        Validates the conversion with the output database.
        It generates a dictionary (invalidated) that stores conversion problems
        '''
        self.checkAndOpenDb()
        invalidated = self.buildInvalidatedDict()
        inputdbStructure = self.getStructureDict()
        outputdbStructure = outputAbstractDb.getStructureDict()
        domainDict = outputAbstractDb.getDomainDict()
        classes =  self.listClassesWithElementsFromDatabase()
        notNullDict = outputAbstractDb.getNotNullDict()
        
        for inputClass in classes.keys():
            outputClass = self.translateAbstractDbLayerNameToOutputFormat(inputClass,outputAbstractDb)
            (schema,className) = self.getTableSchema(inputClass)
            if outputClass in outputdbStructure.keys():
                outputAttrList = self.reorderTupleList(outputdbStructure[outputClass].keys())
                inputAttrList = self.reorderTupleList(inputdbStructure[inputClass].keys())
                            
                sql = self.gen.getFeaturesWithSQL(inputClass,inputAttrList) 
                query = QSqlQuery(sql, self.db)
                if not query.isActive():
                    self.db.close()
                    raise Exception(self.tr("Problem executing query: ")+query.lastError().text())
                
                while query.next():
                    id = query.value(0)
                    #detects null lines
                    for i in range(len(inputAttrList)):
                        nullLine = True
                        value = query.value(i)
                        if value <> None:
                            nullLine = False
                            break
                    if nullLine:
                        if cl not in invalidated['nullLine'].keys():
                            invalidated['nullLine'][inputClass]=0
                        invalidated['nullLine'][inputClass]+=1
                    
                    #validates pks
                    if id == None and (not nullLine):
                        if cl not in invalidated['nullPk'].keys():
                            invalidated['nullPk'][inputClass]=0
                        invalidated['nullPk'][inputClass]+=1
                    
                    for i in range(len(inputAttrList)):
                        value = query.value(i)
                        #validates domain
                        if outputClass in domainDict.keys():    
                            if inputAttrList[i] in domainDict[outputClass].keys():
                                if value not in domainDict[outputClass][inputAttrList[i]] and (not nullLine):
                                    invalidated = self.utils.buildNestedDict(invalidated, ['notInDomain',inputClass,id,inputAttrList[i]], value)
                        #validates not nulls
                        if outputClass in notNullDict.keys():
                            if outputClass in domainDict.keys():
                                if inputAttrList[i] in notNullDict[outputClass] and inputAttrList[i] not in domainDict[outputClass].keys():
                                    if (value == None) and (not nullLine) and (inputAttrList[i] not in domainDict[outputClass].keys()):
                                        invalidated = self.utils.buildNestedDict(invalidated, ['nullAttribute',inputClass,id,inputAttrList[i]], value)             
                            else:
                                if inputAttrList[i] in notNullDict[outputClass]:
                                    try:
                                        if value.isNull():
                                            invalidated = self.utils.buildNestedDict(invalidated, ['nullAttribute',inputClass,id,inputAttrList[i]], value)
                                    except:
                                        if (value == None) and (not nullLine) and (inputAttrList[i] not in domainDict[outputClass].keys()):
                                            invalidated = self.utils.buildNestedDict(invalidated, ['nullAttribute',inputClass,id,inputAttrList[i]], value)
                        if outputClass in domainDict.keys():
                            if (inputAttrList[i] not in ['geom','GEOMETRY','geometry','id','OGC_FID'] and schema <> 'complexos') or (schema == 'complexos' and inputAttrList[i] <> 'id'):
                                if inputAttrList[i] not in outputdbStructure[outputClass].keys():
                                    invalidated = self.utils.buildNestedDict(invalidated, ['attributeNotFoundInOutput',inputClass], [inputAttrList[i]])
                        #validates fk field
                        if 'id_' == inputAttrList[0:3]:
                            if not self.validateUUID(value):
                                if inputAttrList[i] not in outputdbStructure[outputClass].keys():
                                    invalidated = self.utils.buildNestedDict(invalidated, ['nullComplexFk',inputClass], [inputAttrList[i]])
            else:
                invalidated['classNotFoundInOutput'].append(inputAttrList)
        return invalidated
    
    def translateAbstractDbLayerNameToOutputFormat(self, lyr, outputAbstractDb):
        '''
        Translates abstractdb layer name to output format
        lyr: layer name that will be translated
        outputAbstractDb: output database
        '''
        if outputAbstractDb.db.driverName() == 'QSQLITE':
            return lyr
        if outputAbstractDb.db.driverName() == 'QPSQL':
            return str(lyr.split('_')[0]+'.'+'_'.join(lyr.split('_')[1::]))
    
    def translateOGRLayerNameToOutputFormat(self, lyr, ogrOutput):
        '''
        Translates ogr layer name to output format
        lyr: layer name that will be translated
        ogrOutput: ogr output
        '''
        if ogrOutput.GetDriver().name == 'SQLite':
            return lyr
        if ogrOutput.GetDriver().name == 'PostgreSQL':
            return str(lyr.split('_')[0]+'.'+'_'.join(lyr.split('_')[1::]))
    
    def getTableSchema(self,lyr):
        '''
        Gets the table schema
        lyr: layer name
        '''
        schema = lyr.split('_')[0]
        className = '_'.join(lyr.split('_')[1::])
        return (schema, className)
    
    def convertToPostgis(self, outputAbstractDb, type=None):
        '''
        Converts this to a postgis database
        outputAbstractDb: postgis output
        type: conversion type
        '''
        (inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict) = self.prepareForConversion(outputAbstractDb)
        invalidated = self.validateWithOutputDatabaseSchema(outputAbstractDb)
        hasErrors = self.makeValidationSummary(invalidated)
        if type == 'untouchedData':
            if hasErrors:
                self.signals.updateLog.emit('\n\n\n'+self.tr('Conversion not perfomed due to validation errors! Check log above for more information.'))
                return False
            else:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict)
                return status
        if type == 'fixData':
            if hasErrors:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict, invalidated)
                return status
            else:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict)
                return status
        return False
    
    def getDatabaseVersion(self):
        '''
        Gets the database version
        '''
        self.checkAndOpenDb()
        version = '2.1.3'
        sql = self.gen.getEDGVVersion()
        query = QSqlQuery(sql, self.db)
        # if not query.isActive():
        #     raise Exception(self.tr("Problem getting database version: ")+query.lastError().text())
        while query.next():
            version = query.value(0)
        return version
    
    def obtainLinkColumn(self, complexClass, aggregatedClass):
        '''
        Obtains the link column between complex and aggregated class
        complexClass: complex class name
        aggregatedClass: aggregated class name
        '''
        self.checkAndOpenDb()
        #query to obtain the link column between the complex and the feature layer
        sql = self.gen.getLinkColumn(complexClass.replace('complexos_', ''), aggregatedClass)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(self.tr("Problem obtaining link column: ")+query.lastError().text())
        column_name = ""
        while query.next():
            column_name = query.value(0)
        return column_name

    def loadAssociatedFeatures(self, complex):
        '''
        Loads all the features associated to the complex 
        complex: complex class name
        '''
        self.checkAndOpenDb()
        associatedDict = dict()
        #query to get the possible links to the selected complex in the combobox
        complexName = complex.replace('complexos_', '')
        sql = self.gen.getComplexLinks(complexName)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(self.tr("Problem loading associated features: ")+query.lastError().text())

        while query.next():
            #setting the variables
            complex_schema = query.value(0)
            complex = query.value(1)
            aggregated_schema = query.value(2)
            aggregated_class = query.value(3)
            column_name = query.value(4)
            
            if aggregated_class.split('_')[-1] not in ['p', 'l', 'a']:
                continue

            #query to obtain the created complexes
            sql = self.gen.getComplexData(complex_schema, complex)
            complexQuery = QSqlQuery(sql, self.db)
            if not complexQuery.isActive():
                self.db.close()
                raise Exception(self.tr("Problem executing query: ")+complexQuery.lastError().text())

            while complexQuery.next():
                complex_uuid = complexQuery.value(0)
                name = complexQuery.value(1)

                if not (complex_uuid and name):
                    continue

                associatedDict = self.utils.buildNestedDict(associatedDict, [name, complex_uuid, aggregated_class], [])

                #query to obtain the id of the associated feature
                sql = self.gen.getAssociatedFeaturesData(aggregated_schema, aggregated_class, column_name, complex_uuid)
                associatedQuery = QSqlQuery(sql, self.db)
                if not associatedQuery.isActive():
                    self.db.close()
                    raise Exception(self.tr("Problem executing query: ")+associatedQuery.lastError().text())

                while associatedQuery.next():
                    ogc_fid = associatedQuery.value(0)
                    associatedDict = self.utils.buildNestedDict(associatedDict, [name, complex_uuid, aggregated_class], [ogc_fid])
        return associatedDict
    
    def isComplexClass(self, className):
        '''
        Checks if a class is a complex class
        className: class name to be checked
        '''
        self.checkAndOpenDb()
        #getting all complex tables
        query = QSqlQuery(self.gen.getComplexTablesFromDatabase(), self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(self.tr("Problem executing query: ")+query.lastError().text())

        while query.next():
            if query.value(0) == 'complexos_'+className:
                return True
        return False

    def disassociateComplexFromComplex(self, aggregated_class, link_column, id):
        '''
        Disassociates a complex from another complex
        aggregated_class: aggregated class that will be disassociated
        link_column: link column between complex and its aggregated class
        id: complex id (uid) to be disassociated
        '''
        sql = self.gen.disassociateComplexFromComplex('complexos_'+aggregated_class, link_column, id)
        query = QSqlQuery(self.db)
        if not query.exec_(sql):
            self.db.close()
            raise Exception(self.tr('Problem disassociating complex from complex: ') + '\n' + query.lastError().text())

    def getTablesFromDatabase(self):
        '''
        Gets all tables from database
        '''
        self.checkAndOpenDb()
        ret = []

        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(self.tr("Problem getting tables from database: ")+query.lastError().text())

        while query.next():
            #table name
            ret.append(query.value(0))
        return ret

    def getFrameLayerName(self):
        '''
        Gets the frame layer name
        '''
        return 'public_aux_moldura_a'

    def getOrphanGeomTablesWithElements(self, loading = False):
        return []
    
    def getOrphanGeomTables(self):
        return []
    
    def checkAndCreateStyleTable(self):
        return None

    def getStylesFromDb(self,dbVersion):
        return None

    def getGeomTypeDict(self, loadCentroids=False):
        self.checkAndOpenDb()
        edgvVersion = self.getDatabaseVersion()
        sql = self.gen.getGeomByPrimitive(edgvVersion)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(self.tr("Problem getting geom types from db: ")+query.lastError().text())
        geomDict = dict()
        while query.next():
            if edgvVersion in ('2.1.3','FTer_2a_Ed'):
                type = query.value(0)
            else:
                type = self.getResolvedGeomType(query.value(0))
            tableName = query.value(1)
            layerName = '_'.join(tableName.split('_')[1::])
            if type not in geomDict.keys():
                geomDict[type] = []
            if layerName not in geomDict[type]:
                geomDict[type].append(layerName)
        return geomDict
    
    def getGeomDict(self, getCentroids = False):
        '''
        returns a dict like this:
        {'tablePerspective' : {
            'layerName' :
        '''
        self.checkAndOpenDb()
        edgvVersion = self.getDatabaseVersion()
        sql = self.gen.getGeomTablesFromGeometryColumns(edgvVersion)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(self.tr("Problem getting geom tables from db: ")+query.lastError().text())
        geomDict = dict()
        geomDict['primitivePerspective'] = self.getGeomTypeDict()
        geomDict['tablePerspective'] = dict()
        while query.next():
            isCentroid = False
            srid = query.value(0)
            if edgvVersion in ('2.1.3','FTer_2a_Ed'):
                geometryType = query.value(2)
            else:
                geometryType = self.getResolvedGeomType(query.value(2))
            tableName = query.value(3)
            tableSchema = tableName.split('_')[0]
            geometryColumn = query.value(1)
            layerName = '_'.join(tableName.split('_')[1::])
            if layerName not in geomDict['tablePerspective'].keys():
                geomDict['tablePerspective'][layerName] = dict()
                geomDict['tablePerspective'][layerName]['schema'] = tableSchema
                geomDict['tablePerspective'][layerName]['srid'] = str(srid)
                geomDict['tablePerspective'][layerName]['geometryColumn'] = geometryColumn
                geomDict['tablePerspective'][layerName]['geometryType'] = geometryType
                geomDict['tablePerspective'][layerName]['tableName'] = tableName
        return geomDict
    
    def getGeomColumnDict(self):
        '''
        Dict in the form 'geomName':[-list of table names-]
        '''
        self.checkAndOpenDb()
        sql = self.gen.getGeomColumnDict()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(self.tr("Problem getting geom column dict: ")+query.lastError().text())
        geomDict = dict()
        while query.next():
            geomColumn = query.value(0)
            tableName = query.value(1)
            lyrName = '_'.join(tableName.split('_')[1::])
            if geomColumn not in geomDict.keys():
                geomDict[geomColumn] = []
            geomDict[geomColumn].append(lyrName)
        return geomDict

    def createFrame(self, type, scale, param, paramDict = dict()):
        mi, inom, frame = self.prepareCreateFrame(type, scale, param)
        self.insertFrame(scale, mi, inom, frame.asWkb())
        return frame
    
    def insertFrame(self, scale, mi, inom, frame):
        self.checkAndOpenDb()
        srid = self.findEPSG()
        geoSrid = QgsCoordinateReferenceSystem(int(srid)).geographicCRSAuthId().split(':')[-1]
        ogr.UseExceptions()
        outputDS = self.buildOgrDatabase()
        outputLayer=outputDS.GetLayerByName('public_aux_moldura_a')
        newFeat=ogr.Feature(outputLayer.GetLayerDefn())
        auxGeom = ogr.CreateGeometryFromWkb(frame)
        #set geographic srid from frame
        geoSrs = ogr.osr.SpatialReference()
        geoSrs.ImportFromEPSG(int(geoSrid))
        auxGeom.AssignSpatialReference(geoSrs)
        #reproject geom
        outSpatialRef = outputLayer.GetSpatialRef()
        coordTrans = osr.CoordinateTransformation(geoSrs, outSpatialRef)
        auxGeom.Transform(coordTrans)
        newFeat.SetGeometry(auxGeom)
        newFeat.SetField('mi', mi)
        newFeat.SetField('inom', inom)
        newFeat.SetField('escala', str(scale))
        out=outputLayer.CreateFeature(newFeat)
        outputDS.Destroy()
    
    def getTableSchemaFromDb(self, table):
        self.checkAndOpenDb()
        sql = self.gen.getFullTablesName(table)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(self.tr("Problem getting full table name: ")+query.lastError().text())
        while query.next():
            return query.value(0).split('_')[0]
    
    def getGeomColumnTupleList(self, showViews = False):
        """
        list in the format [(table_schema, table_name, geometryColumn, geometryType, tableType)]
        centroids are hidden by default
        """
        self.checkAndOpenDb()
        edgvVersion = self.getDatabaseVersion()
        sql = self.gen.getGeomColumnTupleList(edgvVersion)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(self.tr("Problem getting geom tuple list: ")+query.lastError().text())
        geomList = []
        while query.next():
            if edgvVersion in ['2.1.3','FTer_2a_Ed']:
                geomList.append((query.value(0).split('_')[0], '_'.join(query.value(0).split('_')[1::]), query.value(1), query.value(2), 'BASE TABLE'))
            else:
                geomList.append((query.value(0).split('_')[0], '_'.join(query.value(0).split('_')[1::]), query.value(1), self.getResolvedGeomType(int(query.value(2))), 'BASE TABLE'))
        return geomList
    
    def getResolvedGeomType(self, geometryType):
        geomDict = {0:'GEOMETRY',
                    1:'POINT',
                    2:'LINESTRING',
                    3:'POLYGON',
                    4:'MULTIPOINT',
                    5:'MULTILINESTRING',
                    6:'MULTIPOLYGON',
                    7:'GEOMETRYCOLLECTION',
                    8:'CIRCULARSTRING',
                    9:'COMPOUNDCURVE',
                    10:'CURVEPOLYGON',
                    11:'MULTICURVE',
                    12:'MULTISURFACE',
                    13:'CURVE',
                    14:'SURFACE'}
        return geomDict[geometryType]
Example #12
0
class LoadByCategory(QtGui.QDialog, load_by_category_dialog.Ui_LoadByCategory):
    def __init__(self, parent=None):
        """Constructor."""
        super(LoadByCategory, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.filename = ""
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.categories = []
        self.selectedClasses = []

        self.point = []
        self.line = []
        self.polygon = []
        self.pointWithElement = []
        self.lineWithElement = []
        self.polygonWithElement = []

        #Sql factory generator
        self.isSpatialite = True

        self.setupUi(self)
        self.tabWidget.setCurrentIndex(0)
        self.factory = SqlGeneratorFactory()
        self.gen = self.factory.createSqlGenerator(self.isSpatialite)
        self.utils = Utils()

        self.parentTreeNode = None

        self.comboBoxPostgis.setCurrentIndex(0)
        self.checkBoxPoint.setCheckState(0)
        self.checkBoxLine.setCheckState(0)
        self.checkBoxPolygon.setCheckState(0)
        self.checkBoxAll.setCheckState(0)

        self.bar = QgsMessageBar()
        self.setLayout(QtGui.QGridLayout(self))
        self.layout().setContentsMargins(0,0,0,0)
        self.layout().setAlignment(QtCore.Qt.AlignTop)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
        self.bar.setSizePolicy(sizePolicy)
        self.layout().addWidget(self.bar, 0,0,1,1)

        #Objects Connections
        QtCore.QObject.connect(self.pushButtonOpenFile, QtCore.SIGNAL(("clicked()")), self.loadDatabase)
        QtCore.QObject.connect(self.pushButtonCancel, QtCore.SIGNAL(("clicked()")), self.cancel)
        QtCore.QObject.connect(self.pushButtonOk, QtCore.SIGNAL(("clicked()")), self.okSelected)
        QtCore.QObject.connect(self.tabWidget,QtCore.SIGNAL(("currentChanged(int)")), self.restoreInitialState)
        QtCore.QObject.connect(self.pushButtonSelectAll, QtCore.SIGNAL(("clicked()")), self.selectAll)
        QtCore.QObject.connect(self.pushButtonDeselectAll, QtCore.SIGNAL(("clicked()")), self.deselectAll)
        QtCore.QObject.connect(self.pushButtonSelectOne, QtCore.SIGNAL(("clicked()")), self.selectOne)
        QtCore.QObject.connect(self.pushButtonDeselectOne, QtCore.SIGNAL(("clicked()")), self.deselectOne)
        QtCore.QObject.connect(self.checkBoxAll, QtCore.SIGNAL(("stateChanged(int)")), self.setAllGroup)

        self.db = None
        #populating the postgis combobox
        self.populatePostGISConnectionsCombo()

    def __del__(self):
        self.closeDatabase()

    def closeDatabase(self):
        if self.db:
            self.db.close()
            self.db = None

    def restoreInitialState(self):
        self.filename = ""
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.categories = []
        self.selectedClasses = []
        self.spatialiteFileEdit.setText(self.filename)
        self.postGISCrsEdit.setText('')
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setText('')
        self.spatialiteCrsEdit.setReadOnly(True)
        self.listWidgetCategoryFrom.clear()
        self.listWidgetCategoryTo.clear()

        self.point = []
        self.line = []
        self.polygon = []
        self.pointWithElement = []
        self.lineWithElement = []
        self.polygonWithElement = []
        self.parentTreeNode = None

        #Setting the database type
        if self.tabWidget.currentIndex() == 0:
            self.isSpatialite = True
        else:
            self.isSpatialite = False

        #getting the sql generator according to the database type
        self.gen = self.factory.createSqlGenerator(self.isSpatialite)
        self.comboBoxPostgis.setCurrentIndex(0)
        self.checkBoxPoint.setCheckState(0)
        self.checkBoxLine.setCheckState(0)
        self.checkBoxPolygon.setCheckState(0)
        self.checkBoxAll.setCheckState(0)

    def updateBDField(self):
        if self.dbLoaded == True:
            self.spatialiteFileEdit.setText(self.filename)
        else:
            self.filename = ""
            self.spatialiteFileEdit.setText(self.filename)

    def getDatabaseVersion(self):
        self.dbVersion = self.utils.getDatabaseVersion(self.db)
        self.qmlPath = self.utils.getQmlDir(self.db)

    def listCategoriesFromDatabase(self):
        self.listWidgetCategoryFrom.clear()
        self.listWidgetCategoryTo.clear()
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)

        self.getDatabaseVersion()

        while query.next():
            if self.isSpatialite:
                tableName = query.value(0)
                layerName = tableName
                split = tableName.split('_')
                if len(split) < 2:
                    continue
                if self.dbVersion == '3.0' or self.dbVersion == '2.1.3':
                    schema = split[0]
                    category = split[1]
                    categoryName = schema+'.'+category
                else:
                    categoryName = split[0] #done this way to have back compatibility with spatialites already in production

            else:
                tableSchema = query.value(0)
                tableName = query.value(1)
                split = tableName.split('_')
                category = split[0]
                categoryName = tableSchema+'.'+category
                layerName = tableSchema+'.'+tableName

            if layerName.split("_")[-1] == "p":
                self.point.append(layerName)
            if layerName.split("_")[-1] == "l":
                self.line.append(layerName)
            if layerName.split("_")[-1] == "a":
                self.polygon.append(layerName)

            if tableName.split("_")[-1] == "p" or tableName.split("_")[-1] == "l" \
                or tableName.split("_")[-1] == "a":
                self.insertIntoListView(categoryName)
        self.listWidgetCategoryFrom.sortItems()
        self.setCRS()

    def insertIntoListView(self, item_name):
        found = self.listWidgetCategoryFrom.findItems(item_name, Qt.MatchExactly)
        if len(found) == 0:
            item = QtGui.QListWidgetItem(item_name)
            self.listWidgetCategoryFrom.addItem(item)

    def selectAll(self):
        tam = self.listWidgetCategoryFrom.__len__()
        for i in range(tam+1,1,-1):
            item = self.listWidgetCategoryFrom.takeItem(i-2)
            self.listWidgetCategoryTo.addItem(item)
        self.listWidgetCategoryTo.sortItems()

    def deselectAll(self):
        tam = self.listWidgetCategoryTo.__len__()
        for i in range(tam+1,1,-1):
            item = self.listWidgetCategoryTo.takeItem(i-2)
            self.listWidgetCategoryFrom.addItem(item)
        self.listWidgetCategoryFrom.sortItems()

    def selectOne(self):
        listedItems = self.listWidgetCategoryFrom.selectedItems()
        for i in listedItems:
            item = self.listWidgetCategoryFrom.takeItem(self.listWidgetCategoryFrom.row(i))
            self.listWidgetCategoryTo.addItem(item)
        self.listWidgetCategoryTo.sortItems()

    def deselectOne(self):
        listedItems = self.listWidgetCategoryTo.selectedItems()
        for i in listedItems:
            item = self.listWidgetCategoryTo.takeItem(self.listWidgetCategoryTo.row(i))
            self.listWidgetCategoryFrom.addItem(item)
        self.listWidgetCategoryFrom.sortItems()


    def setAllGroup(self):
        if self.checkBoxAll.isChecked():
            self.checkBoxPoint.setCheckState(2)
            self.checkBoxLine.setCheckState(2)
            self.checkBoxPolygon.setCheckState(2)
        else:
            self.checkBoxPoint.setCheckState(0)
            self.checkBoxLine.setCheckState(0)
            self.checkBoxPolygon.setCheckState(0)

    def setCRS(self):
        try:
            self.epsg = self.utils.findEPSG(self.db)
            if self.epsg == -1:
                self.bar.pushMessage("", self.tr("Coordinate Reference System not set or invalid!"), level=QgsMessageBar.WARNING)
            else:
                self.crs = QgsCoordinateReferenceSystem(self.epsg, QgsCoordinateReferenceSystem.EpsgCrsId)
                if self.isSpatialite:
                    self.spatialiteCrsEdit.setText(self.crs.description())
                    self.spatialiteCrsEdit.setReadOnly(True)
                else:
                    self.postGISCrsEdit.setText(self.crs.description())
                    self.postGISCrsEdit.setReadOnly(True)
        except:
            pass

    @pyqtSlot(int)
    def on_comboBoxPostgis_currentIndexChanged(self):
        if self.comboBoxPostgis.currentIndex() > 0:
            self.loadDatabase()

    def loadDatabase(self):
        self.closeDatabase()

        if self.isSpatialite:
            (self.filename, self.db) = self.utils.getSpatialiteDatabase()
            if self.filename:
                self.spatialiteFileEdit.setText(self.filename)
        else:
            self.db = self.utils.getPostGISDatabase(self.comboBoxPostgis.currentText())
        try:
            if not self.db.open():
                QgsMessageLog.logMessage(self.db.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            else:
                self.dbLoaded = True
                self.listCategoriesFromDatabase()
        except:
            pass

    def populatePostGISConnectionsCombo(self):
        self.comboBoxPostgis.clear()
        self.comboBoxPostgis.addItem("Select Database")
        self.comboBoxPostgis.addItems(self.utils.getPostGISConnections())

    def cancel(self):
        self.restoreInitialState()
        self.close()

    def getSelectedItems(self):
        lista = self.classesListWidget.selectedItems()
        self.selectedClasses = []
        tam = len(lista)
        for i in range(tam):
            self.selectedClasses.append(lista[i].text())
        self.selectedClasses.sort()

    def okSelected(self):
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

            if self.checkBoxOnlyWithElements.isChecked():
                self.setLayersWithElements()
                ponto = self.pointWithElement
                linha = self.lineWithElement
                area = self.polygonWithElement
            else:
                ponto = self.point
                linha = self.line
                area = self.polygon

            if self.db and self.crs and len(self.listWidgetCategoryTo)>0:
                categoriasSelecionadas = []
                for i in range(self.listWidgetCategoryTo.__len__()):
                    categoriasSelecionadas.append(self.listWidgetCategoryTo.item(i).text())

                try:
                    if self.checkBoxPoint.isChecked():
                        self.loadLayers('p',categoriasSelecionadas,ponto)
                    if self.checkBoxLine.isChecked():
                        self.loadLayers('l',categoriasSelecionadas,linha)
                    if self.checkBoxPolygon.isChecked():
                        self.loadLayers('a',categoriasSelecionadas,area)
                    if self.checkBoxPoint.isChecked()== False and self.checkBoxLine.isChecked() == False and self.checkBoxPolygon.isChecked() == False:
                        self.bar.pushMessage(self.tr("WARNING!"), self.tr("Please, select at least one type of layer!"), level=QgsMessageBar.WARNING)
                    else:
                        self.restoreInitialState()
                        self.close()
                except:
                    qgis.utils.iface.messageBar().pushMessage(self.tr("CRITICAL!"), self.tr("Problem loading the categories!"), level=QgsMessageBar.CRITICAL)
                    pass
            else:
                if self.db and not self.crs:
                    self.bar.pushMessage(self.tr("CRITICAL!"), self.tr("Could not determine the coordinate reference system!"), level=QgsMessageBar.CRITICAL)
                if not self.db and not self.crs:
                    self.bar.pushMessage(self.tr("CRITICAL!"), self.tr("Database not loaded properly!"), level=QgsMessageBar.CRITICAL)
                    self.bar.pushMessage(self.tr("CRITICAL!"), self.tr("Could not determine the coordinate reference system!"), level=QgsMessageBar.CRITICAL)
                if len(self.listWidgetCategoryTo)==0:
                    self.bar.pushMessage(self.tr("WARNING!"), self.tr("Please, select at least one category!"), level=QgsMessageBar.WARNING)
                categoriasSelecionadas = []
                self.pointWithElement = []
                self.lineWithElement = []
                self.polygonWithElement = []

            QApplication.restoreOverrideCursor()
        except:
            QApplication.restoreOverrideCursor()

    def loadLayers(self, type, categories, layer_names):
        if self.isSpatialite:
            self.loadSpatialiteLayers(type, categories, layer_names)
        else:

            self.loadPostGISLayers(type, categories, layer_names)

    def setLayersWithElements(self):
        self.pointWithElement = []
        self.lineWithElement = []
        self.polygonWithElement = []

        pontoAux = self.countElements(self.point)
        linhaAux = self.countElements(self.line)
        areaAux = self.countElements(self.polygon)

        for i in pontoAux:
            if i[1] > 0:
                self.pointWithElement.append(i[0])

        for i in linhaAux:
            if i[1] > 0:
                self.lineWithElement.append(i[0])

        for i in areaAux:
            if i[1] > 0:
                self.polygonWithElement.append(i[0])

    def countElements(self, layers):
        listaQuantidades = []
        for layer in layers:
            sql = self.gen.getElementCountFromLayer(layer)
            query = QSqlQuery(sql,self.db)
            query.next()
            number = query.value(0)
            if not query.exec_(sql):
                QgsMessageLog.logMessage(self.tr("Problem counting elements: ")+query.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            listaQuantidades.append([layer, number])
        return listaQuantidades

    def loadPostGISLayers(self, type, categories, layer_names):
        (database, host, port, user, password) = self.utils.getPostGISConnectionParameters(self.comboBoxPostgis.currentText())
        uri = QgsDataSourceURI()
        uri.setConnection(str(host),str(port), str(database), str(user), str(password))
        geom_column = 'geom'
        if self.parentTreeNode is None:
            self.parentTreeNode = qgis.utils.iface.legendInterface (). addGroup (database, -1)

        if type == 'p':
            idGrupo = qgis.utils.iface.legendInterface (). addGroup ("Ponto", True,self.parentTreeNode)
            for categoria in categories:
                self.preparePostGISToLoad(uri, categoria, layer_names, idGrupo, geom_column)
        if type == 'l':
            idGrupo = qgis.utils.iface.legendInterface (). addGroup ("Linha", True,self.parentTreeNode)
            for categoria in categories:
                self.preparePostGISToLoad(uri, categoria, layer_names, idGrupo, geom_column)
        if type == 'a':
            idGrupo = qgis.utils.iface.legendInterface (). addGroup ("Area", True,self.parentTreeNode)
            for categoria in categories:
                self.preparePostGISToLoad(uri, categoria, layer_names, idGrupo, geom_column)

    def preparePostGISToLoad(self, uri, categoria, layer_names, idGrupo, geom_column):
        idSubgrupo = qgis.utils.iface.legendInterface().addGroup(categoria, True, idGrupo)
        layer_names.sort(reverse=True)
        for layer_name in layer_names:
            split = layer_name.split('_')
            category = split[0]
            schema = category.split('.')[0]
            name = layer_name.replace(schema+'.', '')
            if category == categoria:
                sql = self.gen.loadLayerFromDatabase(layer_name)
                uri.setDataSource(schema, name, geom_column, sql, 'id')
                uri.disableSelectAtId(True)
                self.loadEDGVLayer(uri, name, 'postgres', idSubgrupo)

    def prepareSpatialiteToLoad(self, uri, categoria, layer_names, idGrupo, geom_column):
        idSubgrupo = qgis.utils.iface.legendInterface().addGroup(categoria, True, idGrupo)
        layer_names.sort(reverse=True)
        for layer_name in layer_names:
            split = layer_name.split('_')
            if self.dbVersion == '3.0' or self.dbVersion == '2.1.3':
                category = split[0]+'.'+split[1]
            else:
                category = split[0]
            if category == categoria:
                uri.setDataSource('', layer_name, geom_column)
                self.loadEDGVLayer(uri, layer_name, 'spatialite', idSubgrupo)

    def loadSpatialiteLayers(self, type, categories, layer_names):
        uri = QgsDataSourceURI()
        uri.setDatabase(self.filename)
        geom_column = 'GEOMETRY'

        if self.parentTreeNode is None:
            self.parentTreeNode = qgis.utils.iface.legendInterface(). addGroup(self.filename.split('.sqlite')[0].split('/')[-1], -1)

        if type == 'p':
            idGrupo = qgis.utils.iface.legendInterface(). addGroup("Ponto", True, self.parentTreeNode)
            for categoria in categories:
                self.prepareSpatialiteToLoad(uri, categoria, layer_names, idGrupo, geom_column)
        if type == 'l':
            idGrupo = qgis.utils.iface.legendInterface(). addGroup("Linha", True, self.parentTreeNode)
            for categoria in categories:
                self.prepareSpatialiteToLoad(uri, categoria, layer_names, idGrupo, geom_column)
        if type == 'a':
            idGrupo = qgis.utils.iface.legendInterface(). addGroup("Area", True, self.parentTreeNode)
            for categoria in categories:
                self.prepareSpatialiteToLoad(uri, categoria, layer_names, idGrupo, geom_column)

    def loadEDGVLayer(self, uri, layer_name, provider, idSubgrupo):
        vlayer = QgsVectorLayer(uri.uri(), layer_name, provider)
        vlayer.setCrs(self.crs)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer) #added due to api changes
        if self.isSpatialite and (self.dbVersion == '3.0' or self.dbVersion == '2.1.3'):
            lyr = '_'.join(layer_name.replace('\r', '').split('_')[1::])
        else:
            lyr = layer_name.replace('\r','')
        vlayerQml = os.path.join(self.qmlPath, lyr+'.qml')
        vlayer.loadNamedStyle(vlayerQml, False)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer)
        qgis.utils.iface.legendInterface().moveLayer(vlayer, idSubgrupo)
        if not vlayer.isValid():
            QgsMessageLog.logMessage(vlayer.error().summary(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
Example #13
0
class PostgisDBTool(QDialog, FORM_CLASS):
    def __init__(self, iface):
        """Constructor."""
        super(PostgisDBTool, self).__init__()
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)

        self.iface = iface

        self.populateServersCombo()

        self.srs = None
        self.db = None
        self.abstractDb = None
        self.factory = SqlGeneratorFactory()
        #setting the sql generator
        self.gen = self.factory.createSqlGenerator(False)

        self.epsg = 4326

    def getParameters(self):
        """
        Gets database parameters
        """
        return (self.databaseEdit.text(), self.abstractDb, self.versionCombo.currentText(), self.epsg)

    @pyqtSlot(bool)
    def on_saveButton_clicked(self):
        """
        Creates a postgis database
        """
        if self.databaseEdit.text() == '':
            QgsMessageLog.logMessage('Enter database name!', "DSG Tools Plugin", QgsMessageLog.CRITICAL)
        else:
            self.db = self.getDatabase()
            if self.db:
                self.storeConnectionConfiguration(self.serversCombo.currentText(), self.databaseEdit.text())
                self.done(1)


    @pyqtSlot(bool)
    def on_cancelButton_clicked(self):
        """
        Cancels everything
        """
        self.done(-1)

    @pyqtSlot(bool)
    def on_configureServerButton_clicked(self):
        """
        Opens the ViewServer dialog
        """
        dlg = ViewServers(self.iface)
        dlg.show()
        result = dlg.exec_()
        self.populateServersCombo()

    @pyqtSlot(bool)
    def on_srsButton_clicked(self):
        """
        Opens the CRS selector dialog
        """
        projSelector = QgsGenericProjectionSelector()
        message = 'Select the Spatial Reference System!'
        projSelector.setMessage(theMessage=message)
        projSelector.exec_()
        try:
            self.epsg = int(projSelector.selectedAuthId().split(':')[-1])
            srs = QgsCoordinateReferenceSystem(self.epsg, QgsCoordinateReferenceSystem.EpsgCrsId)
            if srs:
                self.srsEdit.setText(srs.description())
            else:
                self.epsg = 4326
        except:
            QMessageBox.warning(self, self.tr("Warning!"), message)


    def createDatabase(self, name):
        """
        Creates the database
        """
        sql = self.gen.getCreateDatabase(name)

        db = self.getDatabase()

        #creating the database
        query = QSqlQuery(db)
        if not query.exec_(sql):
            QMessageBox.warning(self, self.tr("Warning!"), query.lastError().text())
            db.close()
            return False
        db.close()
        return True

    def getDatabase(self, database = 'postgres'):
        """
        Gets a a QSqlDatabase 
        """
        (host, port, user, password) = self.getServerConfiguration(self.serversCombo.currentText())
        self.abstractDb = DbFactory().createDbFactory('QPSQL')

        if password == '':
            conInfo = 'host='+host+' port='+port+' dbname='+database
            self.setCredentials(self.abstractDb.db, conInfo, user)
        else:
            self.abstractDb.connectDatabaseWithParameters(host, port, database, user, password)

        if not self.abstractDb.db.open():
            QgsMessageLog.logMessage(self.abstractDb.db.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)

        return self.abstractDb

    def setCredentials(self, db, conInfo, user):
        """
        Sets connection credentials
        db: QSqlDatabase used
        conInfo: connection information
        user: user name
        """
        (success, user, password) = QgsCredentials.instance().get(conInfo, user, None)
        if not success:
            return
        else:
            db.setPassword(password)
            db.setUserName(user)
            if not db.open():
                self.setCredentials(db, conInfo, user)
            else:
                QgsCredentials.instance().put(conInfo, user, password)

    def updateConnectionName(self):
        """
        Updates connection name
        """
        server = self.serversCombo.currentText()
        database = self.databaseEdit.text()
        name = server+'_'+database
        self.connectionEdit.setText(name)

    def on_serversCombo_currentIndexChanged(self, index):
        """
        Slot to update the connection name
        """
        self.updateConnectionName()

    def on_databaseEdit_textEdited(self, text):
        """
        Adjusts the text before updating the connection name
        """
        self.updateConnectionName()

    def checkFields(self):
        """
        Check fields prior the next step
        """
        if self.serversCombo.currentText() == '' or self.databaseEdit.text() == '' or self.srsEdit.text() == '':
            return False
        return True

    def getServerConfiguration(self, name):
        """
        Gets server configuration from QSettings
        name: server name
        """
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers/'+name)
        host = settings.value('host')
        port = settings.value('port')
        user = settings.value('username')
        password = settings.value('password')
        settings.endGroup()
        return (host, port, user, password)

    def storeConnectionConfiguration(self, server, database):
        """
        Stores the new configuration
        server: server name
        database: database name
        """
        name = self.connectionEdit.text()

        (host, port, user, password) = self.getServerConfiguration(server)

        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections/'+name)
        settings.setValue('database', database)
        settings.setValue('host', host)
        settings.setValue('port', port)
        settings.setValue('username', user)
        settings.setValue('password', password)
        settings.endGroup()

    def getServers(self):
        """
        Gets all servers from QSettings
        """
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers')
        currentConnections = settings.childGroups()
        settings.endGroup()
        return currentConnections

    def populateServersCombo(self):
        """
        Populates the server combo box
        """
        self.serversCombo.clear()
        currentConnections = self.getServers()
        for connection in currentConnections:
            self.serversCombo.addItem(connection)
Example #14
0
class PostgisDbThread(GenericThread):
    def __init__(self, parent = None):
        """
        Constructor.
        """
        super(PostgisDbThread, self).__init__()

        self.factory = SqlGeneratorFactory()
        #setting the sql generator
        self.gen = self.factory.createSqlGenerator(False)
        self.messenger = PostgisDbMessages(self)
        self.dbFactory = DbFactory()
        self.parent = parent

    def setParameters(self, abstractDb, dbName, version, epsg, stopped):
        """
        Sets thread parameters
        """
        self.abstractDb = abstractDb #database = postgis
        self.dbName = dbName
        self.db = None  
        self.version = version
        self.epsg = epsg
        self.stopped = stopped

    def run(self):
        """
        Runs the process
        """
        # Processing ending
        (ret, msg) = self.createDatabaseStructure()
        self.signals.processingFinished.emit(ret, msg, self.getId())

    def connectToTemplate(self, setInnerDb = True):
        """
        Connects to the template database to speed up database creation
        :return:
        """
        database = self.abstractDb.getTemplateName(self.version)
        host = self.abstractDb.db.hostName()
        port = self.abstractDb.db.port()
        user = self.abstractDb.db.userName()
        password = self.abstractDb.db.password()
        template = self.dbFactory.createDbFactory('QPSQL')
        template.connectDatabaseWithParameters(host, port, database, user, password)
        template.checkAndOpenDb()
        if setInnerDb:
            self.db = template.db
        return template

    def createDatabaseStructure(self):
        """
        Creates database structure according to the selected edgv version
        """
        currentPath = os.path.dirname(__file__)
        currentPath = os.path.join(currentPath, '..', '..', 'DbTools', 'PostGISTool')
        if self.version == '2.1.3':
            edgvPath = os.path.join(currentPath, 'sqls', '213', 'edgv213.sql')
        elif self.version == '3.0':
            edgvPath = os.path.join(currentPath, 'sqls', '3', 'edgv3.sql')
        elif self.version == 'FTer_2a_Ed':
            edgvPath = os.path.join(currentPath, 'sqls', 'FTer_2a_Ed', 'edgvFter_2a_Ed.sql')
        else:
            pass
        return self.loadDatabaseStructure(edgvPath)

    def loadDatabaseStructure(self, edgvPath):
        """
        Loads the database structure
        edgvPath: path to the databse sql
        """
        commands = []
        hasTemplate = self.abstractDb.checkTemplate(self.version)
        if hasTemplate:
            templateDb = self.connectToTemplate(setInnerDb = False)
            mustUpdateTemplate = templateDb.checkTemplateImplementationVersion()
            if mustUpdateTemplate:
                templateName = templateDb.db.databaseName()
                templateDb.__del__()
                self.abstractDb.dropDatabase(templateName, dropTemplate = True)
                hasTemplate = False
        if not hasTemplate:
            file = codecs.open(edgvPath, encoding='utf-8', mode="r")
            sql = file.read()
            sql = sql.replace('[epsg]', '4674')
            file.close()
            commands = [i for i in sql.split('#') if i != '']
        # Progress bar steps calculated
        self.signals.rangeCalculated.emit(len(commands)+4, self.getId())
        
        if not hasTemplate:
            try:
                self.abstractDb.createTemplateDatabase(self.version)
                self.signals.stepProcessed.emit(self.getId())
                self.connectToTemplate()
                self.signals.stepProcessed.emit(self.getId())
            except Exception as e:
                return (0, self.messenger.getProblemFeedbackMessage()+'\n'+':'.join(e.args))
            self.db.open()
            self.db.transaction()
            query = QSqlQuery(self.db)
    
            for command in commands:
                if not self.stopped[0]:
                    if not query.exec_(command):
                        QgsMessageLog.logMessage(self.messenger.getProblemMessage(command, query), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
                        self.db.rollback()
                        self.db.close()
                        self.dropDatabase(self.db)
                        return (0, self.messenger.getProblemFeedbackMessage())
    
                    # Updating progress
                    self.signals.stepProcessed.emit(self.getId())
                else:
                    self.db.rollback()
                    self.db.close()
                    self.dropDatabase(self.db)                
                    QgsMessageLog.logMessage(self.messenger.getUserCanceledFeedbackMessage(), "DSG Tools Plugin", QgsMessageLog.INFO)
                    return (-1, self.messenger.getUserCanceledFeedbackMessage())
    
            self.db.commit()
            if self.version == '2.1.3':
                sql = 'ALTER DATABASE %s SET search_path = "$user", public, topology,\'cb\',\'complexos\',\'dominios\';' % self.db.databaseName()
            elif self.version == 'FTer_2a_Ed':
                sql = 'ALTER DATABASE %s SET search_path = "$user", public, topology,\'pe\',\'ge\',\'complexos\',\'dominios\';' % self.db.databaseName()
            elif self.version == '3.0':
                sql = 'ALTER DATABASE %s SET search_path = "$user", public, topology,\'edgv\',\'complexos\',\'dominios\';' % self.db.databaseName()
            
            if sql:
                if not query.exec_(sql):
                    QgsMessageLog.logMessage(self.messenger.getProblemMessage(command, query), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
                    return (0, self.messenger.getProblemFeedbackMessage())
            #this commit was missing, so alter database statement was not commited.
            self.db.commit()
            self.db.close()
            self.abstractDb.setDbAsTemplate(self.version)
        #creates from template
        if not self.stopped[0]:
            templateName = self.abstractDb.getTemplateName(self.version)
            self.abstractDb.createDbFromTemplate(self.dbName, templateName, parentWidget = self.parent)
            self.signals.stepProcessed.emit(self.getId())
            #5. alter spatial structure
            createdDb = self.dbFactory.createDbFactory('QPSQL')
            createdDb.connectDatabaseWithParameters(self.abstractDb.db.hostName(), self.abstractDb.db.port(), self.dbName, self.abstractDb.db.userName(), self.abstractDb.db.password())
            errorTuple = createdDb.updateDbSRID(self.epsg, parentWidget = self.parent, threading = True)
            # if an error occur during the thread we should pass the message to the main thread
            if errorTuple:
                QgsMessageLog.logMessage(self.messenger.getProblemMessage(errorTuple[0], errorTuple[1]), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
                return (0, self.messenger.getProblemFeedbackMessage())                
            self.signals.stepProcessed.emit(self.getId())
        else:
            QgsMessageLog.logMessage(self.messenger.getUserCanceledFeedbackMessage(), "DSG Tools Plugin", QgsMessageLog.INFO)
            return (-1, self.messenger.getUserCanceledFeedbackMessage())
        QgsMessageLog.logMessage(self.messenger.getSuccessFeedbackMessage(), "DSG Tools Plugin", QgsMessageLog.INFO)
        return (1, self.messenger.getSuccessFeedbackMessage())

    def dropDatabase(self,db):
        """
        Drops the created database case a problem occurs during database creation
        db: QSqlDatabase to be dropped
        """
        host = db.hostName()
        port = db.port()
        user = db.userName()
        password = db.password()
        database = 'postgres'
        pgDB = QSqlDatabase('QPSQL')
        pgDB.setHostName(host)
        pgDB.setPort(port)
        pgDB.setUserName(user)
        pgDB.setPassword(password)
        pgDB.setDatabaseName(database)
        if not pgDB.open():
            return False
        sql = self.gen.dropDatabase(db.databaseName())
        query = QSqlQuery(pgDB)
        return query.exec_(sql)
Example #15
0
class LoadByClass(QtGui.QDialog, load_by_class_base.Ui_LoadByClass):
    def __init__(self, parent=None):
        """Constructor."""
        super(LoadByClass, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.filename = ""
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.selectedClasses = []

        #Sql factory generator
        self.isSpatialite = True

        self.setupUi(self)
        self.tabWidget.setCurrentIndex(0)
        self.factory = SqlGeneratorFactory()
        self.gen = self.factory.createSqlGenerator(self.isSpatialite)
        self.utils = Utils()

        self.bar = QgsMessageBar()
        self.setLayout(QtGui.QGridLayout(self))
        self.layout().setContentsMargins(0,0,0,0)
        self.layout().setAlignment(QtCore.Qt.AlignTop)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
        self.bar.setSizePolicy(sizePolicy)
        self.layout().addWidget(self.bar, 0,0,1,1)

        #Objects Connections
        QtCore.QObject.connect(self.pushButtonOpenFile, QtCore.SIGNAL(("clicked()")), self.loadDatabase)
        QtCore.QObject.connect(self.pushButtonCancel, QtCore.SIGNAL(("clicked()")), self.cancel)
        QtCore.QObject.connect(self.selectAllCheck, QtCore.SIGNAL(("stateChanged(int)")), self.selectAll)
        QtCore.QObject.connect(self.pushButtonOk, QtCore.SIGNAL(("clicked()")), self.okSelected)
        QtCore.QObject.connect(self.tabWidget,QtCore.SIGNAL(("currentChanged(int)")), self.restoreInitialState)

        self.db = None
        #populating the postgis combobox
        self.populatePostGISConnectionsCombo()

    def __del__(self):
        self.closeDatabase()

    def closeDatabase(self):
        if self.db:
            self.db.close()
            self.db = None

    def restoreInitialState(self):
        self.filename = ""
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.selectedClasses = []
        self.spatialiteFileEdit.setText(self.filename)
        self.postGISCrsEdit.setText('')
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setText('')
        self.spatialiteCrsEdit.setReadOnly(True)

        tam = self.classesListWidget.__len__()
        for i in range(tam+1,1,-1):
            item = self.classesListWidget.takeItem(i-2)

        self.selectAllCheck.setCheckState(0)
        #Setting the database type
        if self.tabWidget.currentIndex() == 0:
            self.isSpatialite = True
        else:
            self.isSpatialite = False
        #getting the sql generator according to the database type
        self.gen = self.factory.createSqlGenerator(self.isSpatialite)
        self.comboBoxPostgis.setCurrentIndex(0)

    def updateBDField(self):
        if self.dbLoaded == True:
            self.spatialiteFileEdit.setText(self.filename)
        else:
            self.filename = ""
            self.spatialiteFileEdit.setText(self.filename)

    def getDatabaseVersion(self):
        self.dbVersion = self.utils.getDatabaseVersion(self.db)
        self.qmlPath = self.utils.getQmlDir(self.db)

    def listClassesFromDatabase(self):
        self.classesListWidget.clear()
        self.getDatabaseVersion()
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        while query.next():
            if self.isSpatialite:
                tableName = query.value(0)
                layerName = tableName
            else:
                tableSchema = query.value(0)
                tableName = query.value(1)
                layerName = tableSchema+'.'+tableName
            if tableName.split("_")[-1] == "p" or tableName.split("_")[-1] == "l" \
                or tableName.split("_")[-1] == "a":

                item = QtGui.QListWidgetItem(layerName)
                self.classesListWidget.addItem(item)
        self.classesListWidget.sortItems()
        self.setCRS()

    def setCRS(self):
        try:
            self.epsg = self.utils.findEPSG(self.db)
            if self.epsg == -1:
                self.bar.pushMessage("", self.tr("Coordinate Reference System not set or invalid!"), level=QgsMessageBar.WARNING)
            else:
                self.crs = QgsCoordinateReferenceSystem(self.epsg, QgsCoordinateReferenceSystem.EpsgCrsId)
                if self.isSpatialite:
                    self.spatialiteCrsEdit.setText(self.crs.description())
                    self.spatialiteCrsEdit.setReadOnly(True)
                else:
                    self.postGISCrsEdit.setText(self.crs.description())
                    self.postGISCrsEdit.setReadOnly(True)
        except:
            pass

    @pyqtSlot(int)
    def on_comboBoxPostgis_currentIndexChanged(self):
        if self.comboBoxPostgis.currentIndex() > 0:
            self.loadDatabase()

    def loadDatabase(self):
        self.closeDatabase()
        if self.isSpatialite:
            (self.filename, self.db) = self.utils.getSpatialiteDatabase()
            if self.filename:
                self.spatialiteFileEdit.setText(self.filename)
        else:
            self.db = self.utils.getPostGISDatabase(self.comboBoxPostgis.currentText())
        try:
            if not self.db.open():
                QgsMessageLog.logMessage(self.db.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            else:
                self.dbLoaded = True
                self.listClassesFromDatabase()
        except:
            pass

    def populatePostGISConnectionsCombo(self):
        self.comboBoxPostgis.clear()
        self.comboBoxPostgis.addItem(self.tr("Select Database"))
        self.comboBoxPostgis.addItems(self.utils.getPostGISConnections())

    def cancel(self):
        self.restoreInitialState()
        self.close()

    def selectAll(self):
        if self.selectAllCheck.isChecked():
            tam = self.classesListWidget.__len__()
            for i in range(tam+1):
                item = self.classesListWidget.item(i-1)
                self.classesListWidget.setItemSelected(item,2)

        else:
            tam = self.classesListWidget.__len__()
            for i in range(tam+1):
                item = self.classesListWidget.item(i-1)
                self.classesListWidget.setItemSelected(item,0)

    def getSelectedItems(self):
        lista = self.classesListWidget.selectedItems()
        self.selectedClasses = []
        tam = len(lista)
        for i in range(tam):
            self.selectedClasses.append(lista[i].text())
        self.selectedClasses.sort()

    def okSelected(self):
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            if self.isSpatialite:
                self.loadSpatialiteLayers()
            else:
                self.loadPostGISLayers()
            QApplication.restoreOverrideCursor()
        except:
            QApplication.restoreOverrideCursor()

    def loadPostGISLayers(self):
        self.getSelectedItems()
        (database, host, port, user, password) = self.utils.getPostGISConnectionParameters(self.comboBoxPostgis.currentText())
        uri = QgsDataSourceURI()
        uri.setConnection(str(host),str(port), str(database), str(user), str(password))
        if len(self.selectedClasses)>0:
            try:
                geom_column = 'geom'
                for layer in self.selectedClasses:
                    split = layer.split('.')
                    schema = split[0]
                    layerName = split[1]
                    sql = self.gen.loadLayerFromDatabase(layer)
                    uri.setDataSource(schema, layerName, geom_column, sql,'id')
                    uri.disableSelectAtId(True)
                    self.loadEDGVLayer(uri, layerName, 'postgres')
                self.restoreInitialState()
                self.close()
            except:
                self.bar.pushMessage(self.tr("Error!"), self.tr("Could not load the selected classes!"), level=QgsMessageBar.CRITICAL)
        else:
            self.bar.pushMessage(self.tr("Warning!"), self.tr("Please, select at least one class!"), level=QgsMessageBar.WARNING)

    def loadSpatialiteLayers(self):
        self.getSelectedItems()
        uri = QgsDataSourceURI()
        uri.setDatabase(self.filename)
        schema = ''
        geom_column = 'GEOMETRY'
        if len(self.selectedClasses)>0:
            try:
                for layer_name in self.selectedClasses:
                    uri.setDataSource(schema, layer_name, geom_column)
                    self.loadEDGVLayer(uri, layer_name, 'spatialite')
                self.restoreInitialState()
                self.close()
            except:
                self.bar.pushMessage(self.tr("Error!"), self.tr("Could not load the layer(s)!"), level=QgsMessageBar.CRITICAL)
        else:
            self.bar.pushMessage(self.tr("Warning!"), self.tr("Please select at least one layer!"), level=QgsMessageBar.WARNING)

    def loadEDGVLayer(self, uri, layer_name, provider):
        vlayer = QgsVectorLayer(uri.uri(), layer_name, provider)
        vlayer.setCrs(self.crs)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer) #added due to api changes
        if self.isSpatialite and (self.dbVersion == '3.0' or self.dbVersion == '2.1.3'):
            lyr = '_'.join(layer_name.replace('\r', '').split('_')[1::])
        else:
            lyr = layer_name.replace('\r','')
        vlayerQml = os.path.join(self.qmlPath, lyr+'.qml')
        vlayer.loadNamedStyle(vlayerQml, False)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer)
        if not vlayer.isValid():
            QgsMessageLog.logMessage(vlayer.error().summary(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
Example #16
0
class ServerDBExplorer(QtGui.QDialog, FORM_CLASS):
    
    def __init__(self, parent = None):
        """Constructor."""
        super(self.__class__, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        self.utils = Utils()
        self.factory = SqlGeneratorFactory()
        #setting the sql generator
        self.gen = self.factory.createSqlGenerator(False)
        self.serverWidget.populateServersCombo()
        self.serverWidget.abstractDbLoaded.connect(self.populateListWithDatabasesFromServer)
    
    def storeConnection(self, server, database):
        (host, port, user, password) = self.getServerConfiguration(server)
        connection = server+'_'+database
        settings = QSettings()
        if not settings.contains('PostgreSQL/connections/'+connection+'/database'):
            settings.beginGroup('PostgreSQL/connections/'+connection)
            settings.setValue('database', database)
            settings.setValue('host', host)
            settings.setValue('port', port)
            settings.setValue('username', user)
            settings.setValue('password', password)
            settings.endGroup()
            return True
        return False

    def getServerConfiguration(self, name):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers/'+name)
        host = settings.value('host')
        port = settings.value('port')
        user = settings.value('username')
        password = settings.value('password')
        settings.endGroup()
        return (host, port, user, password)

    def storeConnectionConfiguration(self, server, database):
        name = self.connectionEdit.text()
        
        (host, port, user, password) = self.getServerConfiguration(server)
        settings = QSettings()
        if not settings.contains('PostgreSQL/servers/'+name+'/host'):
            settings.beginGroup('PostgreSQL/connections/'+name)
            settings.setValue('database', database)
            settings.setValue('host', host)
            settings.setValue('port', port)
            settings.setValue('username', user)
            settings.setValue('password', password)
            settings.endGroup()
    
    def populateListWithDatabasesFromServer(self):
        self.serverListWidget.clear()
        dbList = self.serverWidget.abstractDb.getEDGVDbsFromServer()
        dbList.sort()
        for (dbname, dbversion) in dbList:
            item =  QListWidgetItem(self.serverListWidget)
            item.setText(dbname+' (EDGV v. '+dbversion+')')
            item.setData(Qt.UserRole, dbname)
            
    @pyqtSlot(bool)
    def on_createConnectionPushButton_clicked(self):
        items = self.serverListWidget.selectedItems()
        existentConnections = []
        newConnections = []
        for item in items:
            dbname = item.data(Qt.UserRole)
            ret = self.storeConnection(self.serverWidget.serversCombo.currentText(), dbname)
            if not ret:
                existentConnections.append(dbname)
            else:
                newConnections.append(dbname)
        
        msg = self.tr('Information:\n')
        if len(existentConnections) > 0:
            msg += self.tr('The following databases connections already exist:\n')  
            for conn in existentConnections:
                msg += conn + ', '
        if len(newConnections) > 0:
            msg += self.tr('\nThe following databases connections were created successfully:\n')  
            for conn in newConnections:
                msg += conn+', '
        QMessageBox.warning(self, self.tr("Warning!"), msg)
            
    @pyqtSlot(bool)
    def on_selectAllPushButton_clicked(self):
        count = self.serverListWidget.count()
        for row in range(count):
            item = self.serverListWidget.item(row)
            item.setSelected(True)       

    @pyqtSlot(bool)
    def on_removeMissingPushButton_clicked(self):
        servers = self.serverWidget.getServers()
        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections')
        candidates = settings.childGroups()
        settings.endGroup()
        removedConn = []
        dbList = self.serverWidget.abstractDb.getDbsFromServer()
        for candidate in candidates:
            candidateSettings = QSettings()
            candidateSettings.beginGroup('PostgreSQL/connections/'+candidate)
            candidateDb = candidateSettings.value('database')
            if candidateDb not in dbList:
                self.removeConnections(candidate, removedConn)
        if len(removedConn)>0:
            msg = self.tr('\nThe following databases connections were removed successfully:\n')+', '.join(removedConn)
        else:
            msg = self.tr('No connections were removed.')
        QMessageBox.warning(self, self.tr("Warning!"), msg)
    
    def removeConnections(self,candidate,removedConn):
        candidateSettings = QSettings()
        candidateSettings.beginGroup('PostgreSQL/connections/'+candidate)
        candidateSettings.remove('')
        removedConn.append(candidate)
        candidateSettings.endGroup()
Example #17
0
 def __init__(self):
     super(PostgisDb,self).__init__()
     self.db = QSqlDatabase('QPSQL')
     self.gen = SqlGeneratorFactory().createSqlGenerator(False)
Example #18
0
class PostgisDbThread(GenericThread):
    def __init__(self):
        """Constructor.
        """
        super(PostgisDbThread, self).__init__()

        self.factory = SqlGeneratorFactory()
        #setting the sql generator
        self.gen = self.factory.createSqlGenerator(False)

        self.messenger = PostgisDbMessages(self)

    def setParameters(self, db, version, epsg, stopped):
        self.db = db
        self.version = version
        self.epsg = epsg
        self.stopped = stopped

    def run(self):
        # Processing ending
        (ret, msg) = self.createDatabaseStructure()
        self.signals.processingFinished.emit(ret, msg, self.getId())

    def createDatabaseStructure(self):
        currentPath = os.path.dirname(__file__)
        currentPath = os.path.join(currentPath, '..', '..', 'DbTools', 'PostGISTool')
        if self.version == '2.1.3':
            edgvPath = os.path.join(currentPath, 'sqls', '213', 'edgv213.sql')
        elif self.version == '3.0':
            edgvPath = os.path.join(currentPath, 'sqls', '30', 'edgv30.sql')
        elif self.version == 'FTer_2a_Ed':
            edgvPath = os.path.join(currentPath, 'sqls', 'FTer_2a_Ed', 'edgvFter_2a_Ed.sql')
        else:
            pass
        return self.loadDatabaseStructure(edgvPath)

    def loadDatabaseStructure(self, edgvPath):
        file = codecs.open(edgvPath, encoding='utf-8', mode="r")
        sql = file.read()
        sql = sql.replace('[epsg]', str(self.epsg))
        file.close()
        commands = sql.split('#')

        # Progress bar steps calculated
        self.signals.rangeCalculated.emit(len(commands), self.getId())

        self.db.transaction()
        query = QSqlQuery(self.db)

        for command in commands:
            if not self.stopped[0]:
                if not query.exec_(command):
                    QgsMessageLog.logMessage(self.messenger.getProblemMessage(command, query), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
                    self.db.rollback()
                    self.db.close()
                    self.dropDatabase(self.db)
                    return (0, self.messenger.getProblemFeedbackMessage())

                # Updating progress
                self.signals.stepProcessed.emit(self.getId())
            else:
                self.db.rollback()
                self.db.close()
                self.dropDatabase(self.db)                
                QgsMessageLog.logMessage(self.messenger.getUserCanceledFeedbackMessage(), "DSG Tools Plugin", QgsMessageLog.INFO)
                return (-1, self.messenger.getUserCanceledFeedbackMessage())

        self.db.commit()
        if self.version == '2.1.3':
            sql = 'ALTER DATABASE %s SET search_path = "$user", public, topology,\'cb\',\'complexos\',\'dominios\';' % self.db.databaseName()
        elif self.version == 'FTer_2a_Ed':
            sql = 'ALTER DATABASE %s SET search_path = "$user", public, topology,\'pe\',\'ge\',\'complexos\',\'dominios\';' % self.db.databaseName()
        
        if not query.exec_(sql):
            QgsMessageLog.logMessage(self.messenger.getProblemMessage(command, query), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            return (0, self.messenger.getProblemFeedbackMessage())
        
        self.db.close()
        QgsMessageLog.logMessage(self.messenger.getSuccessFeedbackMessage(), "DSG Tools Plugin", QgsMessageLog.INFO)
        return (1, self.messenger.getSuccessFeedbackMessage())

    def dropDatabase(self,db):
        host = db.hostName()
        port = db.port()
        user = db.userName()
        password = db.password()
        database = 'postgres'
        pgDB = QSqlDatabase('QPSQL')
        pgDB.setHostName(host)
        pgDB.setPort(port)
        pgDB.setUserName(user)
        pgDB.setPassword(password)
        pgDB.setDatabaseName(database)
        if not pgDB.open():
            return False
        sql = self.gen.dropDatabase(db.databaseName())
        query = QSqlQuery(pgDB)
        return query.exec_(sql)
Example #19
0
class SpatialiteDb(AbstractDb):

    def __init__(self):
        super(SpatialiteDb,self).__init__()
        self.db = QSqlDatabase('QSQLITE')
        self.gen = SqlGeneratorFactory().createSqlGenerator(True)
    
    def getDatabaseName(self):
        return self.db.databaseName().split('.sqlite')[0].split('/')[-1]
    
    def connectDatabase(self, conn = None):
        if conn is None:
            self.connectDatabaseWithGui()
        else:
            self.db.setDatabaseName(conn)
    
    def connectDatabaseWithGui(self):
        fd = QFileDialog()
        filename = fd.getOpenFileName(caption=self.tr('Select a DSGTools Spatialite file'),filter=self.tr('Spatialite file databases (*.sqlite)'))
        self.db.setDatabaseName(filename)
    
    def connectDatabaseWithQSettings(self, name):
        return None

    def connectDatabaseWithParameters(self, host, port, database, user, password):
        return None
    
    def listGeomClassesFromDatabase(self):
        try:
            self.checkAndOpenDb()
        except:
            return []
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        while query.next():
            tableName = str(query.value(0))
            layerName = tableName
            if tableName.split("_")[-1] == "p" or tableName.split("_")[-1] == "l" \
                or tableName.split("_")[-1] == "a":
                classList.append(layerName)
        return classList
    
    def listComplexClassesFromDatabase(self):
        try:
            self.checkAndOpenDb()
        except:
            return []
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        while query.next():
                tableName = str(query.value(0))
                layerName = tableName
                tableSchema = layerName.split('_')[0]
                if tableSchema == 'complexos': 
                    classList.append(layerName)
        return classList    

    def getConnectionFromQSettings(self, conName):
        return None

    def storeConnection(self, server):
        return None
        
    def getServerConfiguration(self, name):
        return None

    def getStructureDict(self):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        classDict = dict()
        sql = self.gen.getStructure(self.getDatabaseVersion())        
        query = QSqlQuery(sql, self.db)
        while query.next():
            className = str(query.value(0))
            classSql = str(query.value(1))
            if className.split('_')[0] == 'complexos' or className.split('_')[-1] in ['p','l','a']:
                if className not in classDict.keys():
                    classDict[className]=dict()
                classSql = classSql.split(className)[1]
                sqlList = classSql.replace('(','').replace(')','').replace('\"','').replace('\'','').split(',')
                for s in sqlList:
                     fieldName = str(s.strip().split(' ')[0])
                     classDict[className][fieldName]=fieldName

                if 'GEOMETRY' in classDict[className].keys():
                    classDict[className]['GEOMETRY'] = 'geom'
                if 'OGC_FID' in classDict[className].keys():
                    classDict[className]['OGC_FID'] = 'id'

        return classDict
    
    def makeOgrConn(self):
        constring = self.db.databaseName()
        return constring

    def getNotNullDict(self):
        return None

    def getDomainDict(self):
        return None 

    def validateWithOutputDatabaseSchema(self,outputAbstractDb):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        invalidated = self.buildInvalidatedDict()
        inputdbStructure = self.getStructureDict()
        outputdbStructure = outputAbstractDb.getStructureDict()
        domainDict = outputAbstractDb.getDomainDict()
        classes =  self.listClassesWithElementsFromDatabase()
        notNullDict = outputAbstractDb.getNotNullDict()
        
        for inputClass in classes.keys():
            outputClass = self.translateAbstractDbLayerNameToOutputFormat(inputClass,outputAbstractDb)
            (schema,className) = self.getTableSchema(inputClass)
            if outputClass in outputdbStructure.keys():
                outputAttrList = self.reorderTupleList(outputdbStructure[outputClass].keys())
                inputAttrList = self.reorderTupleList(inputdbStructure[inputClass].keys())
                            
                sql = self.gen.getFeaturesWithSQL(inputClass,inputAttrList) 
                query = QSqlQuery(sql, self.db)
                
                while query.next():
                    id = query.value(0)
                    #detects null lines
                    for i in range(len(inputAttrList)):
                        nullLine = True
                        value = query.value(i)
                        if value <> None:
                            nullLine = False
                            break
                    if nullLine:
                        if cl not in invalidated['nullLine'].keys():
                            invalidated['nullLine'][inputClass]=0
                        invalidated['nullLine'][inputClass]+=1
                    
                    #validates pks
                    if id == None and (not nullLine):
                        if cl not in invalidated['nullPk'].keys():
                            invalidated['nullPk'][inputClass]=0
                        invalidated['nullPk'][inputClass]+=1
                    
                    for i in range(len(inputAttrList)):
                        value = query.value(i)
                        #validates domain
                        if outputClass in domainDict.keys():    
                            if inputAttrList[i] in domainDict[outputClass].keys():
                                if value not in domainDict[outputClass][inputAttrList[i]] and (not nullLine):
                                    invalidated = self.utils.buildNestedDict(invalidated, ['notInDomain',inputClass,id,inputAttrList[i]], value)
                        #validates not nulls
                        if outputClass in notNullDict.keys():
                            if outputClass in domainDict.keys():
                                if inputAttrList[i] in notNullDict[outputClass] and inputAttrList[i] not in domainDict[outputClass].keys():
                                    if (value == None) and (not nullLine) and (inputAttrList[i] not in domainDict[outputClass].keys()):
                                        invalidated = self.utils.buildNestedDict(invalidated, ['nullAttribute',inputClass,id,inputAttrList[i]], value)             
                            else:
                                if inputAttrList[i] in notNullDict[outputClass]:
                                    if (value == None) and (not nullLine) and (inputAttrList[i] not in domainDict[outputClass].keys()):
                                        invalidated = self.utils.buildNestedDict(invalidated, ['nullAttribute',inputClass,id,inputAttrList[i]], value)
                        if outputClass in domainDict.keys():
                            if (inputAttrList[i] not in ['geom','GEOMETRY','id','OGC_FID'] and schema <> 'complexos') or (schema == 'complexos' and inputAttrList[i] <> 'id'):
                                if inputAttrList[i] not in outputdbStructure[outputClass].keys():
                                    invalidated = self.utils.buildNestedDict(invalidated, ['attributeNotFoundInOutput',inputClass], [inputAttrList[i]])
                            
            else:
                invalidated['classNotFoundInOutput'].append(inputAttrList)
        return invalidated
    
    def translateAbstractDbLayerNameToOutputFormat(self,lyr,outputAbstractDb):
        if outputAbstractDb.db.driverName() == 'QSQLITE':
            return lyr
        if outputAbstractDb.db.driverName() == 'QPSQL':
            return str(lyr.split('_')[0]+'.'+'_'.join(lyr.split('_')[1::]))
    
    def translateOGRLayerNameToOutputFormat(self,lyr,ogrOutput):
        if ogrOutput.GetDriver().name == 'SQLite':
            return lyr
        if ogrOutput.GetDriver().name == 'PostgreSQL':
            return str(lyr.split('_')[0]+'.'+'_'.join(lyr.split('_')[1::]))
    
    def getTableSchema(self,lyr):
        schema = lyr.split('_')[0]
        className = '_'.join(lyr.split('_')[1::])
        return (schema, className)
    
    def convertToPostgis(self, outputAbstractDb,type=None):
        try:
            self.checkAndOpenDb()
        except:
            return False
        (inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict) = self.prepareForConversion(outputAbstractDb)
        invalidated = self.validateWithOutputDatabaseSchema(outputAbstractDb)
        hasErrors = self.makeValidationSummary(invalidated)
        if type == 'untouchedData':
            if hasErrors:
                self.signals.updateLog.emit('\n\n\n'+self.tr('Conversion not perfomed due to validation errors! Check log above for more information.'))
                return False
            else:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict)
                return status
        if type == 'fixData':
            if hasErrors:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict, invalidated)
                return status
            else:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict)
                return status
        return False
    
    def convertToSpatialite(self, outputAbstractDb,type=None):
        return None
    
    def getDatabaseVersion(self):
        try:
            self.checkAndOpenDb()
        except:
            return None
        version = '2.1.3'
        try:
            sqlVersion = self.gen.getEDGVVersion()
            queryVersion =  QSqlQuery(sqlVersion, self.db)
            while queryVersion.next():
                version = queryVersion.value(0)
        except:
            version = '2.1.3'
        return version
    
    def obtainLinkColumn(self, complexClass, aggregatedClass):
        try:
            self.checkAndOpenDb()
        except:
            return ''
        #query to obtain the link column between the complex and the feature layer
        sql = self.gen.getLinkColumn(complexClass.replace('complexos_', ''), aggregatedClass)
        query = QSqlQuery(sql, self.db)
        column_name = ""
        while query.next():
            column_name = query.value(0)
        return column_name

    def loadAssociatedFeatures(self, complex):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        associatedDict = dict()
        #query to get the possible links to the selected complex in the combobox
        complexName = complex.replace('complexos_', '')
        sql = self.gen.getComplexLinks(complexName)
        query = QSqlQuery(sql, self.db)
        while query.next():
            #setting the variables
            complex_schema = query.value(0)
            complex = query.value(1)
            aggregated_schema = query.value(2)
            aggregated_class = query.value(3)
            column_name = query.value(4)

            #query to obtain the created complexes
            sql = self.gen.getComplexData(complex_schema, complex)
            complexQuery = QSqlQuery(sql, self.db)
            while complexQuery.next():
                complex_uuid = complexQuery.value(0)
                name = complexQuery.value(1)

                if not (complex_uuid and name):
                    continue

                associatedDict = self.utils.buildNestedDict(associatedDict, [name, complex_uuid, aggregated_class], [])

                #query to obtain the id of the associated feature
                sql = self.gen.getAssociatedFeaturesData(aggregated_schema, aggregated_class, column_name, complex_uuid)
                associatedQuery = QSqlQuery(sql, self.db)

                while associatedQuery.next():
                    ogc_fid = associatedQuery.value(0)
                    associatedDict = self.utils.buildNestedDict(associatedDict, [name, complex_uuid, aggregated_class], [ogc_fid])
        return associatedDict
    
    def isComplexClass(self, className):
        try:
            self.checkAndOpenDb()
        except:
            return False
        #getting all complex tables
        query = QSqlQuery(self.gen.getComplexTablesFromDatabase(), self.db)
        while query.next():
            if query.value(0) == 'complexos_'+className:
                return True
        return False

    def disassociateComplexFromComplex(self, aggregated_class, link_column, id):
        sql = self.gen.disassociateComplexFromComplex('complexos_'+aggregated_class, link_column, id)
        query = QSqlQuery(self.db)
        if not query.exec_(sql):
            raise Exception(self.tr('Problem disassociating complex from complex: ') + '\n' + query.lastError().text())
    
    def getUsers(self):
        return None
    
    def getUserRelatedRoles(self, username):
        return None
    
    def getRoles(self):
        return None
    
    def createRole(self, role, dict):
        pass

    def dropRole(self, role):
        pass

    def alterUserPass(self, user, newpassword):
        pass

    def createUser(self, user, password, isSuperUser):
        pass

    def removeUser(self, user):
        pass

    def grantRole(self, user, role):
        pass

    def revokeRole(self, user, role):
        pass

    def getTablesFromDatabase(self):
        try:
            self.checkAndOpenDb()
        except:
            return []
        ret = []

        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        while query.next():
            #table name
            ret.append(query.value(0))
        return ret

    def getRolePrivileges(self, role, dbname):
        return None

    def getFrameLayerName(self):
        return 'public_aux_moldura_a'

    def getEDGVDbsFromServer(self,name):
        return None

    def getDbsFromServer(self):
        return None
    
    def checkSuperUser(self):
        return None

    def dropDatabase(self,abstractCandidate):
        return None

    def createResolvedDomainViews(self, createViewClause, fromClause):
        pass

    def getSqlViewFile(self):
        pass
Example #20
0
class PostgisDb(AbstractDb):
    
    def __init__(self):
        super(PostgisDb,self).__init__()
        self.db = QSqlDatabase('QPSQL')
        self.gen = SqlGeneratorFactory().createSqlGenerator(False)
        
    def getDatabaseName(self):
        return self.db.databaseName()
    
    def connectDatabase(self,conn=None):
        if conn.split(':')[0] == 'PG':
            connSplit = conn.split(' ')
            parDict = dict()
            for i in connSplit[1::]:
                par = i.split('=')
                parDict[par[0]]=par[1]
            self.connectDatabaseWithParameters(parDict['host'], parDict['port'], parDict['dbname'], parDict['user'], parDict['password'])
        else:
            self.connectDatabaseWithQSettings(conn)

    def connectDatabaseWithGui(self):
        return None

    def connectDatabaseWithParameters(self, host, port, database, user, password):
        self.db.setHostName(host)
        if type(port) != 'int':
            self.db.setPort(int(port))
        else:
            self.db.setPort(port)
        self.db.setDatabaseName(database)
        self.db.setUserName(user)
        if not password or password == '':
            conInfo = 'host='+host+' port='+port+' dbname='+database
            check = False
            while not check:
                try:
                    (success, user, password) = QgsCredentials.instance().get(conInfo, user, None)
                    if not success:
                        return 
                    self.db.setPassword(password)
                    check = True
                    self.checkAndOpenDb()
                    QgsCredentials.instance().put(conInfo, user, password)
                except:
                    pass
        else:
            self.db.setPassword(password)

    def connectDatabaseWithQSettings(self, name):
        (host, port, database, user, password) = self.getConnectionFromQSettings(name)
        self.db.setHostName(host)
        if type(port) != 'int':
            self.db.setPort(int(port))
        else:
            self.db.setPort(port)
        self.db.setDatabaseName(database)
        self.db.setUserName(user)
        if not password or password == '':
            conInfo = 'host='+host+' port='+port+' dbname='+database
            check = False
            while not check:
                try:
                    (success, user, password) = QgsCredentials.instance().get(conInfo, user, None)
                    if not success:
                        return 
                    self.db.setPassword(password)
                    check = True
                    self.checkAndOpenDb()
                    QgsCredentials.instance().put(conInfo, user, password)
                except:
                    pass
        else:
            self.db.setPassword(password)

    def getDatabaseVersion(self):
        try:
            self.checkAndOpenDb()
        except:
            return '-1'
        sqlVersion = self.gen.getEDGVVersion()
        queryVersion = QSqlQuery(sqlVersion, self.db)
        while queryVersion.next():
            version = queryVersion.value(0)
        return version
    
    def listGeomClassesFromDatabase(self):
        try:
            self.checkAndOpenDb()
        except:
            return []    
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        while query.next():
            tableSchema = query.value(0)
            tableName = query.value(1)
            layerName = tableSchema+'.'+tableName
            if tableName.split("_")[-1] == "p" or tableName.split("_")[-1] == "l" \
                or tableName.split("_")[-1] == "a":
                classList.append(layerName)
        return classList
    
    def listComplexClassesFromDatabase(self):
        try:
            self.checkAndOpenDb()
        except:
            return []      
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        while query.next():
            tableSchema = query.value(0)
            tableName = query.value(1)
            layerName = tableSchema+'.'+tableName
            if tableSchema == 'complexos':
                classList.append(layerName)
        classList.sort()
        return classList

    def storeConnection(self, server):
        (host, port, user, password) = self.getServerConfiguration(server)
        database = self.db.databaseName()
        connection = server+'_'+database
        settings = QSettings()
        if not settings.contains('PostgreSQL/connections/'+connection+'/database'):
            settings.beginGroup('PostgreSQL/connections/'+connection)
            settings.setValue('database', database)
            settings.setValue('host', host)
            settings.setValue('port', port)
            settings.setValue('username', user)
            settings.setValue('password', password)
            settings.endGroup()
            return True
        return False        

    def getConnectionFromQSettings(self, conName):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections/'+conName)
        host = settings.value('host')
        port = settings.value('port')
        database = settings.value('database')
        user = settings.value('username')
        password = settings.value('password')
        settings.endGroup()
        return (host, port, database, user, password)       

    def getServerConfiguration(self, name):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers/'+name)
        host = settings.value('host')
        port = settings.value('port')
        user = settings.value('username')
        password = settings.value('password')
        settings.endGroup()
        return (host, port, user, password)

    def getStructureDict(self):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        classDict = dict()
        sql = self.gen.getStructure(self.getDatabaseVersion())        
        query = QSqlQuery(sql, self.db)
        while query.next():
            className = str(query.value(0))+'.'+str(query.value(1))
            fieldName = str(query.value(2))
            if str(query.value(0)) == 'complexos' or className.split('_')[-1] in ['p','l','a']:
                if className not in classDict.keys():
                    classDict[className]=dict()
                classDict[className][fieldName]=fieldName
                if 'geom' in classDict[className].keys():
                    classDict[className]['geom'] = 'GEOMETRY'
                if str(query.value(0)) <> 'complexos' and 'id' in classDict[className].keys():
                    classDict[className]['id'] = 'OGC_FID'
        return classDict
    
    def makeOgrConn(self):
        dbName = self.db.databaseName()
        dbUser = self.db.userName()
        dbHost = self.db.hostName()
        dbPass = self.db.password()
        dbPort = str(self.db.port())
        constring = 'PG: dbname=\''+dbName+'\' user=\''+dbUser+'\' host=\''+dbHost+'\' password=\''+dbPass+'\' port='+dbPort
        return constring

    def getNotNullDict(self):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        if self.getDatabaseVersion() == '2.1.3':
            schemaList = ['cb', 'complexos']
        elif self.getDatabaseVersion() == 'FTer_2a_Ed':
            schemaList = ['pe','ge','ct', 'complexos']
        else:
            QgsMessageLog.logMessage(self.tr('Operation not defined for this database version!'), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            return None
        sql = self.gen.getNotNullFields(schemaList)
        query = QSqlQuery(sql, self.db)
        notNullDict = dict()
        while query.next():
            schemaName = str(query.value(0))
            className = str(query.value(1))
            attName = str(query.value(2))
            cl = schemaName+'.'+className
            if cl not in notNullDict.keys():
                notNullDict[cl] = []
            notNullDict[cl].append(attName)
        return notNullDict

    def getDomainDict(self):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        if self.getDatabaseVersion() == '2.1.3':
            schemaList = ['cb', 'complexos', 'dominios']
        elif self.getDatabaseVersion() == 'FTer_2a_Ed':
            schemaList = ['pe','ge','ct', 'complexos']
        else:
            QgsMessageLog.logMessage(self.tr('Operation not defined for this database version!'), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            return
        sql = self.gen.validateWithDomain(schemaList)
        query = QSqlQuery(sql, self.db)
        classDict = dict()
        domainDict = dict()
        while query.next():
            schemaName = str(query.value(0))
            className = str(query.value(1))
            attName = str(query.value(2))
            domainName = str(query.value(3))
            domainTable = str(query.value(4))
            domainQuery = str(query.value(5))
            cl = schemaName+'.'+className
            query2 = QSqlQuery(domainQuery,self.db)
            while query2.next():
                value = int(query2.value(0))
                classDict = self.utils.buildNestedDict(classDict,[str(cl),str(attName)],[value])
        return classDict
    
    def validateWithOutputDatabaseSchema(self,outputAbstractDb):
        return None

    def translateAbstractDbLayerNameToOutputFormat(self,lyr,outputAbstractDb):
        if outputAbstractDb.db.driverName() == 'QSQLITE':
            return str(lyr.split('.')[0]+'_'+'_'.join(lyr.split('.')[1::]))
        if outputAbstractDb.db.driverName() == 'QPSQL':
            return lyr

    def translateOGRLayerNameToOutputFormat(self,lyr,ogrOutput):
        if ogrOutput.GetDriver().name == 'SQLite':
            return str(lyr.split('.')[0]+'_'+'_'.join(lyr.split('.')[1::]))
        if ogrOutput.GetDriver().name == 'PostgreSQL':
            return lyr

    def getTableSchema(self,lyr):
        schema = lyr.split('.')[0]
        className = '_'.join(lyr.split('.')[1::])
        return (schema, className)

    def convertToPostgis(self, outputAbstractDb,type=None):
        return None
    
    def convertToSpatialite(self, outputAbstractDb,type=None):
        (inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict) = self.prepareForConversion(outputAbstractDb)
        status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict)
        return status
    
    def obtainLinkColumn(self, complexClass, aggregatedClass):
        try:
            self.checkAndOpenDb()
        except:
            return ''
        complexClass = complexClass.replace('complexos.', '')
        #query to obtain the link column between the complex and the feature layer
        sql = self.gen.getLinkColumn(complexClass, aggregatedClass)
        query = QSqlQuery(sql, self.db)
        column_name = ''
        while query.next():
            column_name = query.value(0)
        return column_name

    def loadAssociatedFeatures(self, complex):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        associatedDict = dict()
        complex = complex.replace('complexos.', '')
        #query to get the possible links to the selected complex in the combobox
        sql = self.gen.getComplexLinks(complex)
        query = QSqlQuery(sql, self.db)
        while query.next():
            #setting the variables
            complex_schema = query.value(0)
            complex = query.value(1)
            aggregated_schema = query.value(2)
            aggregated_class = query.value(3)
            column_name = query.value(4)

            #query to obtain the created complexes
            sql = self.gen.getComplexData(complex_schema, complex)
            complexQuery = QSqlQuery(sql, self.db)
            while complexQuery.next():
                complex_uuid = complexQuery.value(0)
                name = complexQuery.value(1)

                if not (complex_uuid and name):
                    continue
                
                associatedDict = self.utils.buildNestedDict(associatedDict, [name, complex_uuid, aggregated_class], [])
                
                #query to obtain the id of the associated feature
                sql = self.gen.getAssociatedFeaturesData(aggregated_schema, aggregated_class, column_name, complex_uuid)
                associatedQuery = QSqlQuery(sql, self.db)

                while associatedQuery.next():
                    ogc_fid = associatedQuery.value(0)
                    associatedDict = self.utils.buildNestedDict(associatedDict, [name, complex_uuid, aggregated_class], [ogc_fid])
        return associatedDict
    
    def isComplexClass(self, className):
        try:
            self.checkAndOpenDb()
        except:
            return False
        #getting all complex tables
        query = QSqlQuery(self.gen.getComplexTablesFromDatabase(), self.db)
        while query.next():
            if query.value(0) == className:
                return True
        return False

    def disassociateComplexFromComplex(self, aggregated_class, link_column, id):
        sql = self.gen.disassociateComplexFromComplex(aggregated_class, link_column, id)
        query = QSqlQuery(self.db)
        if not query.exec_(sql):
            raise Exception(self.tr('Problem disassociating complex from complex: ') + '\n' + query.lastError().text())
    
    def getUsers(self):
        try:
            self.checkAndOpenDb()
        except:
            return []
        ret = []
        
        sql = self.gen.getUsers()
        query = QSqlQuery(sql, self.db)

        while query.next():
            ret.append(query.value(0))
            
        ret.sort()
        return ret

    def getUserRelatedRoles(self, username):
        try:
            self.checkAndOpenDb()
        except:
            return [], []
        installed = []
        assigned = []

        sql = self.gen.getUserRelatedRoles(username)
        query = QSqlQuery(sql, self.db)

        while query.next():
            rolname = query.value(0)
            usename = query.value(1)
            if not usename:
                installed.append(rolname)
            else:
                assigned.append(rolname)

        installed.sort()
        assigned.sort()
        return installed, assigned
    
    def getRoles(self):
        try:
            self.checkAndOpenDb()
        except:
            return []
        ret = []

        sql = self.gen.getRoles()
        query = QSqlQuery(sql, self.db)

        while query.next():
            ret.append(query.value(0))

        ret.sort()
        return ret

    def createRole(self, role, dict):
        try:
            self.checkAndOpenDb()
        except:
            return
        #making this so the instaciated permissions stay with different names
        uuid = str(uuid4()).replace('-', '_')
        role += '_'+uuid

        sql = self.gen.createRole(role, dict)
        split = sql.split(';')
        query = QSqlQuery(self.db)
        
        #try to revoke the permissions
        try:
            self.dropRole(role)
        except:
            pass

        for inner in split:
            if not query.exec_(inner):
                if '42710' in query.lastError().text():
                    #In this case the role is already created (duplicate object error). We just need to proceed executing the grants.
                    continue
                else:
                    raise Exception(self.tr('Problem assigning profile: ') +role+'\n'+query.lastError().text())
    
    def dropRole(self, role):
        try:
            self.checkAndOpenDb()
        except:
            return
        sql = self.gen.dropRole(role)
        split = sql.split('#')
        query = QSqlQuery(self.db)

        for inner in split:
            if not query.exec_(inner):
                if '2BP01' in query.lastError().text():
                    #In this case the role is still used by other databases, therefore it shouldn't be dropped.
                    continue
                else:
                    raise Exception(self.tr('Problem removing profile: ') +role+'\n'+query.lastError().text())

    def alterUserPass(self, user, newpassword):
        try:
            self.checkAndOpenDb()
        except:
            return
        sql = self.gen.alterUserPass(user, newpassword)
        query = QSqlQuery(self.db)

        if not query.exec_(sql):
            raise Exception(self.tr('Problem altering user\'s password: '******'\n'+query.lastError().text())

    def createUser(self, user, password, isSuperUser):
        try:
            self.checkAndOpenDb()
        except:
            return
        sql = self.gen.createUser(user, password, isSuperUser)
        query = QSqlQuery(self.db)

        if not query.exec_(sql):
            raise Exception(self.tr('Problem creating user: '******'\n'+query.lastError().text())

    def removeUser(self, user):
        try:
            self.checkAndOpenDb()
        except:
            return
        sql = self.gen.removeUser(user)
        query = QSqlQuery(self.db)

        if not query.exec_(sql):
            raise Exception(self.tr('Problem removing user: '******'\n'+query.lastError().text())

    def grantRole(self, user, role):
        try:
            self.checkAndOpenDb()
        except:
            return        
        sql = self.gen.grantRole(user, role)
        query = QSqlQuery(self.db)

        if not query.exec_(sql):
            raise Exception(self.tr('Problem granting profile: ') +role+'\n'+query.lastError().text())

    def revokeRole(self, user, role):
        try:
            self.checkAndOpenDb()
        except:
            return
        sql = self.gen.revokeRole(user, role)
        query = QSqlQuery(self.db)

        if not query.exec_(sql):
            raise Exception(self.tr('Problem revoking profile: ') +role+'\n'+query.lastError().text())

    def getTablesFromDatabase(self):
        try:
            self.checkAndOpenDb()
        except:
            return []
        ret = []

        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)

        while query.next():
            #table name
            ret.append(query.value(0))

        return ret

    def getRolePrivileges(self, role, dbname):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        privilegesDict = dict()
        
        sql = self.gen.getRolePrivileges(role, dbname)
        query = QSqlQuery(sql, self.db)
        
        while query.next():
            schema = query.value(3)
            table = query.value(4)
            privilege = query.value(5)
            
            if schema in ['cb', 'public', 'complexos', 'pe', 'ge']:
                privilegesDict = self.utils.buildNestedDict(privilegesDict, [schema, table], [privilege])
            
        permissionsDict = dict()
        for schema in privilegesDict.keys():
            for table in privilegesDict[schema].keys():
                split = table.split('_')
                category = split[0]
                layerName = schema+'.'+table
                
                if schema not in permissionsDict.keys():
                    permissionsDict[schema] = dict()
                    
                if category not in permissionsDict[schema].keys():
                    permissionsDict[schema][category] = dict()

                privileges = privilegesDict[schema][table]
                write = ['DELETE', 'INSERT', 'SELECT', 'UPDATE', 'TRUNCATE', 'REFERENCES', 'TRIGGER']
                if all((permission in privileges for permission in write)):
                    if layerName not in permissionsDict[schema][category]:
                        permissionsDict[schema][category][layerName] = dict()
                        permissionsDict[schema][category][layerName]['read'] = '2'#read yes
                        permissionsDict[schema][category][layerName]['write'] = '2'#write yes
                else:
                    if layerName not in permissionsDict[schema][category]:
                        permissionsDict[schema][category][layerName] = dict()
                        permissionsDict[schema][category][layerName]['read'] = '2'#read yes
                        permissionsDict[schema][category][layerName]['write'] = '0'#write no
                        
        return permissionsDict    

    def getFrameLayerName(self):
        return 'public.aux_moldura_a'
    
    def getEDGVDbsFromServer(self):
        #Can only be used in postgres database.
        try:
            self.checkAndOpenDb()
        except:
            return []
        query = QSqlQuery(self.gen.getDatabasesFromServer(),self.db)
        dbList = []
        
        while query.next():
            dbList.append(query.value(0))
        
        edvgDbList = []
        for database in dbList:
            db = None
            db = QSqlDatabase("QPSQL")
            db.setDatabaseName(database)
            db.setHostName(self.db.hostName())
            db.setPort(self.db.port())
            db.setUserName(self.db.userName())
            db.setPassword(self.db.password())
            if not db.open():
                QgsMessageLog.logMessage('DB :'+database+'| msg: '+db.lastError().databaseText(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)

            query2 = QSqlQuery(db)
            if query2.exec_(self.gen.getEDGVVersion()):
                while query2.next():
                    version = query2.value(0)
                    if version:
                        edvgDbList.append((database,version))
            else:
                QgsMessageLog.logMessage(self.tr('Problem accessing database: ') +database+'\n'+query2.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
        return edvgDbList
    
    def getDbsFromServer(self):
        #Can only be used in postgres database.
        try:
            self.checkAndOpenDb()
        except:
            return []
        query = QSqlQuery(self.gen.getDatabasesFromServer(),self.db)
        dbList = []
        
        while query.next():
            dbList.append(query.value(0))
        return dbList
    
    def checkSuperUser(self):
        try:
            self.checkAndOpenDb()
        except:
            return False
        query = QSqlQuery(self.db)
        if query.exec_(self.gen.isSuperUser(self.db.userName())):
            query.next()
            value = query.value(0)
            return value
        return False
    
    def dropDatabase(self, candidateName):
        try:
            self.checkAndOpenDb()
        except:
            return
        if self.checkSuperUser():
            sql = self.gen.dropDatabase(candidateName)
            query = QSqlQuery(self.db)
            if not query.exec_(sql):
                raise Exception(self.tr('Problem dropping database: ') + query.lastError().text())
    
    def createResolvedDomainViews(self, createViewClause, fromClause):
        try:
            self.checkAndOpenDb()
        except:
            return
        if self.checkSuperUser():
            filename = self.getSqlViewFile()
            if filename <> None:
                file = codecs.open(filename, encoding='utf-8', mode="r")
                sql = file.read()
                sql = sql.replace('[VIEW]', createViewClause).replace('[FROM]', fromClause)
                file.close()
                commands = sql.split('#')
                self.db.transaction()
                query = QSqlQuery(self.db)
                for command in commands:
                    if not query.exec_(command):
                        self.db.rollback()
                        self.db.close()
                        raise Exception(self.tr('Problem creating views: ') + str(query.lastError().text()))
                self.db.commit()
                self.db.close()

    def getSqlViewFile(self):
        try:
            self.checkAndOpenDb()
        except:
            return
        currentPath = os.path.dirname(__file__)
        dbVersion = self.getDatabaseVersion()
        file = None
        if dbVersion == '2.1.3':
            file = os.path.join(currentPath,'..','..','DbTools','PostGISTool', 'sqls', '213', 'views_213.sql')
        if dbVersion == 'FTer_2a_Ed':
            file = os.path.join(currentPath,'..','..','DbTools','PostGISTool', 'sqls', 'FTer_2a_Ed', 'views_edgvFter_2a_Ed.sql')
        return file
Example #21
0
class SpatialiteDb(AbstractDb):
    def __init__(self):
        '''
        Constructor
        '''
        super(SpatialiteDb, self).__init__()
        self.db = QSqlDatabase('QSQLITE')
        self.gen = SqlGeneratorFactory().createSqlGenerator(True)

    def getDatabaseName(self):
        '''
        Gets the database name
        '''
        return self.db.databaseName().split('.sqlite')[0].split('/')[-1]

    def connectDatabase(self, conn=None):
        '''
        Connects to database
        conn: Database name
        '''
        if conn is None:
            self.connectDatabaseWithGui()
        else:
            self.db.setDatabaseName(conn)

    def connectDatabaseWithGui(self):
        '''
        Connects to database using user interface dialog
        '''
        fd = QFileDialog()
        filename = fd.getOpenFileName(
            caption=self.tr('Select a DSGTools Spatialite file'),
            filter=self.tr('Spatialite file databases (*.sqlite)'))
        self.db.setDatabaseName(filename)

    def listGeomClassesFromDatabase(self, primitiveFilter=[]):
        '''
        Gets a list with geometry classes from database
        '''
        self.checkAndOpenDb()
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(
                self.tr("Problem listing geom classes: ") +
                query.lastError().text())
        while query.next():
            tableName = str(query.value(0))
            layerName = tableName
            if tableName.split("_")[-1] == "p" or tableName.split("_")[-1] == "l" \
                or tableName.split("_")[-1] == "a":
                classList.append(layerName)
        return classList

    def listComplexClassesFromDatabase(self):
        '''
        Gets a list with complex classes from database
        '''
        self.checkAndOpenDb()
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(
                self.tr("Problem listing complex classes: ") +
                query.lastError().text())
        while query.next():
            tableName = str(query.value(0))
            layerName = tableName
            tableSchema = layerName.split('_')[0]
            if tableSchema == 'complexos':
                classList.append(layerName)
        return classList

    def getStructureDict(self):
        '''
        Gets database structure according to the edgv version
        '''
        self.checkAndOpenDb()
        classDict = dict()
        sql = self.gen.getStructure(self.getDatabaseVersion())
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(
                self.tr("Problem getting database structure: ") +
                query.lastError().text())
        while query.next():
            className = str(query.value(0))
            classSql = str(query.value(1))
            if className.split('_')[0] == 'complexos' or className.split(
                    '_')[-1] in ['p', 'l', 'a']:
                if className not in classDict.keys():
                    classDict[className] = dict()
                classSql = classSql.split(className)[1]
                sqlList = classSql.replace('(', '').replace(')', '').replace(
                    '\"', '').replace('\'', '').split(',')
                for s in sqlList:
                    fieldName = str(s.strip().split(' ')[0])
                    classDict[className][fieldName] = fieldName

                if 'GEOMETRY' in classDict[className].keys():
                    classDict[className]['GEOMETRY'] = 'geom'
                if 'geometry' in classDict[className].keys():
                    classDict[className]['geometry'] = 'geom'
                if 'OGC_FID' in classDict[className].keys():
                    classDict[className]['OGC_FID'] = 'id'

        return classDict

    def makeOgrConn(self):
        '''
        Makes a connection string for spatialite databases (e.g just the name)
        '''
        constring = self.db.databaseName()
        return constring

    def validateWithOutputDatabaseSchema(self, outputAbstractDb):
        '''
        Validates the conversion with the output database.
        It generates a dictionary (invalidated) that stores conversion problems
        '''
        self.checkAndOpenDb()
        invalidated = self.buildInvalidatedDict()
        inputdbStructure = self.getStructureDict()
        outputdbStructure = outputAbstractDb.getStructureDict()
        domainDict = outputAbstractDb.getDomainDict()
        classes = self.listClassesWithElementsFromDatabase()
        notNullDict = outputAbstractDb.getNotNullDict()

        for inputClass in classes.keys():
            outputClass = self.translateAbstractDbLayerNameToOutputFormat(
                inputClass, outputAbstractDb)
            (schema, className) = self.getTableSchema(inputClass)
            if outputClass in outputdbStructure.keys():
                outputAttrList = self.reorderTupleList(
                    outputdbStructure[outputClass].keys())
                inputAttrList = self.reorderTupleList(
                    inputdbStructure[inputClass].keys())

                sql = self.gen.getFeaturesWithSQL(inputClass, inputAttrList)
                query = QSqlQuery(sql, self.db)
                if not query.isActive():
                    self.db.close()
                    raise Exception(
                        self.tr("Problem executing query: ") +
                        query.lastError().text())

                while query.next():
                    id = query.value(0)
                    #detects null lines
                    for i in range(len(inputAttrList)):
                        nullLine = True
                        value = query.value(i)
                        if value <> None:
                            nullLine = False
                            break
                    if nullLine:
                        if cl not in invalidated['nullLine'].keys():
                            invalidated['nullLine'][inputClass] = 0
                        invalidated['nullLine'][inputClass] += 1

                    #validates pks
                    if id == None and (not nullLine):
                        if cl not in invalidated['nullPk'].keys():
                            invalidated['nullPk'][inputClass] = 0
                        invalidated['nullPk'][inputClass] += 1

                    for i in range(len(inputAttrList)):
                        value = query.value(i)
                        #validates domain
                        if outputClass in domainDict.keys():
                            if inputAttrList[i] in domainDict[
                                    outputClass].keys():
                                if value not in domainDict[outputClass][
                                        inputAttrList[i]] and (not nullLine):
                                    invalidated = self.utils.buildNestedDict(
                                        invalidated, [
                                            'notInDomain', inputClass, id,
                                            inputAttrList[i]
                                        ], value)
                        #validates not nulls
                        if outputClass in notNullDict.keys():
                            if outputClass in domainDict.keys():
                                if inputAttrList[i] in notNullDict[
                                        outputClass] and inputAttrList[
                                            i] not in domainDict[
                                                outputClass].keys():
                                    if (value == None) and (not nullLine) and (
                                            inputAttrList[i] not in
                                            domainDict[outputClass].keys()):
                                        invalidated = self.utils.buildNestedDict(
                                            invalidated, [
                                                'nullAttribute', inputClass,
                                                id, inputAttrList[i]
                                            ], value)
                            else:
                                if inputAttrList[i] in notNullDict[
                                        outputClass]:
                                    try:
                                        if value.isNull():
                                            invalidated = self.utils.buildNestedDict(
                                                invalidated, [
                                                    'nullAttribute',
                                                    inputClass, id,
                                                    inputAttrList[i]
                                                ], value)
                                    except:
                                        if (value == None) and (
                                                not nullLine
                                        ) and (inputAttrList[i] not in
                                               domainDict[outputClass].keys()):
                                            invalidated = self.utils.buildNestedDict(
                                                invalidated, [
                                                    'nullAttribute',
                                                    inputClass, id,
                                                    inputAttrList[i]
                                                ], value)
                        if outputClass in domainDict.keys():
                            if (inputAttrList[i] not in [
                                    'geom', 'GEOMETRY', 'geometry', 'id',
                                    'OGC_FID'
                            ] and schema <> 'complexos') or (
                                    schema == 'complexos'
                                    and inputAttrList[i] <> 'id'):
                                if inputAttrList[i] not in outputdbStructure[
                                        outputClass].keys():
                                    invalidated = self.utils.buildNestedDict(
                                        invalidated, [
                                            'attributeNotFoundInOutput',
                                            inputClass
                                        ], [inputAttrList[i]])
                        #validates fk field
                        if 'id_' == inputAttrList[0:3]:
                            if not self.validateUUID(value):
                                if inputAttrList[i] not in outputdbStructure[
                                        outputClass].keys():
                                    invalidated = self.utils.buildNestedDict(
                                        invalidated,
                                        ['nullComplexFk', inputClass],
                                        [inputAttrList[i]])
            else:
                invalidated['classNotFoundInOutput'].append(inputAttrList)
        return invalidated

    def translateAbstractDbLayerNameToOutputFormat(self, lyr,
                                                   outputAbstractDb):
        '''
        Translates abstractdb layer name to output format
        lyr: layer name that will be translated
        outputAbstractDb: output database
        '''
        if outputAbstractDb.db.driverName() == 'QSQLITE':
            return lyr
        if outputAbstractDb.db.driverName() == 'QPSQL':
            return str(lyr.split('_')[0] + '.' + '_'.join(lyr.split('_')[1::]))

    def translateOGRLayerNameToOutputFormat(self, lyr, ogrOutput):
        '''
        Translates ogr layer name to output format
        lyr: layer name that will be translated
        ogrOutput: ogr output
        '''
        if ogrOutput.GetDriver().name == 'SQLite':
            return lyr
        if ogrOutput.GetDriver().name == 'PostgreSQL':
            return str(lyr.split('_')[0] + '.' + '_'.join(lyr.split('_')[1::]))

    def getTableSchema(self, lyr):
        '''
        Gets the table schema
        lyr: layer name
        '''
        schema = lyr.split('_')[0]
        className = '_'.join(lyr.split('_')[1::])
        return (schema, className)

    def convertToPostgis(self, outputAbstractDb, type=None):
        '''
        Converts this to a postgis database
        outputAbstractDb: postgis output
        type: conversion type
        '''
        (inputOgrDb, outputOgrDb, fieldMap, inputLayerList,
         errorDict) = self.prepareForConversion(outputAbstractDb)
        invalidated = self.validateWithOutputDatabaseSchema(outputAbstractDb)
        hasErrors = self.makeValidationSummary(invalidated)
        if type == 'untouchedData':
            if hasErrors:
                self.signals.updateLog.emit('\n\n\n' + self.tr(
                    'Conversion not perfomed due to validation errors! Check log above for more information.'
                ))
                return False
            else:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap,
                                          inputLayerList, errorDict)
                return status
        if type == 'fixData':
            if hasErrors:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap,
                                          inputLayerList, errorDict,
                                          invalidated)
                return status
            else:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap,
                                          inputLayerList, errorDict)
                return status
        return False

    def getDatabaseVersion(self):
        '''
        Gets the database version
        '''
        self.checkAndOpenDb()
        version = '2.1.3'
        sql = self.gen.getEDGVVersion()
        query = QSqlQuery(sql, self.db)
        # if not query.isActive():
        #     raise Exception(self.tr("Problem getting database version: ")+query.lastError().text())
        while query.next():
            version = query.value(0)
        return version

    def obtainLinkColumn(self, complexClass, aggregatedClass):
        '''
        Obtains the link column between complex and aggregated class
        complexClass: complex class name
        aggregatedClass: aggregated class name
        '''
        self.checkAndOpenDb()
        #query to obtain the link column between the complex and the feature layer
        sql = self.gen.getLinkColumn(complexClass.replace('complexos_', ''),
                                     aggregatedClass)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(
                self.tr("Problem obtaining link column: ") +
                query.lastError().text())
        column_name = ""
        while query.next():
            column_name = query.value(0)
        return column_name

    def loadAssociatedFeatures(self, complex):
        '''
        Loads all the features associated to the complex 
        complex: complex class name
        '''
        self.checkAndOpenDb()
        associatedDict = dict()
        #query to get the possible links to the selected complex in the combobox
        complexName = complex.replace('complexos_', '')
        sql = self.gen.getComplexLinks(complexName)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(
                self.tr("Problem loading associated features: ") +
                query.lastError().text())

        while query.next():
            #setting the variables
            complex_schema = query.value(0)
            complex = query.value(1)
            aggregated_schema = query.value(2)
            aggregated_class = query.value(3)
            column_name = query.value(4)

            if aggregated_class.split('_')[-1] not in ['p', 'l', 'a']:
                continue

            #query to obtain the created complexes
            sql = self.gen.getComplexData(complex_schema, complex)
            complexQuery = QSqlQuery(sql, self.db)
            if not complexQuery.isActive():
                self.db.close()
                raise Exception(
                    self.tr("Problem executing query: ") +
                    complexQuery.lastError().text())

            while complexQuery.next():
                complex_uuid = complexQuery.value(0)
                name = complexQuery.value(1)

                if not (complex_uuid and name):
                    continue

                associatedDict = self.utils.buildNestedDict(
                    associatedDict, [name, complex_uuid, aggregated_class], [])

                #query to obtain the id of the associated feature
                sql = self.gen.getAssociatedFeaturesData(
                    aggregated_schema, aggregated_class, column_name,
                    complex_uuid)
                associatedQuery = QSqlQuery(sql, self.db)
                if not associatedQuery.isActive():
                    self.db.close()
                    raise Exception(
                        self.tr("Problem executing query: ") +
                        associatedQuery.lastError().text())

                while associatedQuery.next():
                    ogc_fid = associatedQuery.value(0)
                    associatedDict = self.utils.buildNestedDict(
                        associatedDict, [name, complex_uuid, aggregated_class],
                        [ogc_fid])
        return associatedDict

    def isComplexClass(self, className):
        '''
        Checks if a class is a complex class
        className: class name to be checked
        '''
        self.checkAndOpenDb()
        #getting all complex tables
        query = QSqlQuery(self.gen.getComplexTablesFromDatabase(), self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(
                self.tr("Problem executing query: ") +
                query.lastError().text())

        while query.next():
            if query.value(0) == 'complexos_' + className:
                return True
        return False

    def disassociateComplexFromComplex(self, aggregated_class, link_column,
                                       id):
        '''
        Disassociates a complex from another complex
        aggregated_class: aggregated class that will be disassociated
        link_column: link column between complex and its aggregated class
        id: complex id (uid) to be disassociated
        '''
        sql = self.gen.disassociateComplexFromComplex(
            'complexos_' + aggregated_class, link_column, id)
        query = QSqlQuery(self.db)
        if not query.exec_(sql):
            self.db.close()
            raise Exception(
                self.tr('Problem disassociating complex from complex: ') +
                '\n' + query.lastError().text())

    def getTablesFromDatabase(self):
        '''
        Gets all tables from database
        '''
        self.checkAndOpenDb()
        ret = []

        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            self.db.close()
            raise Exception(
                self.tr("Problem getting tables from database: ") +
                query.lastError().text())

        while query.next():
            #table name
            ret.append(query.value(0))
        return ret

    def getFrameLayerName(self):
        '''
        Gets the frame layer name
        '''
        return 'public_aux_moldura_a'

    def getOrphanGeomTablesWithElements(self, loading=False):
        return []

    def getOrphanGeomTables(self):
        return []

    def checkAndCreateStyleTable(self):
        return None

    def getStylesFromDb(self, dbVersion):
        return None

    def getGeomTypeDict(self, loadCentroids=False):
        self.checkAndOpenDb()
        edgvVersion = self.getDatabaseVersion()
        sql = self.gen.getGeomByPrimitive(edgvVersion)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(
                self.tr("Problem getting geom types from db: ") +
                query.lastError().text())
        geomDict = dict()
        while query.next():
            if edgvVersion in ('2.1.3', 'FTer_2a_Ed'):
                type = query.value(0)
            else:
                type = self.getResolvedGeomType(query.value(0))
            tableName = query.value(1)
            layerName = '_'.join(tableName.split('_')[1::])
            if type not in geomDict.keys():
                geomDict[type] = []
            if layerName not in geomDict[type]:
                geomDict[type].append(layerName)
        return geomDict

    def getGeomDict(self, getCentroids=False):
        '''
        returns a dict like this:
        {'tablePerspective' : {
            'layerName' :
        '''
        self.checkAndOpenDb()
        edgvVersion = self.getDatabaseVersion()
        sql = self.gen.getGeomTablesFromGeometryColumns(edgvVersion)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(
                self.tr("Problem getting geom tables from db: ") +
                query.lastError().text())
        geomDict = dict()
        geomDict['primitivePerspective'] = self.getGeomTypeDict()
        geomDict['tablePerspective'] = dict()
        while query.next():
            isCentroid = False
            srid = query.value(0)
            if edgvVersion in ('2.1.3', 'FTer_2a_Ed'):
                geometryType = query.value(2)
            else:
                geometryType = self.getResolvedGeomType(query.value(2))
            tableName = query.value(3)
            tableSchema = tableName.split('_')[0]
            geometryColumn = query.value(1)
            layerName = '_'.join(tableName.split('_')[1::])
            if layerName not in geomDict['tablePerspective'].keys():
                geomDict['tablePerspective'][layerName] = dict()
                geomDict['tablePerspective'][layerName]['schema'] = tableSchema
                geomDict['tablePerspective'][layerName]['srid'] = str(srid)
                geomDict['tablePerspective'][layerName][
                    'geometryColumn'] = geometryColumn
                geomDict['tablePerspective'][layerName][
                    'geometryType'] = geometryType
                geomDict['tablePerspective'][layerName][
                    'tableName'] = tableName
        return geomDict

    def getGeomColumnDict(self):
        '''
        Dict in the form 'geomName':[-list of table names-]
        '''
        self.checkAndOpenDb()
        sql = self.gen.getGeomColumnDict()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(
                self.tr("Problem getting geom column dict: ") +
                query.lastError().text())
        geomDict = dict()
        while query.next():
            geomColumn = query.value(0)
            tableName = query.value(1)
            lyrName = '_'.join(tableName.split('_')[1::])
            if geomColumn not in geomDict.keys():
                geomDict[geomColumn] = []
            geomDict[geomColumn].append(lyrName)
        return geomDict

    def createFrame(self, type, scale, param, paramDict=dict()):
        mi, inom, frame = self.prepareCreateFrame(type, scale, param)
        self.insertFrame(scale, mi, inom, frame.asWkb())
        return frame

    def insertFrame(self, scale, mi, inom, frame):
        self.checkAndOpenDb()
        srid = self.findEPSG()
        geoSrid = QgsCoordinateReferenceSystem(
            int(srid)).geographicCRSAuthId().split(':')[-1]
        ogr.UseExceptions()
        outputDS = self.buildOgrDatabase()
        outputLayer = outputDS.GetLayerByName('public_aux_moldura_a')
        newFeat = ogr.Feature(outputLayer.GetLayerDefn())
        auxGeom = ogr.CreateGeometryFromWkb(frame)
        #set geographic srid from frame
        geoSrs = ogr.osr.SpatialReference()
        geoSrs.ImportFromEPSG(int(geoSrid))
        auxGeom.AssignSpatialReference(geoSrs)
        #reproject geom
        outSpatialRef = outputLayer.GetSpatialRef()
        coordTrans = osr.CoordinateTransformation(geoSrs, outSpatialRef)
        auxGeom.Transform(coordTrans)
        newFeat.SetGeometry(auxGeom)
        newFeat.SetField('mi', mi)
        newFeat.SetField('inom', inom)
        newFeat.SetField('escala', str(scale))
        out = outputLayer.CreateFeature(newFeat)
        outputDS.Destroy()

    def getTableSchemaFromDb(self, table):
        self.checkAndOpenDb()
        sql = self.gen.getFullTablesName(table)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(
                self.tr("Problem getting full table name: ") +
                query.lastError().text())
        while query.next():
            return query.value(0).split('_')[0]

    def getGeomColumnTupleList(self, showViews=False):
        """
        list in the format [(table_schema, table_name, geometryColumn, geometryType, tableType)]
        centroids are hidden by default
        """
        self.checkAndOpenDb()
        edgvVersion = self.getDatabaseVersion()
        sql = self.gen.getGeomColumnTupleList(edgvVersion)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(
                self.tr("Problem getting geom tuple list: ") +
                query.lastError().text())
        geomList = []
        while query.next():
            if edgvVersion in ['2.1.3', 'FTer_2a_Ed']:
                geomList.append((query.value(0).split('_')[0],
                                 '_'.join(query.value(0).split('_')[1::]),
                                 query.value(1), query.value(2), 'BASE TABLE'))
            else:
                geomList.append(
                    (query.value(0).split('_')[0],
                     '_'.join(query.value(0).split('_')[1::]), query.value(1),
                     self.getResolvedGeomType(int(query.value(2))),
                     'BASE TABLE'))
        return geomList

    def getResolvedGeomType(self, geometryType):
        geomDict = {
            0: 'GEOMETRY',
            1: 'POINT',
            2: 'LINESTRING',
            3: 'POLYGON',
            4: 'MULTIPOINT',
            5: 'MULTILINESTRING',
            6: 'MULTIPOLYGON',
            7: 'GEOMETRYCOLLECTION',
            8: 'CIRCULARSTRING',
            9: 'COMPOUNDCURVE',
            10: 'CURVEPOLYGON',
            11: 'MULTICURVE',
            12: 'MULTISURFACE',
            13: 'CURVE',
            14: 'SURFACE'
        }
        return geomDict[geometryType]
Example #22
0
 def __init__(self):
     self.factory = SqlGeneratorFactory()
Example #23
0
class Utils:
    def __init__(self):
        self.factory = SqlGeneratorFactory()

    def __del__(self):
        pass

    def getQmlDir(self, db):
        currentPath = os.path.dirname(__file__)
        if qgis.core.QGis.QGIS_VERSION_INT >= 20600:
            qmlVersionPath = os.path.join(currentPath, '..', 'Qmls', 'qgis_26')
        else:
            qmlVersionPath = os.path.join(currentPath, '..', 'Qmls', 'qgis_22')

        version = self.getDatabaseVersion(db)
        if version == '3.0':
            qmlPath = os.path.join(qmlVersionPath, 'edgv_30')
        elif version == '2.1.3':
            qmlPath = os.path.join(qmlVersionPath, 'edgv_213')
        return qmlPath

    def findEPSG(self, db):
        gen = self.factory.createSqlGenerator(self.isSpatialiteDB(db))
        sql = gen.getSrid()
        query = QSqlQuery(sql, db)
        srids = []
        while query.next():
            srids.append(query.value(0))
        return srids[0]

    def getPostGISConnectionParameters(self, name):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections/'+name)
        database = settings.value('database')
        host = settings.value('host')
        port = settings.value('port')
        user = settings.value('username')
        password = settings.value('password')
        settings.endGroup()
        return (database, host, port, user, password)

    def getPostGISConnections(self):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections')
        currentConnections = settings.childGroups()
        settings.endGroup()
        return currentConnections

    def getSpatialiteDatabase(self):
        db = None
        fd = QFileDialog()
        filename = fd.getOpenFileName(filter='*.sqlite')
        if filename:
            db = QSqlDatabase("QSQLITE")
            db.setDatabaseName(filename)
        return (filename, db)

    def getPostGISDatabase(self, postGISConnection):
        db = None
        db = QSqlDatabase("QPSQL")
        (database, host, port, user, password) = self.getPostGISConnectionParameters(postGISConnection)
        db.setDatabaseName(database)
        db.setHostName(host)
        db.setPort(int(port))
        db.setUserName(user)
        db.setPassword(password)
        return db

    def getDatabaseVersion(self, db):
        gen = self.factory.createSqlGenerator(self.isSpatialiteDB(db))
        sqlVersion = gen.getEDGVVersion()
        queryVersion =  QSqlQuery(sqlVersion, db)
        version = '2.1.3'
        while queryVersion.next():
            version = queryVersion.value(0)
        return version

    def isSpatialiteDB(self, db):
        if db.driverName() == 'QPSQL':
            isSpatialite = False
        elif db.driverName() == 'QSQLITE':
            isSpatialite = True
        return isSpatialite
Example #24
0
class PostgisDBTool(QDialog, Ui_Dialog):
    def __init__(self, iface):
        """Constructor."""
        super(PostgisDBTool, self).__init__()
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)

        self.iface = iface

        self.populateServersCombo()

        self.srs = None

        self.factory = SqlGeneratorFactory()
        #setting the sql generator
        self.gen = self.factory.createSqlGenerator(False)

        self.epsg = 4326

    def getParameters(self):
        return (self.getDatabase(self.databaseEdit.text()), self.versionCombo.currentText(), self.epsg)

    @pyqtSlot(bool)
    def on_saveButton_clicked(self):
        if self.createDatabase(self.databaseEdit.text()):
            self.storeConnectionConfiguration(self.serversCombo.currentText(), self.databaseEdit.text())
            self.done(1)
        else:
            self.done(0)

    @pyqtSlot(bool)
    def on_cancelButton_clicked(self):
        self.done(-1)

    @pyqtSlot(bool)
    def on_srsButton_clicked(self):
        projSelector = QgsGenericProjectionSelector()
        message = 'Select the Spatial Reference System!'
        projSelector.setMessage(theMessage=message)
        projSelector.exec_()
        try:
            self.epsg = int(projSelector.selectedAuthId().split(':')[-1])
            srs = QgsCoordinateReferenceSystem(self.epsg, QgsCoordinateReferenceSystem.EpsgCrsId)
            if srs:
                self.srsEdit.setText(srs.description())
            else:
                self.epsg = 4326
        except:
            QMessageBox.warning(self, self.tr("Warning!"), self.tr(message))

    def createDatabase(self, name):
        sql = self.gen.getCreateDatabase(name)

        db = self.getDatabase()

        #creating the database
        query = QSqlQuery(db)
        if not query.exec_(sql):
            QMessageBox.warning(self, self.tr("Warning!"), query.lastError().text())
            db.close()
            return False
        db.close()
        return True

    def getDatabase(self, database = 'postgres'):
        (host, port, user, password) = self.getServerConfiguration(self.serversCombo.currentText())

        db = QSqlDatabase("QPSQL")
        db.setDatabaseName(database)
        db.setHostName(host)
        db.setPort(int(port))
        db.setUserName(user)
        db.setPassword(password)
        if not db.open():
            QgsMessageLog.logMessage(db.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)

        return db

    def updateConnectionName(self):
        server = self.serversCombo.currentText()
        database = self.databaseEdit.text()
        name = server+'_'+database
        self.connectionEdit.setText(name)

    def on_serversCombo_currentIndexChanged(self, index):
        self.updateConnectionName()

    def on_databaseEdit_textEdited(self, text):
        text = text.lower()
        self.databaseEdit.setText(text)
        self.updateConnectionName()

    def checkFields(self):
        if self.serversCombo.currentText() == '' or self.databaseEdit.text() == '' \
            or self.srsEdit.text() == '':
            return False
        return True

    def getServerConfiguration(self, name):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers/'+name)
        host = settings.value('host')
        port = settings.value('port')
        user = settings.value('username')
        password = settings.value('password')
        settings.endGroup()
        return (host, port, user, password)

    def storeConnectionConfiguration(self, server, database):
        name = self.connectionEdit.text()

        (host, port, user, password) = self.getServerConfiguration(server)

        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections/'+name)
        settings.setValue('database', database)
        settings.setValue('host', host)
        settings.setValue('port', port)
        settings.setValue('username', user)
        settings.setValue('password', password)
        settings.endGroup()

    def getServers(self):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers')
        currentConnections = settings.childGroups()
        settings.endGroup()
        return currentConnections

    def populateServersCombo(self):
        self.serversCombo.clear()
        currentConnections = self.getServers()
        for connection in currentConnections:
            self.serversCombo.addItem(connection)
Example #25
0
class PostgisDBTool(QDialog, FORM_CLASS):
    def __init__(self, iface):
        """Constructor."""
        super(PostgisDBTool, self).__init__()
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)

        self.iface = iface

        self.populateServersCombo()

        self.srs = None

        self.factory = SqlGeneratorFactory()
        #setting the sql generator
        self.gen = self.factory.createSqlGenerator(False)

        self.epsg = 4326

    def getParameters(self):
        return (self.getDatabase(self.databaseEdit.text()), self.versionCombo.currentText(), self.epsg)

    @pyqtSlot(bool)
    def on_saveButton_clicked(self):
        if self.createDatabase(self.databaseEdit.text()):
            self.storeConnectionConfiguration(self.serversCombo.currentText(), self.databaseEdit.text())
            self.done(1)
        else:
            self.done(0)

    @pyqtSlot(bool)
    def on_cancelButton_clicked(self):
        self.done(-1)

    @pyqtSlot(bool)
    def on_configureServerButton_clicked(self):
        dlg = ViewServers(self.iface)
        dlg.show()
        result = dlg.exec_()
        self.populateServersCombo()
        

    @pyqtSlot(bool)
    def on_srsButton_clicked(self):
        projSelector = QgsGenericProjectionSelector()
        message = 'Select the Spatial Reference System!'
        projSelector.setMessage(theMessage=message)
        projSelector.exec_()
        try:
            self.epsg = int(projSelector.selectedAuthId().split(':')[-1])
            srs = QgsCoordinateReferenceSystem(self.epsg, QgsCoordinateReferenceSystem.EpsgCrsId)
            if srs:
                self.srsEdit.setText(srs.description())
            else:
                self.epsg = 4326
        except:
            QMessageBox.warning(self, self.tr("Warning!"), self.tr(message))

    def createDatabase(self, name):
        sql = self.gen.getCreateDatabase(name)

        db = self.getDatabase()

        #creating the database
        query = QSqlQuery(db)
        if not query.exec_(sql):
            QMessageBox.warning(self, self.tr("Warning!"), query.lastError().text())
            db.close()
            return False
        db.close()
        return True

    def getDatabase(self, database = 'postgres'):
        (host, port, user, password) = self.getServerConfiguration(self.serversCombo.currentText())
        db = QSqlDatabase("QPSQL")
        db.setConnectOptions('connect_timeout=10')
        db.setDatabaseName(database)
        db.setHostName(host)
        db.setPort(int(port))
        db.setUserName(user)

        if password == '':
            conInfo = 'host='+host+' port='+port+' dbname='+database
            self.setCredentials(db, conInfo, user)
        else:
            db.setPassword(password)

        if not db.open():
            QgsMessageLog.logMessage(db.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)

        return db

    def setCredentials(self, db, conInfo, user):
        (success, user, password) = QgsCredentials.instance().get(conInfo, user, None)
        if not success:
            return
        else:
            db.setPassword(password)
            if not db.open():
                self.setCredentials(db, conInfo, user)
            else:
                QgsCredentials.instance().put(conInfo, user, password)

    def updateConnectionName(self):
        server = self.serversCombo.currentText()
        database = self.databaseEdit.text()
        name = server+'_'+database
        self.connectionEdit.setText(name)

    def on_serversCombo_currentIndexChanged(self, index):
        self.updateConnectionName()

    def on_databaseEdit_textEdited(self, text):
        text = text.lower()
        self.databaseEdit.setText(text)
        self.updateConnectionName()

    def checkFields(self):
        if self.serversCombo.currentText() == '' or self.databaseEdit.text() == '' or self.srsEdit.text() == '':
            return False
        return True

    def getServerConfiguration(self, name):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers/'+name)
        host = settings.value('host')
        port = settings.value('port')
        user = settings.value('username')
        password = settings.value('password')
        settings.endGroup()
        return (host, port, user, password)

    def storeConnectionConfiguration(self, server, database):
        name = self.connectionEdit.text()

        (host, port, user, password) = self.getServerConfiguration(server)

        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections/'+name)
        settings.setValue('database', database)
        settings.setValue('host', host)
        settings.setValue('port', port)
        settings.setValue('username', user)
        settings.setValue('password', password)
        settings.endGroup()

    def getServers(self):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers')
        currentConnections = settings.childGroups()
        settings.endGroup()
        return currentConnections

    def populateServersCombo(self):
        self.serversCombo.clear()
        currentConnections = self.getServers()
        for connection in currentConnections:
            self.serversCombo.addItem(connection)
Example #26
0
class PostgisDbThread(GenericThread):
    def __init__(self, parent=None):
        """
        Constructor.
        """
        super(PostgisDbThread, self).__init__()

        self.factory = SqlGeneratorFactory()
        #setting the sql generator
        self.gen = self.factory.createSqlGenerator(False)
        self.messenger = PostgisDbMessages(self)
        self.dbFactory = DbFactory()
        self.parent = parent

    def setParameters(self, abstractDb, dbName, version, epsg, stopped):
        """
        Sets thread parameters
        """
        self.abstractDb = abstractDb  #database = postgis
        self.dbName = dbName
        self.db = None
        self.version = version
        self.epsg = epsg
        self.stopped = stopped

    def run(self):
        """
        Runs the process
        """
        # Processing ending
        (ret, msg) = self.createDatabaseStructure()
        self.signals.processingFinished.emit(ret, msg, self.getId())

    def connectToTemplate(self, setInnerDb=True):
        """
        Connects to the template database to speed up database creation
        :return:
        """
        database = self.abstractDb.getTemplateName(self.version)
        host = self.abstractDb.db.hostName()
        port = self.abstractDb.db.port()
        user = self.abstractDb.db.userName()
        password = self.abstractDb.db.password()
        template = self.dbFactory.createDbFactory('QPSQL')
        template.connectDatabaseWithParameters(host, port, database, user,
                                               password)
        template.checkAndOpenDb()
        if setInnerDb:
            self.db = template.db
        return template

    def createDatabaseStructure(self):
        """
        Creates database structure according to the selected edgv version
        """
        currentPath = os.path.dirname(__file__)
        currentPath = os.path.join(currentPath, '..', '..', 'DbTools',
                                   'PostGISTool')
        if self.version == '2.1.3':
            edgvPath = os.path.join(currentPath, 'sqls', '213', 'edgv213.sql')
        elif self.version == '3.0':
            edgvPath = os.path.join(currentPath, 'sqls', '3', 'edgv3.sql')
        elif self.version == 'FTer_2a_Ed':
            edgvPath = os.path.join(currentPath, 'sqls', 'FTer_2a_Ed',
                                    'edgvFter_2a_Ed.sql')
        else:
            pass
        return self.loadDatabaseStructure(edgvPath)

    def loadDatabaseStructure(self, edgvPath):
        """
        Loads the database structure
        edgvPath: path to the databse sql
        """
        commands = []
        hasTemplate = self.abstractDb.checkTemplate(self.version)
        if hasTemplate:
            templateDb = self.connectToTemplate(setInnerDb=False)
            mustUpdateTemplate = templateDb.checkTemplateImplementationVersion(
            )
            if mustUpdateTemplate:
                templateName = templateDb.db.databaseName()
                templateDb.__del__()
                self.abstractDb.dropDatabase(templateName, dropTemplate=True)
                hasTemplate = False
        if not hasTemplate:
            file = codecs.open(edgvPath, encoding='utf-8', mode="r")
            sql = file.read()
            sql = sql.replace('[epsg]', '4674')
            file.close()
            commands = [i for i in sql.split('#') if i != '']
        # Progress bar steps calculated
        self.signals.rangeCalculated.emit(len(commands) + 4, self.getId())

        if not hasTemplate:
            try:
                self.abstractDb.createTemplateDatabase(self.version)
                self.signals.stepProcessed.emit(self.getId())
                self.connectToTemplate()
                self.signals.stepProcessed.emit(self.getId())
            except Exception as e:
                return (0, self.messenger.getProblemFeedbackMessage() + '\n' +
                        ':'.join(e.args))
            self.db.open()
            self.db.transaction()
            query = QSqlQuery(self.db)

            for command in commands:
                if not self.stopped[0]:
                    if not query.exec_(command):
                        QgsMessageLog.logMessage(
                            self.messenger.getProblemMessage(command, query),
                            "DSG Tools Plugin", QgsMessageLog.CRITICAL)
                        self.db.rollback()
                        self.db.close()
                        self.dropDatabase(self.db)
                        return (0, self.messenger.getProblemFeedbackMessage())

                    # Updating progress
                    self.signals.stepProcessed.emit(self.getId())
                else:
                    self.db.rollback()
                    self.db.close()
                    self.dropDatabase(self.db)
                    QgsMessageLog.logMessage(
                        self.messenger.getUserCanceledFeedbackMessage(),
                        "DSG Tools Plugin", QgsMessageLog.INFO)
                    return (-1,
                            self.messenger.getUserCanceledFeedbackMessage())

            self.db.commit()
            if self.version == '2.1.3':
                sql = 'ALTER DATABASE %s SET search_path = "$user", public, topology,\'cb\',\'complexos\',\'dominios\';' % self.db.databaseName(
                )
            elif self.version == 'FTer_2a_Ed':
                sql = 'ALTER DATABASE %s SET search_path = "$user", public, topology,\'pe\',\'ge\',\'complexos\',\'dominios\';' % self.db.databaseName(
                )
            elif self.version == '3.0':
                sql = 'ALTER DATABASE %s SET search_path = "$user", public, topology,\'edgv\',\'complexos\',\'dominios\';' % self.db.databaseName(
                )

            if sql:
                if not query.exec_(sql):
                    QgsMessageLog.logMessage(
                        self.messenger.getProblemMessage(command, query),
                        "DSG Tools Plugin", QgsMessageLog.CRITICAL)
                    return (0, self.messenger.getProblemFeedbackMessage())
            #this commit was missing, so alter database statement was not commited.
            self.db.commit()
            self.db.close()
            self.abstractDb.setDbAsTemplate(self.version)
        #creates from template
        if not self.stopped[0]:
            templateName = self.abstractDb.getTemplateName(self.version)
            self.abstractDb.createDbFromTemplate(self.dbName,
                                                 templateName,
                                                 parentWidget=self.parent)
            self.signals.stepProcessed.emit(self.getId())
            #5. alter spatial structure
            createdDb = self.dbFactory.createDbFactory('QPSQL')
            createdDb.connectDatabaseWithParameters(
                self.abstractDb.db.hostName(), self.abstractDb.db.port(),
                self.dbName, self.abstractDb.db.userName(),
                self.abstractDb.db.password())
            errorTuple = createdDb.updateDbSRID(self.epsg,
                                                parentWidget=self.parent,
                                                threading=True)
            # if an error occur during the thread we should pass the message to the main thread
            if errorTuple:
                QgsMessageLog.logMessage(
                    self.messenger.getProblemMessage(errorTuple[0],
                                                     errorTuple[1]),
                    "DSG Tools Plugin", QgsMessageLog.CRITICAL)
                return (0, self.messenger.getProblemFeedbackMessage())
            self.signals.stepProcessed.emit(self.getId())
        else:
            QgsMessageLog.logMessage(
                self.messenger.getUserCanceledFeedbackMessage(),
                "DSG Tools Plugin", QgsMessageLog.INFO)
            return (-1, self.messenger.getUserCanceledFeedbackMessage())
        QgsMessageLog.logMessage(self.messenger.getSuccessFeedbackMessage(),
                                 "DSG Tools Plugin", QgsMessageLog.INFO)
        return (1, self.messenger.getSuccessFeedbackMessage())

    def dropDatabase(self, db):
        """
        Drops the created database case a problem occurs during database creation
        db: QSqlDatabase to be dropped
        """
        host = db.hostName()
        port = db.port()
        user = db.userName()
        password = db.password()
        database = 'postgres'
        pgDB = QSqlDatabase('QPSQL')
        pgDB.setHostName(host)
        pgDB.setPort(port)
        pgDB.setUserName(user)
        pgDB.setPassword(password)
        pgDB.setDatabaseName(database)
        if not pgDB.open():
            return False
        sql = self.gen.dropDatabase(db.databaseName())
        query = QSqlQuery(pgDB)
        return query.exec_(sql)
Example #27
0
class ComplexWindow(QtGui.QDockWidget, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(ComplexWindow, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        #self.enderecoLine.setText('186.228.51.52')
        #self.portaLine.setText('2101'
        self.iface = iface

        QObject.connect(self.dbButton, SIGNAL(("clicked()")), self.getDataSources)
        QObject.connect(self.dbCombo, SIGNAL("activated(int)"), self.updateComplexClass)
        QObject.connect(self.complexCombo, SIGNAL("activated(int)"), self.loadAssociatedFeatures)
        QObject.connect(self.iface, SIGNAL("newProjectCreated()"), self.clearDock)

        self.db = None
        self.databases = None
        self.factory = SqlGeneratorFactory()
        self.gen = None

    def __del__(self):
        if self.db:
            self.db.close()
            self.db = None

    def clearDock(self):
        self.treeWidget.clear()
        self.dbCombo.clear()
        self.complexCombo.clear()

    def isSpatialiteDatabase(self, dbName):
        (dataSourceUri, credentials) = self.databases[dbName]
        if dataSourceUri.host() == "":
            return True
        return False

    def getUserCredentials(self, lyr):
        dataSourceUri = QgsDataSourceURI( lyr.dataProvider().dataSourceUri() )
        if dataSourceUri.host() == "":
            return (None, None)

        connInfo = dataSourceUri.connectionInfo()
        (success, user, passwd ) = QgsCredentials.instance().get( connInfo, None, None )
        # Put the credentials back (for yourself and the provider), as QGIS removes it when you "get" it
        if success:
            QgsCredentials.instance().put( connInfo, user, passwd )

        return (user, passwd)

    def updateComplexClass(self):
        if self.db:
            self.db.close()
            self.db = None

        if self.dbCombo.currentIndex() == 0:
            return

        dbName = self.dbCombo.currentText()

        #getting the sql generator
        self.gen = self.factory.createSqlGenerator(self.isSpatialiteDatabase(dbName))

        (dataSourceUri, credentials) = self.databases[dbName]
        #verifying the connection type
        if self.isSpatialiteDatabase(dbName):
            self.db = QSqlDatabase("QSQLITE")
            self.db.setDatabaseName(dbName)
        else:
            self.db = QSqlDatabase("QPSQL")
            self.db.setDatabaseName(dbName)
            self.db.setHostName(dataSourceUri.host())
            self.db.setPort(int(dataSourceUri.port()))
            self.db.setUserName(credentials[0])
            self.db.setPassword(credentials[1])
        if not self.db.open():
            print self.db.lastError().text()

        self.populateComboBox()

    def populateComboBox(self):
        #getting all complex tables
        self.complexCombo.clear()
        self.complexCombo.addItem(self.tr("select a complex class"))

        dbName = self.dbCombo.currentText()
        (dataSourceUri, credentials) = self.databases[dbName]

        #getting all complex tables
        query = QSqlQuery(self.gen.getComplexTablesFromDatabase(), self.db)
        while query.next():
            self.complexCombo.addItem(query.value(0))

    def getDataSources(self):
        self.dbCombo.clear()
        self.dbCombo.addItem(self.tr("select a database"))

        if self.databases:
            self.databases.clear()

        #dictionary of names and datasourceUri
        self.databases = dict()
        self.layers = self.iface.mapCanvas().layers()
        for layer in self.layers:
            dataSourceUri = QgsDataSourceURI( layer.dataProvider().dataSourceUri() )
            dbName = dataSourceUri.database()
            if dbName not in self.databases:
                self.databases[dbName] = (dataSourceUri,self.getUserCredentials(layer))
                #populating the combo
                self.dbCombo.addItem(dbName)

    @pyqtSlot(bool)
    def on_managePushButton_clicked(self):
        #opens a dialog to manage complexes
        if self.isSpatialiteDatabase(self.dbCombo.currentText()):
            self.dlg = ManageComplexDialog(self.iface, self.db, self.complexCombo.currentText())
        else:
            self.dlg = ManageComplexDialog(self.iface, self.db, 'complexos.'+self.complexCombo.currentText())
        #connects a signal to update the tree widget when done
        QObject.connect(self.dlg, SIGNAL(("tableUpdated()")), self.loadAssociatedFeatures)
        #connects a signal to disassociate features from complex before removal
        QObject.connect(self.dlg, SIGNAL(("markedToRemove( PyQt_PyObject )")), self.disassociateFeatures)
        result = self.dlg.exec_()
        if result:
            pass

    @pyqtSlot(bool)
    def on_associatePushButton_clicked(self):
        self.associateFeatures()

    @pyqtSlot(bool)
    def on_zoomButton_clicked(self):
        #case no item is selected we should warn the user
        if len(self.treeWidget.selectedItems()) == 0:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("Please, select an item to zoom."))
            return

        item = self.treeWidget.selectedItems()[0]
        #checking if the item is a complex (it should have depth = 2)
        if self.depth(item) == 2:
            bbox = QgsRectangle()
            for i in range(item.childCount()):
                aggregated_item = item.child(i)
                aggregated_class = aggregated_item.text(0)
                #getting the layer the needs to be updated
                aggregated_layer = None
                layers = self.iface.mapCanvas().layers()
                for layer in layers:
                    if layer.name() == aggregated_class:
                        aggregated_layer = layer
                        break

                if not aggregated_layer:
                    QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("The associated classes must be loaded in the table of contents."))
                    return

                for j in range(aggregated_item.childCount()):
                    id = aggregated_item.child(j).text(0)
                    freq = QgsFeatureRequest()
                    freq.setFilterFid(int(id))
                    feature = layer.getFeatures( freq ).next()
                    if j==0:
                        bbox=feature.geometry().boundingBox()
                    bbox.combineExtentWith(feature.geometry().boundingBox())

            self.iface.mapCanvas().setExtent(bbox)
            self.iface.mapCanvas().refresh()
        else:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("Select a complex."))
            return

    def getAdjustedComplexName(self, dbName, complex):
        if self.isSpatialiteDatabase(dbName):
            complex = '\''+complex.replace("complexos_","")+'\''
        else:
            complex = '\''+complex+'\''
        return complex

    def disassociateFeatures(self, toBeRemoved):
        for uuid in toBeRemoved:
            items = self.treeWidget.findItems(uuid, Qt.MatchRecursive, 1)
            if len(items) == 0:
                return
            complexItem = items[0]
            count = complexItem.childCount()
            for i in range(count):
                self.disassociateAggregatedClass(complexItem.child(i))

    def disassociateAggregatedClass(self, item):
        aggregated_class = item.text(0)
        uuid = item.parent().text(1)
        complex = item.parent().parent().text(0)
        complex = self.getAdjustedComplexName(self.dbCombo.currentText(), complex)
        link_column = self.obtainLinkColumn(complex, aggregated_class)

        #getting the layer the needs to be updated
        aggregated_layer = None
        layers = self.iface.mapCanvas().layers()
        for layer in layers:
            if layer.name() == aggregated_class:
                aggregated_layer = layer
                break

        if not aggregated_layer:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("The class you're trying to disassociate must loaded in the table of contents."))
            return

        for i in range(item.childCount()):
            #feature id that will be updated
            id = item.child(i).text(0)
            self.updateLayerOnDisassociate(layer, aggregated_class, link_column, id)

    def disassociateAggregatedId(self, item):
        aggregated_class = item.parent().text(0)
        uuid = item.parent().parent().text(1)
        complex = item.parent().parent().parent().text(0)
        complex = self.getAdjustedComplexName(self.dbCombo.currentText(), complex)
        link_column = self.obtainLinkColumn(complex, aggregated_class)

        #getting the layer the needs to be updated
        aggregated_layer = None
        layers = self.iface.mapCanvas().layers()
        for layer in layers:
            if layer.name() == aggregated_class:
                aggregated_layer = layer
                break

        if not aggregated_layer:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("The class you're trying to disassociate must loaded in the table of contents."))
            return

        #feature id that will be updated
        id = item.text(0)
        self.updateLayerOnDisassociate(layer, aggregated_class, link_column, id)

    def updateLayerOnDisassociate(self, layer, aggregated_class, link_column, id):
        if self.isComplexClass(aggregated_class):
            sql = self.gen.disassociateComplexFromComplex(aggregated_class, link_column, id)
            query = QSqlQuery(sql, self.db)
        else:
            #field index that will be set to NULL
            fieldIndex = [i for i in range(len(layer.dataProvider().fields())) if layer.dataProvider().fields()[i].name() == link_column]
            #attribute pair that will be changed
            attrs = {fieldIndex[0]:None}
            #actual update in the database
            layer.dataProvider().changeAttributeValues({int(id):attrs})

    def isComplexClass(self, className):
        #getting all complex tables
        query = QSqlQuery(self.gen.getComplexTablesFromDatabase(), self.db)
        while query.next():
            if query.value(0) == className:
                return True
        return False

    @pyqtSlot(bool)
    def on_disassociatePushButton_clicked(self):
        #case no item is selected we should warn the user
        if len(self.treeWidget.selectedItems()) == 0:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("Please, select an aggregated class or aggregated id."))
            return

        item = self.treeWidget.selectedItems()[0]
        #checking if the item is a complex (it should have depth = 2)
        if self.depth(item) == 3:
            self.disassociateAggregatedClass(item)
        elif self.depth(item) == 4:
            self.disassociateAggregatedId(item)
        else:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("Please, select an aggregated class or aggregated id."))
            return

        self.loadAssociatedFeatures()

    def loadAssociatedFeatures(self):
        self.treeWidget.clear()

        if self.complexCombo.currentIndex() == 0:
            return

        complex = self.complexCombo.currentText()
        complex = self.getAdjustedComplexName(self.dbCombo.currentText(), complex)

        #query to get the possible links to the selected complex in the combobox
        sql = self.gen.getComplexLinks(complex)
        query = QSqlQuery(sql, self.db)
        while query.next():
            #setting the variables
            complex_schema = query.value(0)
            complex = query.value(1)
            aggregated_schema = query.value(2)
            aggregated_class = query.value(3)
            column_name = query.value(4)

            #query to obtain the created complexes
            sql = self.gen.getComplexData(complex_schema, complex)
            complexQuery = QSqlQuery(sql, self.db)
            while complexQuery.next():
                complex_uuid = complexQuery.value(0)
                name = complexQuery.value(1)

                if not (complex_uuid and name):
                    continue
                #adding the information in the tree widget case there are no associated features
                if self.isSpatialiteDatabase(self.dbCombo.currentText()):
                    self.addAssociatedFeature(complex_schema+"_"+complex, name, complex_uuid, None, None)
                else:
                    self.addAssociatedFeature(complex, name, complex_uuid, None, None)

                #query to obtain the id of the associated feature
                sql = self.gen.getAssociatedFeaturesData(aggregated_schema, aggregated_class, column_name, complex_uuid)
                associatedQuery = QSqlQuery(sql, self.db)

                while associatedQuery.next():
                    ogc_fid = associatedQuery.value(0)
                    #adding the information in the tree widget
                    if self.isSpatialiteDatabase(self.dbCombo.currentText()):
                        self.addAssociatedFeature(str(complex_schema+"_"+complex), str(name), complex_uuid, str(aggregated_schema+"_"+aggregated_class), ogc_fid)
                    else:
                        self.addAssociatedFeature(str(complex), str(name), complex_uuid, str(aggregated_class), ogc_fid)

    def depth(self, item):
        #calculates the depth of the item
        depth = 0
        while item is not None:
            item = item.parent()
            depth += 1
        return depth

    def obtainLinkColumn(self, complexClass, aggregatedClass):
        #query to obtain the link column between the complex and the feature layer
        sql = self.gen.getLinkColumn(complexClass, aggregatedClass)
        query = QSqlQuery(sql, self.db)
        column_name = ""
        while query.next():
            column_name = query.value(0)
        return column_name

    def associateFeatures(self):
        #case no item is selected we should warn the user
        if len(self.treeWidget.selectedItems()) == 0:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("Please, select a complex."))
            return

        item = self.treeWidget.selectedItems()[0]
        #checking if the item is a complex (it should have depth = 2)
        if self.depth(item) != 2:
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr("Please, select a complex."))
            return

        complex = self.complexCombo.currentText()
        #surrounding the name with ''
        complex = self.getAdjustedComplexName(self.dbCombo.currentText(), complex)

        #uuid to be adjust on the selected features
        uuid = item.text(1)

        #getting the selected features
        forbiddenLayers = []
        self.layers = self.iface.mapCanvas().layers()
        for layer in self.layers:
            #case no fetures selected we proceed to the next one
            selectedFeatures = layer.selectedFeatures()
            if len(selectedFeatures) == 0:
                continue

            #obtaining the link column
            column_name = self.obtainLinkColumn(complex, layer.name())

            #storing the names of the incompatible layers
            if column_name == "":
                forbiddenLayers.append(layer.name())
                continue

            for feature in selectedFeatures:
                fieldIndex = [i for i in range(len(layer.dataProvider().fields())) if layer.dataProvider().fields()[i].name() == column_name]
                #feature id that will be updated
                id = feature.id()
                #attribute pair that will be changed
                attrs = {fieldIndex[0]:uuid}
                #actual update in the database
                layer.dataProvider().changeAttributeValues({id:attrs})

        #show the message of incompatible classes to associate
        if len(forbiddenLayers) > 0:
            message = ""
            message += self.tr("The following layers cannot be associated to complexes from ")+self.complexCombo.currentText()+":\n"
            for text in forbiddenLayers:
                message += text+"\n"
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), message)

        #updating the tree widget
        self.loadAssociatedFeatures()

    def createTreeItem(self, parent, text, uuid = ""):
        count = parent.childCount()
        children = []
        #making a list of item names
        for i in range(count):
            child = parent.child(i)
            children.append(child.text(0))

        #checking if the text is already in the tree widget
        if text not in children:
            #case not it should be created
            item = QTreeWidgetItem(parent)
            item.setExpanded(True)
            item.setText(0,text)
            #adding the complex uuid to the tree widget
            if uuid != "":
                item.setText(1, str(uuid))
        else:
            #case already exists the correspondind item should be returned
            for i in range(count):
                child = parent.child(i)
                if child.text(0) == text:
                    item = child
        return item

    def addAssociatedFeature(self, className, complexName, complexId, associatedClass, associatedId):
        #get the corresponding top level item
        classNameItem = self.createTreeItem(self.treeWidget.invisibleRootItem(), className)
        #get the corresponding complex item
        complexNameItem = self.createTreeItem(classNameItem, complexName, complexId)
        if associatedClass and associatedId:
            #get the corresponding class item
            associatedClassItem = self.createTreeItem(complexNameItem, associatedClass)
            #creates the corresponding associated item
            self.createTreeItem(associatedClassItem, str(associatedId))

    def __test(self, x):
        if (x.parent() == None) :
            return True
        else:
            return False
Example #28
0
class SpatialiteDb(AbstractDb):
    def __init__(self):
        super(SpatialiteDb, self).__init__()
        self.db = QSqlDatabase('QSQLITE')
        self.gen = SqlGeneratorFactory().createSqlGenerator(True)

    def getDatabaseName(self):
        return self.db.databaseName().split('.sqlite')[0].split('/')[-1]

    def connectDatabase(self, conn=None):
        if conn is None:
            self.connectDatabaseWithGui()
        else:
            self.db.setDatabaseName(conn)

    def connectDatabaseWithGui(self):
        fd = QFileDialog()
        filename = fd.getOpenFileName(
            caption=self.tr('Select a DSGTools Spatialite file'),
            filter=self.tr('Spatialite file databases (*.sqlite)'))
        self.db.setDatabaseName(filename)

    def connectDatabaseWithQSettings(self, name):
        return None

    def connectDatabaseWithParameters(self, host, port, database, user,
                                      password):
        return None

    def listGeomClassesFromDatabase(self):
        try:
            self.checkAndOpenDb()
        except:
            return []
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        while query.next():
            tableName = str(query.value(0))
            layerName = tableName
            if tableName.split("_")[-1] == "p" or tableName.split("_")[-1] == "l" \
                or tableName.split("_")[-1] == "a":
                classList.append(layerName)
        return classList

    def listComplexClassesFromDatabase(self):
        try:
            self.checkAndOpenDb()
        except:
            return []
        classList = []
        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        while query.next():
            tableName = str(query.value(0))
            layerName = tableName
            tableSchema = layerName.split('_')[0]
            if tableSchema == 'complexos':
                classList.append(layerName)
        return classList

    def getConnectionFromQSettings(self, conName):
        return None

    def storeConnection(self, server):
        return None

    def getServerConfiguration(self, name):
        return None

    def getStructureDict(self):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        classDict = dict()
        sql = self.gen.getStructure(self.getDatabaseVersion())
        query = QSqlQuery(sql, self.db)
        while query.next():
            className = str(query.value(0))
            classSql = str(query.value(1))
            if className.split('_')[0] == 'complexos' or className.split(
                    '_')[-1] in ['p', 'l', 'a']:
                if className not in classDict.keys():
                    classDict[className] = dict()
                classSql = classSql.split(className)[1]
                sqlList = classSql.replace('(', '').replace(')', '').replace(
                    '\"', '').replace('\'', '').split(',')
                for s in sqlList:
                    fieldName = str(s.strip().split(' ')[0])
                    classDict[className][fieldName] = fieldName

                if 'GEOMETRY' in classDict[className].keys():
                    classDict[className]['GEOMETRY'] = 'geom'
                if 'OGC_FID' in classDict[className].keys():
                    classDict[className]['OGC_FID'] = 'id'

        return classDict

    def makeOgrConn(self):
        constring = self.db.databaseName()
        return constring

    def getNotNullDict(self):
        return None

    def getDomainDict(self):
        return None

    def validateWithOutputDatabaseSchema(self, outputAbstractDb):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        invalidated = self.buildInvalidatedDict()
        inputdbStructure = self.getStructureDict()
        outputdbStructure = outputAbstractDb.getStructureDict()
        domainDict = outputAbstractDb.getDomainDict()
        classes = self.listClassesWithElementsFromDatabase()
        notNullDict = outputAbstractDb.getNotNullDict()

        for inputClass in classes.keys():
            outputClass = self.translateAbstractDbLayerNameToOutputFormat(
                inputClass, outputAbstractDb)
            (schema, className) = self.getTableSchema(inputClass)
            if outputClass in outputdbStructure.keys():
                outputAttrList = self.reorderTupleList(
                    outputdbStructure[outputClass].keys())
                inputAttrList = self.reorderTupleList(
                    inputdbStructure[inputClass].keys())

                sql = self.gen.getFeaturesWithSQL(inputClass, inputAttrList)
                query = QSqlQuery(sql, self.db)

                while query.next():
                    id = query.value(0)
                    #detects null lines
                    for i in range(len(inputAttrList)):
                        nullLine = True
                        value = query.value(i)
                        if value <> None:
                            nullLine = False
                            break
                    if nullLine:
                        if cl not in invalidated['nullLine'].keys():
                            invalidated['nullLine'][inputClass] = 0
                        invalidated['nullLine'][inputClass] += 1

                    #validates pks
                    if id == None and (not nullLine):
                        if cl not in invalidated['nullPk'].keys():
                            invalidated['nullPk'][inputClass] = 0
                        invalidated['nullPk'][inputClass] += 1

                    for i in range(len(inputAttrList)):
                        value = query.value(i)
                        #validates domain
                        if outputClass in domainDict.keys():
                            if inputAttrList[i] in domainDict[
                                    outputClass].keys():
                                if value not in domainDict[outputClass][
                                        inputAttrList[i]] and (not nullLine):
                                    invalidated = self.utils.buildNestedDict(
                                        invalidated, [
                                            'notInDomain', inputClass, id,
                                            inputAttrList[i]
                                        ], value)
                        #validates not nulls
                        if outputClass in notNullDict.keys():
                            if outputClass in domainDict.keys():
                                if inputAttrList[i] in notNullDict[
                                        outputClass] and inputAttrList[
                                            i] not in domainDict[
                                                outputClass].keys():
                                    if (value == None) and (not nullLine) and (
                                            inputAttrList[i] not in
                                            domainDict[outputClass].keys()):
                                        invalidated = self.utils.buildNestedDict(
                                            invalidated, [
                                                'nullAttribute', inputClass,
                                                id, inputAttrList[i]
                                            ], value)
                            else:
                                if inputAttrList[i] in notNullDict[
                                        outputClass]:
                                    if (value == None) and (not nullLine) and (
                                            inputAttrList[i] not in
                                            domainDict[outputClass].keys()):
                                        invalidated = self.utils.buildNestedDict(
                                            invalidated, [
                                                'nullAttribute', inputClass,
                                                id, inputAttrList[i]
                                            ], value)
                        if outputClass in domainDict.keys():
                            if (inputAttrList[i] not in [
                                    'geom', 'GEOMETRY', 'id', 'OGC_FID'
                            ] and schema <> 'complexos') or (
                                    schema == 'complexos'
                                    and inputAttrList[i] <> 'id'):
                                if inputAttrList[i] not in outputdbStructure[
                                        outputClass].keys():
                                    invalidated = self.utils.buildNestedDict(
                                        invalidated, [
                                            'attributeNotFoundInOutput',
                                            inputClass
                                        ], [inputAttrList[i]])

            else:
                invalidated['classNotFoundInOutput'].append(inputAttrList)
        return invalidated

    def translateAbstractDbLayerNameToOutputFormat(self, lyr,
                                                   outputAbstractDb):
        if outputAbstractDb.db.driverName() == 'QSQLITE':
            return lyr
        if outputAbstractDb.db.driverName() == 'QPSQL':
            return str(lyr.split('_')[0] + '.' + '_'.join(lyr.split('_')[1::]))

    def translateOGRLayerNameToOutputFormat(self, lyr, ogrOutput):
        if ogrOutput.GetDriver().name == 'SQLite':
            return lyr
        if ogrOutput.GetDriver().name == 'PostgreSQL':
            return str(lyr.split('_')[0] + '.' + '_'.join(lyr.split('_')[1::]))

    def getTableSchema(self, lyr):
        schema = lyr.split('_')[0]
        className = '_'.join(lyr.split('_')[1::])
        return (schema, className)

    def convertToPostgis(self, outputAbstractDb, type=None):
        try:
            self.checkAndOpenDb()
        except:
            return False
        (inputOgrDb, outputOgrDb, fieldMap, inputLayerList,
         errorDict) = self.prepareForConversion(outputAbstractDb)
        invalidated = self.validateWithOutputDatabaseSchema(outputAbstractDb)
        hasErrors = self.makeValidationSummary(invalidated)
        if type == 'untouchedData':
            if hasErrors:
                self.signals.updateLog.emit('\n\n\n' + self.tr(
                    'Conversion not perfomed due to validation errors! Check log above for more information.'
                ))
                return False
            else:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap,
                                          inputLayerList, errorDict)
                return status
        if type == 'fixData':
            if hasErrors:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap,
                                          inputLayerList, errorDict,
                                          invalidated)
                return status
            else:
                status = self.translateDS(inputOgrDb, outputOgrDb, fieldMap,
                                          inputLayerList, errorDict)
                return status
        return False

    def convertToSpatialite(self, outputAbstractDb, type=None):
        return None

    def getDatabaseVersion(self):
        try:
            self.checkAndOpenDb()
        except:
            return None
        version = '2.1.3'
        try:
            sqlVersion = self.gen.getEDGVVersion()
            queryVersion = QSqlQuery(sqlVersion, self.db)
            while queryVersion.next():
                version = queryVersion.value(0)
        except:
            version = '2.1.3'
        return version

    def obtainLinkColumn(self, complexClass, aggregatedClass):
        try:
            self.checkAndOpenDb()
        except:
            return ''
        #query to obtain the link column between the complex and the feature layer
        sql = self.gen.getLinkColumn(complexClass.replace('complexos_', ''),
                                     aggregatedClass)
        query = QSqlQuery(sql, self.db)
        column_name = ""
        while query.next():
            column_name = query.value(0)
        return column_name

    def loadAssociatedFeatures(self, complex):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        associatedDict = dict()
        #query to get the possible links to the selected complex in the combobox
        complexName = complex.replace('complexos_', '')
        sql = self.gen.getComplexLinks(complexName)
        query = QSqlQuery(sql, self.db)
        while query.next():
            #setting the variables
            complex_schema = query.value(0)
            complex = query.value(1)
            aggregated_schema = query.value(2)
            aggregated_class = query.value(3)
            column_name = query.value(4)

            #query to obtain the created complexes
            sql = self.gen.getComplexData(complex_schema, complex)
            complexQuery = QSqlQuery(sql, self.db)
            while complexQuery.next():
                complex_uuid = complexQuery.value(0)
                name = complexQuery.value(1)

                if not (complex_uuid and name):
                    continue

                associatedDict = self.utils.buildNestedDict(
                    associatedDict, [name, complex_uuid, aggregated_class], [])

                #query to obtain the id of the associated feature
                sql = self.gen.getAssociatedFeaturesData(
                    aggregated_schema, aggregated_class, column_name,
                    complex_uuid)
                associatedQuery = QSqlQuery(sql, self.db)

                while associatedQuery.next():
                    ogc_fid = associatedQuery.value(0)
                    associatedDict = self.utils.buildNestedDict(
                        associatedDict, [name, complex_uuid, aggregated_class],
                        [ogc_fid])
        return associatedDict

    def isComplexClass(self, className):
        try:
            self.checkAndOpenDb()
        except:
            return False
        #getting all complex tables
        query = QSqlQuery(self.gen.getComplexTablesFromDatabase(), self.db)
        while query.next():
            if query.value(0) == 'complexos_' + className:
                return True
        return False

    def disassociateComplexFromComplex(self, aggregated_class, link_column,
                                       id):
        sql = self.gen.disassociateComplexFromComplex(
            'complexos_' + aggregated_class, link_column, id)
        query = QSqlQuery(self.db)
        if not query.exec_(sql):
            raise Exception(
                self.tr('Problem disassociating complex from complex: ') +
                '\n' + query.lastError().text())

    def getUsers(self):
        return None

    def getUserRelatedRoles(self, username):
        return None

    def getRoles(self):
        return None

    def createRole(self, role, dict):
        pass

    def dropRole(self, role):
        pass

    def alterUserPass(self, user, newpassword):
        pass

    def createUser(self, user, password, isSuperUser):
        pass

    def removeUser(self, user):
        pass

    def grantRole(self, user, role):
        pass

    def revokeRole(self, user, role):
        pass

    def getTablesFromDatabase(self):
        try:
            self.checkAndOpenDb()
        except:
            return []
        ret = []

        sql = self.gen.getTablesFromDatabase()
        query = QSqlQuery(sql, self.db)
        while query.next():
            #table name
            ret.append(query.value(0))
        return ret

    def getRolePrivileges(self, role, dbname):
        return None

    def getFrameLayerName(self):
        return 'public_aux_moldura_a'

    def getEDGVDbsFromServer(self, name):
        return None

    def getDbsFromServer(self):
        return None

    def checkSuperUser(self):
        return None

    def dropDatabase(self, abstractCandidate):
        return None

    def createResolvedDomainViews(self, createViewClause, fromClause):
        pass

    def getSqlViewFile(self):
        pass
class CreateInomDialog(QtGui.QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(CreateInomDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        self.iface = iface
        #Sql factory generator
        self.isSpatialite = True
        self.tabWidget.setCurrentIndex(0)
        self.factory = SqlGeneratorFactory()
        self.gen = self.factory.createSqlGenerator(self.isSpatialite)

        QObject.connect(self.tabWidget, SIGNAL(("currentChanged(int)")), self.restoreInitialState)
        QObject.connect(self.pushButtonOpenFile, SIGNAL(("clicked()")), self.loadDatabase)

        self.restoreInitialState()

        self.db = None
        #populating the postgis combobox
        self.populatePostGISConnectionsCombo()

        self.map_index = UtmGrid()

        self.disableAll()

        self.setValidCharacters()

        self.setMask()

    def __del__(self):
        self.closeDatabase()

    @pyqtSlot()
    def on_okButton_clicked(self):
        if not self.dbLoaded:
            QMessageBox.warning(self, self.tr("Warning!"), self.tr('Please, select a database first.'))
            return

        if not self.validateMI():
            QMessageBox.warning(self, self.tr("Warning!"), self.tr('Map name index not valid!'))
            return
        frame = self.map_index.getQgsPolygonFrame(self.inomLineEdit.text())
        reprojected = self.reprojectFrame(frame)
        self.insertFrameIntoLayer(reprojected)
        self.done(1)

    def insertFrameIntoLayer(self,reprojected):
        self.utils = Utils()
        self.dbVersion = self.utils.getDatabaseVersion(self.db)
        self.qmlPath = self.utils.getQmlDir(self.db)

        layer = self.getFrameLayer()
        if not layer:
            return

        layer.startEditing()
        feat = QgsFeature()
        feat.setFields(layer.dataProvider().fields())
        feat.setGeometry(reprojected)
        feat.setAttribute(2, self.inomLineEdit.text())
        feat.setAttribute(3, self.scaleCombo.currentText())
        layer.addFeatures([feat], makeSelected=True)
        layer.commitChanges()

        bbox = reprojected.boundingBox()
        for feature in layer.getFeatures():
            bbox.combineExtentWith(feature.geometry().boundingBox())

        bbox = self.iface.mapCanvas().mapSettings().layerToMapCoordinates(layer, bbox)
        self.iface.mapCanvas().setExtent(bbox)
        self.iface.mapCanvas().refresh()

    def getFrameLayer(self):
        for lyr in self.iface.legendInterface().layers():
            if lyr.name() == 'public_aux_moldura_a' or lyr.name() == 'aux_moldura_a':
                dbname = self.getDBNameFromLayer(lyr)
                if self.isSpatialite and dbname == self.filename:
                    return lyr
                if not self.isSpatialite:
                    (database, host, port, user, password) = self.utils.getPostGISConnectionParameters(self.comboBoxPostgis.currentText())
                    if dbname == database:
                        return lyr

        if self.isSpatialite:
            return self.loadSpatialiteFrame()
        else:
            return self.loadPostGISFrame()

        return None

    def getDBNameFromLayer(self, lyr):
        dbname = None
        splitUri = lyr.dataProvider().dataSourceUri().split(' ')
        if len(splitUri) > 0:
            dbsplit = splitUri[0].split('=')
            if len(dbsplit) > 1 and dbsplit[0] == 'dbname':
                dbnameInString = dbsplit[1]
                dbnameSplit = dbnameInString.split('\'')
                if len(dbnameSplit) > 1:
                    dbname = dbnameSplit[1]
        return dbname

    def loadPostGISFrame(self):
        self.selectedClasses = ['public.aux_moldura_a']
        (database, host, port, user, password) = self.utils.getPostGISConnectionParameters(self.comboBoxPostgis.currentText())
        uri = QgsDataSourceURI()
        uri.setConnection(str(host),str(port), str(database), str(user), str(password))
        if len(self.selectedClasses)>0:
            try:
                geom_column = 'geom'
                for layer in self.selectedClasses:
                    split = layer.split('.')
                    schema = split[0]
                    layerName = split[1]
                    sql = self.gen.loadLayerFromDatabase(layer)
                    uri.setDataSource(schema, layerName, geom_column, sql,'id')
                    uri.disableSelectAtId(True)
                    return self.loadEDGVLayer(uri, layerName, 'postgres')
            except:
                self.bar.pushMessage(self.tr("Error!"), self.tr("Could not load the selected frame!"), level=QgsMessageBar.CRITICAL)
        else:
            self.bar.pushMessage(self.tr("Warning!"), self.tr("Please, select at least one class!"), level=QgsMessageBar.WARNING)

    def loadSpatialiteFrame(self):
        self.selectedClasses = ['public_aux_moldura_a']
        uri = QgsDataSourceURI()
        uri.setDatabase(self.filename)
        schema = ''
        geom_column = 'GEOMETRY'
        if len(self.selectedClasses)>0:
            for layer_name in self.selectedClasses:
                uri.setDataSource(schema, layer_name, geom_column)
                return self.loadEDGVLayer(uri, layer_name, 'spatialite')

    def loadEDGVLayer(self, uri, layer_name, provider):
        vlayer = QgsVectorLayer(uri.uri(), layer_name, provider)
        vlayer.setCrs(self.crs)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer) #added due to api changes
        if self.isSpatialite and (self.dbVersion == '3.0' or self.dbVersion == '2.1.3'):
            lyr = '_'.join(layer_name.replace('\r','').split('_')[1::])
        else:
            lyr = layer_name.replace('\r','')
        vlayerQml = os.path.join(self.qmlPath, lyr+'.qml')
        vlayer.loadNamedStyle(vlayerQml,False)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer)
        if not vlayer.isValid():
            QgsMessageLog.logMessage(vlayer.error().summary(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            return None
        return vlayer

    @pyqtSlot()
    def on_cancelButton_clicked(self):
        self.done(0)

    @pyqtSlot(int)
    def on_comboBoxPostgis_currentIndexChanged(self):
        if self.comboBoxPostgis.currentIndex() > 0:
            self.loadDatabase()

    @pyqtSlot(str)
    def on_miLineEdit_textChanged(self,s):
        if (s!=''):
            self.inomen=self.map_index.getINomenFromMI(str(s))
            self.inomLineEdit.setText(self.inomen)

    @pyqtSlot(str)
    def on_mirLineEdit_textChanged(self,s):
        if (s!=''):
            self.inomen=self.map_index.getINomenFromMIR(str(s))
            self.inomLineEdit.setText(self.inomen)

    def reprojectFrame(self, poly):
        crsSrc = QgsCoordinateReferenceSystem(self.crs.geographicCRSAuthId())
        coordinateTransformer = QgsCoordinateTransform(crsSrc, self.crs)
        polyline = poly.asMultiPolygon()[0][0]
        newPolyline = []
        for point in polyline:
            newPolyline.append(coordinateTransformer.transform(point))
        qgsPolygon = QgsGeometry.fromMultiPolygon([[newPolyline]])
        return qgsPolygon

    def closeDatabase(self):
        if self.db:
            self.db.close()
            self.db = None

    def restoreInitialState(self):
        self.filename = ""
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.postGISCrsEdit.setText('')
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setText('')
        self.spatialiteCrsEdit.setReadOnly(True)

        if self.tabWidget.currentIndex() == 0:
            self.isSpatialite = True
        else:
            self.isSpatialite = False

        #getting the sql generator according to the database type
        self.gen = self.factory.createSqlGenerator(self.isSpatialite)
        self.comboBoxPostgis.setCurrentIndex(0)

    def setCRS(self):
        try:
            self.epsg = self.findEPSG()
            print self.epsg
            if self.epsg == -1:
                self.bar.pushMessage("", self.tr("Coordinate Reference System not set or invalid!"), level=QgsMessageBar.WARNING)
            else:
                self.crs = QgsCoordinateReferenceSystem(self.epsg, QgsCoordinateReferenceSystem.EpsgCrsId)
                if self.isSpatialite:
                    self.spatialiteCrsEdit.setText(self.crs.description())
                    self.spatialiteCrsEdit.setReadOnly(True)
                else:
                    self.postGISCrsEdit.setText(self.crs.description())
                    self.postGISCrsEdit.setReadOnly(True)
        except:
            pass

    def loadDatabase(self):
        self.closeDatabase()
        if self.isSpatialite:
            fd = QtGui.QFileDialog()
            self.filename = fd.getOpenFileName(filter='*.sqlite')
            if self.filename:
                self.spatialiteFileEdit.setText(self.filename)
                self.db = QSqlDatabase("QSQLITE")
                self.db.setDatabaseName(self.filename)
        else:
            self.db = QSqlDatabase("QPSQL")
            (database, host, port, user, password) = self.getPostGISConnectionParameters(self.comboBoxPostgis.currentText())
            self.db.setDatabaseName(database)
            self.db.setHostName(host)
            self.db.setPort(int(port))
            self.db.setUserName(user)
            self.db.setPassword(password)
        try:
            if not self.db.open():
                print self.db.lastError().text()
            else:
                self.dbLoaded = True
                self.setCRS()
        except:
            pass

    def getPostGISConnectionParameters(self, name):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections/'+name)
        database = settings.value('database')
        host = settings.value('host')
        port = settings.value('port')
        user = settings.value('username')
        password = settings.value('password')
        settings.endGroup()
        return (database, host, port, user, password)

    def getPostGISConnections(self):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections')
        currentConnections = settings.childGroups()
        settings.endGroup()
        return currentConnections

    def populatePostGISConnectionsCombo(self):
        self.comboBoxPostgis.clear()
        self.comboBoxPostgis.addItem(self.tr("Select Database"))
        self.comboBoxPostgis.addItems(self.getPostGISConnections())

    def findEPSG(self):
        sql = self.gen.getSrid()
        query = QSqlQuery(sql, self.db)
        srids = []
        while query.next():
            srids.append(query.value(0))
        return srids[0]

    def setValidCharacters(self):
        self.chars = []

        chars = 'NS'
        self.chars.append(chars)
        chars = 'ABCDEFGHIJKLMNOPQRSTUVZ'
        self.chars.append(chars)
        chars = ['01','02','03','04','05','06','07','08','09','10',
                   '11','12','13','14','15','16','17','18','19','20',
                   '21','22','23','24','25','26','27','28','29','30',
                   '31','32','33','34','35','36','37','38','39','40',
                   '41','42','43','44','45','46','47','48','49','50',
                   '51','52','53','54','55','56','57','58','59','60']
        self.chars.append(chars)
        chars = 'VXYZ'
        self.chars.append(chars)
        chars = 'ABCD'
        self.chars.append(chars)
        chars = ['I','II','III','IV','V','VI']
        self.chars.append(chars)
        chars = '1234'
        self.chars.append(chars)
        chars = ['NO','NE','SO','SE']
        self.chars.append(chars)
        chars = 'ABCDEF'
        self.chars.append(chars)
        chars = ['I','II','III','IV']
        self.chars.append(chars)
        chars = '123456'
        self.chars.append(chars)
        chars = 'ABCD'
        self.chars.append(chars)

    def setMask(self):
        if self.scaleCombo.currentText() == '1000k':
            self.inomLineEdit.setInputMask('NN-NN')
        elif self.scaleCombo.currentText() == '500k':
            self.inomLineEdit.setInputMask('NN-NN-N')
        elif self.scaleCombo.currentText() == '250k':
            self.inomLineEdit.setInputMask('NN-NN-N-N')
        elif self.scaleCombo.currentText() == '100k':
            self.inomLineEdit.setInputMask('NN-NN-N-N-Nnn')
        elif self.scaleCombo.currentText() == '50k':
            self.inomLineEdit.setInputMask('NN-NN-N-N-Nnn-0')
        elif self.scaleCombo.currentText() == '25k':
            self.inomLineEdit.setInputMask('NN-NN-N-N-Nnn-0-NN')
        elif self.scaleCombo.currentText() == '10k':
            self.inomLineEdit.setInputMask('NN-NN-N-N-Nnn-0-NN-N')
        elif self.scaleCombo.currentText() == '5k':
            self.inomLineEdit.setInputMask('NN-NN-N-N-Nnn-0-NN-N-Nnn')
        elif self.scaleCombo.currentText() == '2k':
            self.inomLineEdit.setInputMask('NN-NN-N-N-Nnn-0-NN-N-Nnn-0')
        elif self.scaleCombo.currentText() == '1k':
            self.inomLineEdit.setInputMask('NN-NN-N-N-Nnn-0-NN-N-Nnn-0-N')

    def validateMI(self):
        mi = self.inomLineEdit.text()
        split = mi.split('-')
        for i in range(len(split)):
            word = str(split[i])
            if len(word) == 0:
                return False
            if i == 0:
                if word[0] not in self.chars[0]:
                    print word
                    return False
                if word[1] not in self.chars[1]:
                    print word
                    return False
            elif i == 1:
                if word not in self.chars[2]:
                    print word
                    return False
            elif i == 2:
                if word not in self.chars[3]:
                    print word
                    return False
            elif i == 3:
                if word not in self.chars[4]:
                    print word
                    return False
            elif i == 4:
                if word not in self.chars[5]:
                    print word
                    return False
            elif i == 5:
                if word not in self.chars[6]:
                    print word
                    return False
            elif i == 6:
                if word not in self.chars[7]:
                    print word
                    return False
            elif i == 7:
                if word not in self.chars[8]:
                    print word
                    return False
            elif i == 8:
                if word not in self.chars[9]:
                    print word
                    return False
            elif i == 9:
                if word not in self.chars[10]:
                    print word
                    return False
            elif i == 10:
                if word not in self.chars[11]:
                    print word
                    return False
        return True

    def disableAll(self):
        self.mirLineEdit.setEnabled(False)
        self.miLineEdit.setEnabled(False)
        self.inomLineEdit.setEnabled(False)

    @pyqtSlot(int)
    def on_scaleCombo_currentIndexChanged(self):
        self.setMask()

    @pyqtSlot(bool)
    def on_mirRadioButton_toggled(self, toggled):
        if toggled:
            self.mirLineEdit.setEnabled(True)
        else:
            self.mirLineEdit.setEnabled(False)

    @pyqtSlot(bool)
    def on_miRadioButton_toggled(self, toggled):
        if toggled:
            self.miLineEdit.setEnabled(True)
        else:
            self.miLineEdit.setEnabled(False)

    @pyqtSlot(bool)
    def on_inomRadioButton_toggled(self, toggled):
        if toggled:
            self.inomLineEdit.setEnabled(True)
        else:
            self.inomLineEdit.setEnabled(False)