예제 #1
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'
     }
예제 #2
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.dbFactory = DbFactory()
예제 #3
0
 def __init__(self, parent=None):
     super(ConnectionComboBox, self).__init__(parent)
     self.parent = parent
     self.abstractDb = None
     self.abstractDbFactory = DbFactory()
     self.serverAbstractDb = None
     self.displayDict = {'2.1.3':'EDGV 2.1.3', 'FTer_2a_Ed':'EDGV FTer 2a Ed', 'Non_EDGV':self.tr('Other database model')}
     self.lineEdit().setPlaceholderText(self.tr('Select a database'))
     self.currentIndexChanged.connect(self.loadDatabase)
     self.instantiateAbstractDb = False
예제 #4
0
 def instantiateAdminDb(self, serverAbstractDb):
     """
     Instantiates dsgtools_admindb in the same server as serverAbstractDb. 
     If dsgtools_admindb does not exists, instantiateAdminDb calls createAdminDb
     """
     (host, port, user, password) = serverAbstractDb.getParamsFromConectedDb()
     adminDb = DbFactory().createDbFactory('QPSQL')
     if not serverAbstractDb.hasAdminDb():
         return self.createAdminDb(serverAbstractDb, adminDb, host, port, user, password)
     adminDb.connectDatabaseWithParameters(host, port, 'dsgtools_admindb', user, password)
     return adminDb
예제 #5
0
 def instantiateAbstractDb(self, dbName):
     """
     Instantiates an abstractDb.
     """
     if dbName not in self.dbDict.keys():
         (host, port, user, password) = self.serverAbstractDb.getParamsFromConectedDb()
         abstractDb = DbFactory().createDbFactory('QPSQL')
         abstractDb.connectDatabaseWithParameters(host, port, dbName, user, password)
     else:
         abstractDb = self.dbDict[dbName]
     return abstractDb
예제 #6
0
 def __init__(self, iface, parent=None):
     '''Constructor.'''
     super(ViewServers, 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
     self.abstractDbFactory = DbFactory()
     self.initGui()
예제 #7
0
    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
예제 #8
0
 def __init__(self, iface, parent=None):
     """
     Constructor
     """
     super(StyleManagerTool, self).__init__(parent)
     self.setupUi(self)
     self.iface = iface
     self.splitter.hide()
     self.refreshDb()
     self.dbFactory = DbFactory()
     self.applyPushButton.setEnabled(False)
     self.utils = Utils()
예제 #9
0
    def __init__(self, parent=None):
        """
        Constructor
        """
        super(CreateProfile, 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.folder = os.path.join(os.path.dirname(__file__), 'profiles')

        self.abstractDb = None
        self.abstractDbFactory = DbFactory()

        self.populateTreeDict()
예제 #10
0
 def __init__(self, createParam, parentWidget = None):
     super(DbCreator,self).__init__()
     self.dbFactory = DbFactory()
     self.parentWidget = parentWidget
     if isinstance(createParam, unicode):
         self.outputDir = createParam
     if isinstance(createParam, AbstractDb):
         self.abstractDb = createParam
     self.scaleMIDict = {1:'100k',2:'50k',3:'25k',4:'10k',5:'5k',6:'2k',7:'1k'}
예제 #11
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.iface = iface
        
        self.dbButton.clicked.connect(self.getDataSources)
        self.dbCombo.activated.connect(self.updateComplexClass)
        self.complexCombo.activated.connect(self.loadAssociatedFeatures)
        self.iface.newProjectCreated.connect(self.clearDock)

        self.abstractDb = None
        self.databases = None
        self.abstractDbFactory = DbFactory()
예제 #12
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.dbFactory = DbFactory()
     self.localDb = None
     self.serverWidget.populateServersCombo()
     #signal connections
     self.serverWidget.abstractDbLoaded.connect(self.checkSuperUser)
     self.serverWidget.clearWidgets.connect(self.clearAll)
     self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
     self.treeWidget.customContextMenuRequested.connect(
         self.createMenuAssigned)
예제 #13
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.dbFactory = DbFactory()
예제 #14
0
    def setInitialState(self):
        self.filename = ''
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        
        self.abstractDb = None
        self.isSpatialite = True
        self.tabWidget.setCurrentIndex(0)
        self.abstractDbFactory = DbFactory()
        self.utils = Utils()

        #populating the postgis combobox
        self.comboBoxPostgis.setCurrentIndex(0)
        self.populatePostGISConnectionsCombo()
        self.spatialiteFileEdit.setReadOnly(True)   
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setReadOnly(True)   
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setReadOnly(True)       
예제 #15
0
    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 __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
예제 #17
0
 def __init__(self, iface, parent = None):
     """
     Constructor
     """
     super(StyleManagerTool, self).__init__(parent)
     self.setupUi(self)
     self.iface = iface
     self.splitter.hide()
     self.refreshDb()
     self.dbFactory = DbFactory()
     self.applyPushButton.setEnabled(False)
     self.utils = Utils()
예제 #18
0
    def clearAll(self):
        """
        Resets the initial state
        """
        self.filename = ''
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None

        self.abstractDb = None
        self.isSpatialite = False
        self.abstractDbFactory = DbFactory()
        self.utils = Utils()

        #populating the postgis combobox
        self.comboBoxPostgis.clear()
        self.spatialiteFileEdit.setReadOnly(True)
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setReadOnly(True)
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setReadOnly(True)
예제 #19
0
    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
예제 #20
0
    def __init__(self, parent = None):
        """Constructor."""
        super(CreateProfile, 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.folder = os.path.join(os.path.dirname(__file__), 'profiles')

        self.abstractDb = None
        self.abstractDbFactory = DbFactory()

        self.populateTreeDict()
    def __init__(self, permissionManager, abstractDb, parent=None):
        """
        Constructor
        """
        super(CreateProfileWithProfileManager, 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.permissionManager = permissionManager
        self.abstractDb = abstractDb
        self.abstractDbFactory = DbFactory()

        self.populateTreeDict()
예제 #22
0
    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
예제 #23
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.iface = iface
        
        self.dbButton.clicked.connect(self.getDataSources)
        self.dbCombo.activated.connect(self.updateComplexClass)
        self.complexCombo.activated.connect(self.loadAssociatedFeatures)
        self.iface.newProjectCreated.connect(self.clearDock)

        self.abstractDb = None
        self.databases = None
        self.abstractDbFactory = DbFactory()
예제 #24
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':[], '3.0':[]}
     self.correspondenceDict = {self.tr('Load Database Model EDGV Version 2.1.3'):'2.1.3', self.tr('Load Database Model EDGV Version 3.0'):'3.0', self.tr('Load Database Model EDGV Version FTer_2a_Ed'):'FTer_2a_Ed',self.tr('Load Other Database Models'):'Non_EDGV'}
 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 3.0'):'3.0', 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':[], '3.0':[]}
     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
예제 #26
0
    def clearAll(self):
        """
        Resets the initial state
        """
        self.filename = ''
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        
        self.abstractDb = None
        self.isSpatialite = False
        self.abstractDbFactory = DbFactory()
        self.utils = Utils()

        #populating the postgis combobox
        self.comboBoxPostgis.clear()
        self.spatialiteFileEdit.setReadOnly(True)   
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setReadOnly(True)   
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setReadOnly(True)      
예제 #27
0
class ExploreServerWidget(QtGui.QWidget, FORM_CLASS):
    abstractDbLoaded = pyqtSignal()
    clearWidgets = pyqtSignal()
    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.dbFactory = DbFactory()

    #TODO
    def getServers(self):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers')
        currentConnections = settings.childGroups()
        settings.endGroup()
        return currentConnections
    
    #TODO
    def browseServer(self,dbList,host,port,user,password):
        gen = self.factory.createSqlGenerator(False)
        edvgDbList = []
        for database in dbList:
            db = self.getPostGISDatabaseWithParams(database, host, port, user, password)
            if not db.open():
                qgis.utils.iface.messageBar().pushMessage('DB :'+database+'| msg: '+db.lastError().databaseText(), level=QgsMessageBar.CRITICAL)

            query = QSqlQuery(db)
            if query.exec_(gen.getEDGVVersion()):
                while query.next():
                    version = query.value(0)
                    if version:
                        edvgDbList.append((database, version))
        return edvgDbList
    
    #TODO
    def getDbsFromServer(self,name):
        gen = self.factory.createSqlGenerator(False)
        
        (host, port, user, password) = self.getServerConfiguration(name)
        database = 'postgres'
        
        db = self.getPostGISDatabaseWithParams(database, host, port, user, password)
        if not db.open():
            QgsMessageLog.logMessage(db.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
        
        query = QSqlQuery(gen.getDatabasesFromServer(), db)
        dbList = []
        while query.next():
            dbList.append(query.value(0))
        return self.browseServer(dbList, host, port, user, password)
    
    @pyqtSlot(bool)
    def on_createNewServerPushButton_clicked(self):  
        createNewServer = ViewServers(self)
        createNewServer.exec_()
        self.populateServersCombo()

    def populateServersCombo(self):
        self.serversCombo.clear()
        self.serversCombo.addItem(self.tr('Select Server'))
        currentConnections = self.getServers()
        for connection in currentConnections:
            self.serversCombo.addItem(connection)
    
    @pyqtSlot(int)
    def on_serversCombo_currentIndexChanged(self):
        self.clearWidgets.emit()
        if self.serversCombo.currentIndex() != 0:
            self.abstractDb = self.dbFactory.createDbFactory('QPSQL')
            (host, port, user, password) = self.abstractDb.getServerConfiguration(self.serversCombo.currentText())
            self.abstractDb.connectDatabaseWithParameters(host, port, 'postgres', user, password)
            self.abstractDbLoaded.emit()
예제 #28
0
class StyleManagerTool(QWidget, FORM_CLASS): 
    def __init__(self, iface, parent = None):
        """
        Constructor
        """
        super(StyleManagerTool, self).__init__(parent)
        self.setupUi(self)
        self.iface = iface
        self.splitter.hide()
        self.refreshDb()
        self.dbFactory = DbFactory()
        self.applyPushButton.setEnabled(False)
        self.utils = Utils()
        
    @pyqtSlot(bool)
    def on_layerPushButton_toggled(self, toggled):
        """
        Shows/Hides the tool bar
        """
        if toggled:
            self.refreshDb()
            self.splitter.show()
        else:
            self.splitter.hide()
    
    @pyqtSlot(bool, name = 'on_refreshPushButton_clicked')
    def refreshDb(self):
        self.dbComboBox.clear()
        self.dbComboBox.addItem(self.tr('Select Database'))
        #populate database list
        for dbName in self.getDatabaseList():
            self.dbComboBox.addItem(dbName)
    
    @pyqtSlot(int, name = 'on_styleComboBox_currentIndexChanged')
    def enableApply(self):
        dbIdx = self.dbComboBox.currentIndex()
        stylesIdx = self.styleComboBox.currentIndex()
        if dbIdx > 0 and stylesIdx > 0:
            self.applyPushButton.setEnabled(True)
        else:
            self.applyPushButton.setEnabled(False)

    @pyqtSlot(bool)
    def on_applyPushButton_clicked(self):
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            dbName = self.dbComboBox.currentText()
            styleName = self.styleComboBox.currentText()
            lyrList = self.getLayers(dbName)
            abstractDb = self.getAbstractDb(dbName)
            dbVersion = abstractDb.getDatabaseVersion()
            stylesDict = abstractDb.getStyleDict(dbVersion)
            selectedStyle = stylesDict[styleName]
            localProgress = ProgressWidget(1, len(lyrList) - 1, self.tr('Loading style {0}').format(styleName), parent=self.iface.mapCanvas())
            for lyr in lyrList:
                try:
                    uri = QgsDataSourceURI(lyr.dataProvider().dataSourceUri())
                    fullPath = self.getStyle(abstractDb, selectedStyle, lyr.name())
                    if fullPath:
                        lyr.applyNamedStyle(fullPath)
                except:
                    pass
                localProgress.step()
            self.iface.mapCanvas().refreshAllLayers()
            QApplication.restoreOverrideCursor()
        except Exception as e:
            QgsMessageLog.logMessage(self.tr('Error setting style ') + styleName + ': ' +':'.join(e.args), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            QApplication.restoreOverrideCursor()

    
    def getLayers(self, dbName):
        lyrList = []
        for lyr in self.iface.legendInterface().layers():
            if isinstance(lyr, QgsVectorLayer):
                candidateUri = QgsDataSourceURI(lyr.dataProvider().dataSourceUri())
                if candidateUri.database() == dbName and lyr.providerType() in ['postgres', 'spatialite']:
                    lyrList.append(lyr)
        return lyrList
    
    def getDatabaseList(self):
        dbList = []
        for lyr in self.iface.legendInterface().layers():
            if isinstance(lyr, QgsVectorLayer):
                candidateUri = QgsDataSourceURI(lyr.dataProvider().dataSourceUri())
                dbName = candidateUri.database()
                if dbName not in dbList and lyr.providerType() in ['postgres', 'spatialite']:
                    dbList.append(dbName)
        return dbList
    
    def loadStylesCombo(self, abstractDb):
        dbVersion = abstractDb.getDatabaseVersion()
        styleDict = abstractDb.getStyleDict(dbVersion)
        self.styleComboBox.clear()
        styleList = styleDict.keys()
        numberOfStyles = len(styleList)
        if numberOfStyles > 0:
            self.styleComboBox.addItem(self.tr('Select Style'))
            for i in range(numberOfStyles):
                self.styleComboBox.addItem(styleList[i])
        else:
            self.styleComboBox.addItem(self.tr('No available styles'))
    
    def getParametersFromLyr(self, dbName):
        for lyr in self.iface.legendInterface().layers():
          if isinstance(lyr, QgsVectorLayer):
            candidateUri = QgsDataSourceURI(lyr.dataProvider().dataSourceUri())
            if candidateUri.database() == dbName:
                currLyr = lyr
                break
        dbParameters = dict()
        if currLyr.providerType() == 'postgres':
            dbParameters['host'] = candidateUri.host()
            dbParameters['port'] = candidateUri.port()
            dbParameters['user'] = candidateUri.username()
            dbParameters['password'] = candidateUri.password()
            return dbParameters, 'QPSQL'
        if currLyr.providerType() == 'spatialite':
            dbParameters['dbPath'] = candidateUri.database()
            return dbParameters, 'QSQLITE'
        else:
            raise Exception(self.tr('Feature only implemented for PostGIS and Spatialite'))
    
    def getAbstractDb(self, dbName):
        dbParameters, driverName = self.getParametersFromLyr(dbName)
        abstractDb = self.dbFactory.createDbFactory(driverName)
        if 'host' in dbParameters.keys():
            abstractDb.connectDatabaseWithParameters(dbParameters['host'], dbParameters['port'], dbName, dbParameters['user'], dbParameters['password'])
        else:
            abstractDb.connectDatabase(dbParameters['dbPath'])
        return abstractDb

    @pyqtSlot(int)
    def on_dbComboBox_currentIndexChanged(self, idx):
        if idx <= 0:
            self.styleComboBox.clear()
            self.styleComboBox.addItem(self.tr('Select Style'))
            self.styleComboBox.setEnabled(False)
        elif idx > 0:
            self.styleComboBox.setEnabled(True)
            dbName = self.dbComboBox.currentText()
            abstractDb = self.getAbstractDb(dbName)
            self.loadStylesCombo(abstractDb)
        self.enableApply()
        
    def getStyle(self, abstractDb, stylePath, className):
        if 'db:' in stylePath:
            return abstractDb.getStyle(stylePath.split(':')[-1], className)
        else:
            return self.getStyleFromFile(stylePath, className)
    
    def getStyleFromFile(self, stylePath, className):
        availableStyles = os.walk(stylePath).next()[2]
        styleName = className+'.qml'
        if styleName in availableStyles:
            path = os.path.join(stylePath, styleName)
            qml = self.utils.parseStyle(path)
            return qml
        else:
            return None
예제 #29
0
class ConnectionWidget(QtGui.QWidget, FORM_CLASS):
    connectionChanged = pyqtSignal()
    problemOccurred = pyqtSignal(str)
    dbChanged = pyqtSignal(AbstractDb)
    styleChanged = pyqtSignal(dict)

    def __init__(self, parent=None):
        """Constructor."""
        super(ConnectionWidget, 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.setInitialState()
        self.serverWidget.populateServersCombo()
        self.serverWidget.abstractDbLoaded.connect(self.getDatabasesFromServer)
        self.serverWidget.clearWidgets.connect(self.clearAll)

    def __del__(self):
        """
        Closes the database
        """
        self.closeDatabase()

    def closeDatabase(self):
        """
        Closes the current database
        """
        if self.abstractDb:
            del self.abstractDb
            self.abstractDb = None

    def clearAll(self):
        """
        Resets the initial state
        """
        self.filename = ''
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None

        self.abstractDb = None
        self.isSpatialite = False
        self.abstractDbFactory = DbFactory()
        self.utils = Utils()

        #populating the postgis combobox
        self.comboBoxPostgis.clear()
        self.spatialiteFileEdit.setReadOnly(True)
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setReadOnly(True)
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setReadOnly(True)

    def setInitialState(self):
        """
        Sets the initial state
        """
        self.filename = ''
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None

        self.abstractDb = None
        self.isSpatialite = False
        self.tabWidget.setCurrentIndex(0)
        self.abstractDbFactory = DbFactory()
        self.utils = Utils()
        self.serverWidget.serversCombo.setCurrentIndex(0)

        #populating the postgis combobox
        self.comboBoxPostgis.clear()
        self.spatialiteFileEdit.setReadOnly(True)
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setReadOnly(True)
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setReadOnly(True)

    @pyqtSlot(int)
    def on_comboBoxPostgis_currentIndexChanged(self):
        """
        Updates database information when the combo box changes
        """
        if self.comboBoxPostgis.currentIndex() > 0:
            self.postGISCrsEdit.setText('')
            self.postGISCrsEdit.setReadOnly(True)
            self.edgvPostgisVersionEdit.setText('')
            self.edgvPostgisVersionEdit.setReadOnly(True)
            self.loadDatabase()
            self.connectionChanged.emit()

    @pyqtSlot(bool)
    def on_pushButtonOpenFile_clicked(self):
        """
        Loads a spatialite database
        """
        self.loadDatabase()
        if self.isDBConnected():
            self.connectionChanged.emit()

    @pyqtSlot(int)
    def on_tabWidget_currentChanged(self):
        """
        Changes the tab to work with spatialite or postgis databases
        """
        self.filename = ''
        self.comboBoxPostgis.clear()
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.dbVersion = ''
        self.serverWidget.serversCombo.setCurrentIndex(0)
        self.spatialiteFileEdit.setReadOnly(True)
        self.spatialiteFileEdit.setText(self.filename)
        self.postGISCrsEdit.setText('')
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setText('')
        self.spatialiteCrsEdit.setReadOnly(True)
        self.edgvSpatialiteVersionEdit.setText('')
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setText('')
        self.edgvPostgisVersionEdit.setReadOnly(True)
        self.mGroupBox.setTitle(self.tr('Database connection'))

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

    def loadDatabase(self):
        """
        Loads the selected database
        """
        self.closeDatabase()
        try:
            if self.isSpatialite:
                self.abstractDb = self.abstractDbFactory.createDbFactory(
                    'QSQLITE')
                self.abstractDb.connectDatabase()
                self.spatialiteFileEdit.setText(
                    self.abstractDb.db.databaseName())
                self.edgvSpatialiteVersionEdit.setText(
                    self.abstractDb.getDatabaseVersion())

            else:
                self.abstractDb = self.abstractDbFactory.createDbFactory(
                    'QPSQL')
                (host, port, user,
                 password) = self.serverWidget.getServerParameters()
                dbName = self.comboBoxPostgis.currentText()
                self.abstractDb.connectDatabaseWithParameters(
                    host, port, dbName, user, password)
                self.edgvPostgisVersionEdit.setText(
                    self.abstractDb.getDatabaseVersion())
                serverName = self.serverWidget.serversCombo.currentText()
                newText = dbName + self.tr(' on ') + serverName
                self.mGroupBox.setToolTip(newText)
                # self.mGroupBox.setTitle(newText)

            self.abstractDb.checkAndOpenDb()
            self.dbLoaded = True
            self.dbVersion = self.abstractDb.getDatabaseVersion()
            self.abstractDb.checkAndCreateStyleTable()
            self.styles = self.abstractDb.getStyleDict(self.dbVersion)
            self.styleChanged.emit(self.styles)
            self.dbChanged.emit(self.abstractDb)
            if self.dbVersion == '-1':
                self.problemOccurred.emit(
                    self.tr('This is not a valid DsgTools database!'))
            else:
                self.setCRS()
        except Exception as e:
            self.problemOccurred.emit(
                self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin",
                                     QgsMessageLog.CRITICAL)

    def setCRS(self):
        """
        Sets the CRS information
        """
        try:
            self.epsg = self.abstractDb.findEPSG()
            if self.epsg == -1:
                self.problemOccurred.emit(
                    self.tr('Coordinate Reference System not set or invalid!'))
            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 Exception as e:
            self.problemOccurred.emit(
                self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin",
                                     QgsMessageLog.CRITICAL)

    def isDBConnected(self):
        """
        Checks if the database is already loaded
        """
        return self.dbLoaded

    def getDBVersion(self):
        """
        Gets the database version
        """
        ret = ''
        try:
            ret = self.abstractDb.getDatabaseVersion()
        except Exception as e:
            self.problemOccurred.emit(
                self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin",
                                     QgsMessageLog.CRITICAL)
        return ret

    def getQmlPath(self):
        """
        Gets the QML path
        """
        ret = ''
        try:
            ret = self.abstractDb.getQmlDir()
        except Exception as e:
            self.problemOccurred.emit(
                self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin",
                                     QgsMessageLog.CRITICAL)
        return ret

    def getDatabasesFromServer(self):
        """
        Gets databases from server
        """
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        try:
            if self.serverWidget.abstractDb:
                dbList = self.serverWidget.abstractDb.getEDGVDbsFromServer(
                    parentWidget=self)
                dbList.sort()
                self.comboBoxPostgis.clear()
                self.comboBoxPostgis.addItem(self.tr('Select Database'))
                for db, version in dbList:
                    self.comboBoxPostgis.addItem(db)

            else:
                self.setInitialState()
                return
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
            self.setInitialState()
            self.setInitialState()
        QApplication.restoreOverrideCursor()
예제 #30
0
class ConnectionWidget(QtGui.QWidget, FORM_CLASS):
    connectionChanged = pyqtSignal()
    problemOccurred = pyqtSignal(str)
    dbChanged = pyqtSignal(AbstractDb)
    styleChanged = pyqtSignal(dict)
    def __init__(self, parent = None):
        """Constructor."""
        super(ConnectionWidget, 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.setInitialState()
        self.serverWidget.populateServersCombo()
        self.serverWidget.abstractDbLoaded.connect(self.getDatabasesFromServer)
        self.serverWidget.clearWidgets.connect(self.clearAll)
        
         
    def __del__(self):
        """
        Closes the database
        """
        self.closeDatabase()

    def closeDatabase(self):
        """
        Closes the current database
        """
        if self.abstractDb:
            del self.abstractDb
            self.abstractDb = None
                 
    def clearAll(self):
        """
        Resets the initial state
        """
        self.filename = ''
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        
        self.abstractDb = None
        self.isSpatialite = False
        self.abstractDbFactory = DbFactory()
        self.utils = Utils()

        #populating the postgis combobox
        self.comboBoxPostgis.clear()
        self.spatialiteFileEdit.setReadOnly(True)   
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setReadOnly(True)   
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setReadOnly(True)      

    def setInitialState(self):
        """
        Sets the initial state
        """
        self.filename = ''
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        
        self.abstractDb = None
        self.isSpatialite = False
        self.tabWidget.setCurrentIndex(0)
        self.abstractDbFactory = DbFactory()
        self.utils = Utils()
        self.serverWidget.serversCombo.setCurrentIndex(0)

        #populating the postgis combobox
        self.comboBoxPostgis.clear()
        self.spatialiteFileEdit.setReadOnly(True)   
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setReadOnly(True)   
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setReadOnly(True)      

    @pyqtSlot(int)
    def on_comboBoxPostgis_currentIndexChanged(self):
        """
        Updates database information when the combo box changes
        """
        if self.comboBoxPostgis.currentIndex() > 0:
            self.postGISCrsEdit.setText('')
            self.postGISCrsEdit.setReadOnly(True)
            self.edgvPostgisVersionEdit.setText('')
            self.edgvPostgisVersionEdit.setReadOnly(True)  
            self.loadDatabase()
            self.connectionChanged.emit()
        
    @pyqtSlot(bool)
    def on_pushButtonOpenFile_clicked(self):  
        """
        Loads a spatialite database
        """
        self.loadDatabase()
        if self.isDBConnected():
            self.connectionChanged.emit()
        
    @pyqtSlot(int)
    def on_tabWidget_currentChanged(self):
        """
        Changes the tab to work with spatialite or postgis databases
        """
        self.filename = ''
        self.comboBoxPostgis.clear()
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.dbVersion = ''
        self.serverWidget.serversCombo.setCurrentIndex(0)
        self.spatialiteFileEdit.setReadOnly(True)
        self.spatialiteFileEdit.setText(self.filename)
        self.postGISCrsEdit.setText('')
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setText('')
        self.spatialiteCrsEdit.setReadOnly(True)   
        self.edgvSpatialiteVersionEdit.setText('')
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setText('')
        self.edgvPostgisVersionEdit.setReadOnly(True)
        self.mGroupBox.setTitle(self.tr('Database connection'))
        
        #Setting the database type
        if self.tabWidget.currentIndex() == 1:
            self.isSpatialite = True
        else:
            self.isSpatialite = False

    def loadDatabase(self):
        """
        Loads the selected database
        """
        self.closeDatabase()
        try:
            if self.isSpatialite:
                self.abstractDb = self.abstractDbFactory.createDbFactory('QSQLITE')
                self.abstractDb.connectDatabase()
                self.spatialiteFileEdit.setText(self.abstractDb.db.databaseName())
                self.edgvSpatialiteVersionEdit.setText(self.abstractDb.getDatabaseVersion())
                    
            else:
                self.abstractDb = self.abstractDbFactory.createDbFactory('QPSQL')
                (host, port, user, password) = self.serverWidget.getServerParameters()
                dbName = self.comboBoxPostgis.currentText()
                self.abstractDb.connectDatabaseWithParameters(host, port, dbName, user, password)
                self.edgvPostgisVersionEdit.setText(self.abstractDb.getDatabaseVersion())
                serverName = self.serverWidget.serversCombo.currentText()
                newText = dbName + self.tr(' on ') + serverName 
                self.mGroupBox.setToolTip(newText)
                # self.mGroupBox.setTitle(newText)

            self.abstractDb.checkAndOpenDb()
            self.dbLoaded = True
            self.dbVersion = self.abstractDb.getDatabaseVersion()
            self.abstractDb.checkAndCreateStyleTable()
            self.styles = self.abstractDb.getStyleDict(self.dbVersion)
            self.styleChanged.emit(self.styles)
            self.dbChanged.emit(self.abstractDb)
            if self.dbVersion == '-1':
                self.problemOccurred.emit(self.tr('This is not a valid DsgTools database!'))
            else:
                self.setCRS()
        except Exception as e:
            self.problemOccurred.emit(self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin", QgsMessageLog.CRITICAL)   

    def setCRS(self):
        """
        Sets the CRS information
        """
        try:
            self.epsg = self.abstractDb.findEPSG()
            if self.epsg == -1:
                self.problemOccurred.emit(self.tr('Coordinate Reference System not set or invalid!'))
            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 Exception as e:
            self.problemOccurred.emit(self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin", QgsMessageLog.CRITICAL)

        
    def isDBConnected(self):
        """
        Checks if the database is already loaded
        """
        return self.dbLoaded
        
    def getDBVersion(self):
        """
        Gets the database version
        """
        ret = ''
        try:
            ret = self.abstractDb.getDatabaseVersion()
        except Exception as e:
            self.problemOccurred.emit(self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
        return ret
    
    def getQmlPath(self):
        """
        Gets the QML path
        """
        ret = ''
        try:
            ret = self.abstractDb.getQmlDir()
        except Exception as e:
            self.problemOccurred.emit(self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
        return ret
    
    def getDatabasesFromServer(self):
        """
        Gets databases from server
        """  
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        try:
            if self.serverWidget.abstractDb:
                dbList = self.serverWidget.abstractDb.getEDGVDbsFromServer(parentWidget = self)
                dbList.sort()
                self.comboBoxPostgis.clear()
                self.comboBoxPostgis.addItem(self.tr('Select Database'))
                for db, version in dbList:
                    self.comboBoxPostgis.addItem(db)
                
            else:
                self.setInitialState()
                return
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
            self.setInitialState()
            self.setInitialState()
        QApplication.restoreOverrideCursor()
예제 #31
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)
예제 #32
0
class ViewServers(QtGui.QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        '''Constructor.'''
        super(ViewServers, 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
        self.abstractDbFactory = DbFactory()
        self.initGui()
    
    def initGui(self):
        header = self.tableWidget.horizontalHeader()
        header.setResizeMode(QHeaderView.Stretch)
        self.populateTable()
        
    def populateTable(self):
        currentConnections = self.getServers()
        self.tableWidget.setRowCount(len(currentConnections))
        for i, connection in enumerate(currentConnections):
            self.tableWidget.setItem(i, 0, QTableWidgetItem(connection))
            (host, port, user, password) = self.getServerConfiguration(connection)
            self.tableWidget.setItem(i, 1, QTableWidgetItem(host))
            self.tableWidget.setItem(i, 2, QTableWidgetItem(port))
            self.tableWidget.setItem(i, 3, QTableWidgetItem(user))
            if not password or len(password) == 0:
                self.tableWidget.setItem(i, 4, QTableWidgetItem(self.tr('Not Saved')))
            else:
                self.tableWidget.setItem(i, 4, QTableWidgetItem(self.tr('Saved')))
        
    @pyqtSlot(bool)
    def on_cancelButton_clicked(self):
        self.done(0)
        
    @pyqtSlot(bool)
    def on_addButton_clicked(self):
        dlg = ServerConfigurator(self)
        result = dlg.exec_()
        if result:
            self.populateTable()
            
    @pyqtSlot(bool)
    def on_editButton_clicked(self):
        selectedItem = self.returnSelectedName()
        if not selectedItem:
            return
        dlg = ServerConfigurator(self)
        dlg.setServerConfiguration(selectedItem.text())
        result = dlg.exec_()
        if result:
            self.populateTable()
        
    @pyqtSlot(bool)
    def on_removeButton_clicked(self):
        selectedItem = self.returnSelectedName()
        if not selectedItem:
            return
        self.removeServerConfiguration(selectedItem.text())
        self.tableWidget.removeRow(selectedItem.row())
        QMessageBox.warning(self, self.tr('Info!'), self.tr('Server removed.'))
        
    @pyqtSlot(bool)
    def on_testButton_clicked(self):
        selectedItem = self.returnSelectedName()
        if not selectedItem:
            return
        name = selectedItem.text()
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            test = self.testServer(name)
            QApplication.restoreOverrideCursor()
        except:
            QApplication.restoreOverrideCursor()
        if test:
            QMessageBox.warning(self, self.tr('Info!'), self.tr('Connection online.'))
        else:
            QMessageBox.warning(self, self.tr('Info!'), self.tr('Connection was not successful. Check log for details.'))
        
    def getServers(self):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers')
        currentConnections = settings.childGroups()
        settings.endGroup()
        return currentConnections
    
    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 removeServerConfiguration(self, name):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers/'+name)
        settings.remove('')
        settings.endGroup()
        
    def testServer(self, name):
        abstractDb = self.abstractDbFactory.createDbFactory('QPSQL')
        if not abstractDb:
            return False
        (host, port, user, password) = abstractDb.getServerConfiguration(name)
        abstractDb.connectDatabaseWithParameters(host, port, 'postgres', user, password)
        try:
            abstractDb.checkAndOpenDb()
        except Exception as e:
            QgsMessageLog.logMessage(e.args[0], 'DSG Tools Plugin', QgsMessageLog.CRITICAL)
            return False
        return True
    
    def returnSelectedName(self):
        if len(self.tableWidget.selectedItems()) == 0:
            QMessageBox.warning(self, self.tr('Warning!'), self.tr('Select one server.'))
            return
        return self.tableWidget.selectedItems()[0]
예제 #33
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)
class CustomServerConnectionWidget(QtGui.QWidget, FORM_CLASS):
    selectionChanged = pyqtSignal()
    resetAll = pyqtSignal()
    dbDictChanged = pyqtSignal(str,list)
    styleChanged = pyqtSignal(dict)
    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 3.0'):'3.0', 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':[], '3.0':[]}
        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
    
    def selectedDatabases(self, dbList, type):
        """
        Selects databases from a name list and database type
        """
        #TODO: build selectedDbsDict and emit dbDictChanged()
        #1- Iterate over dbList and check if all layers on dbList are on dict. If not, add it.
        if type == 'added':
            (host, port, user, password) = self.serverWidget.abstractDb.getParamsFromConectedDb()
            for dbName in dbList:
                if dbName not in self.selectedDbsDict.keys():
                    if host and port and user:
                        localDb = self.dbFactory.createDbFactory('QPSQL')
                        localDb.connectDatabaseWithParameters(host, port, dbName, user, password)
                        self.selectedDbsDict[dbName] = localDb
                        #do get dicts
                        localDict = localDb.getStyleDict(localDb.getDatabaseVersion())
                        for key in localDict.keys():
                            if key not in self.stylesDict.keys():
                                self.stylesDict[key] = dict()
                                self.stylesDict[key]['dbList'] = []
                            self.stylesDict[key]['style'] = localDict[key]
                            if dbName not in self.stylesDict[key]['dbList']:
                                self.stylesDict[key]['dbList'].append(dbName)
            self.dbDictChanged.emit('added', dbList)
            self.styleChanged.emit(self.stylesDict)
        #2- Iterate over selectedDbsDict and if there is a key not in dbList, close db and pop item
        if type == 'removed':
            for dbName in self.selectedDbsDict.keys():
                if dbName in dbList:
                    self.selectedDbsDict.pop(dbName)
            self.dbDictChanged.emit('removed', dbList)
            for key in self.stylesDict.keys():
                for db in self.stylesDict[key]['dbList']:
                    if db in dbList:
                        idx = self.stylesDict[key]['dbList'].index(db)
                        self.stylesDict[key]['dbList'].pop(idx)
                if len(self.stylesDict[key]['dbList']) == 0:
                    self.stylesDict.pop(key)
            self.styleChanged.emit(self.stylesDict)
    
    def selectedFiles(self, dbList, type):
        """
        Selects databases from a name list and database type
        """
        #TODO: build selectedDbsDict and emit dbDictChanged()
        #1- Iterate over dbList and check if all layers on dbList are on dict. If not, add it.
        if type == 'added':
            for dbName in dbList:
                if dbName not in self.selectedDbsDict.keys():
                    localDb = self.dbFactory.createDbFactory('QSQLITE')
                    localDb.connectDatabase(conn = self.spatialiteDict[dbName])
                    self.selectedDbsDict[dbName] = localDb
                    #do get dicts
                    localDict = localDb.getStyleDict(localDb.getDatabaseVersion())
                    for key in localDict.keys():
                        if key not in self.stylesDict.keys():
                            self.stylesDict[key] = dict()
                            self.stylesDict[key]['dbList'] = []
                        self.stylesDict[key]['style'] = localDict[key]
                        if dbName not in self.stylesDict[key]['dbList']:
                            self.stylesDict[key]['dbList'].append(dbName)
            self.dbDictChanged.emit('added', dbList)
            self.styleChanged.emit(self.stylesDict)
        #2- Iterate over selectedDbsDict and if there is a key not in dbList, close db and pop item
        if type == 'removed':
            for dbName in self.selectedDbsDict.keys():
                if dbName in dbList:
                    self.selectedDbsDict.pop(dbName)
            self.dbDictChanged.emit('removed', dbList)
            for key in self.stylesDict.keys():
                for db in self.stylesDict[key]['dbList']:
                    if db in dbList:
                        idx = self.stylesDict[key]['dbList'].index(db)
                        self.stylesDict[key]['dbList'].pop(idx)
                if len(self.stylesDict[key]['dbList']) == 0:
                    self.stylesDict.pop(key)
            self.styleChanged.emit(self.stylesDict)
    
    @pyqtSlot(int)
    def on_serverConnectionTab_currentChanged(self, currentTab):
        """
        Changes the database type (spatialite/postgis)
        """
        if currentTab == 0:
            self.clearSpatialiteTab()
            self.populatePostgisSelector()
        elif currentTab == 1:
            self.clearPostgisTab()
            self.populateSpatialiteSelector()
        pass
    
    def populatePostgisSelector(self):
        """
        Populates the postgis database list according to the database type
        """
        self.dbDict = {'2.1.3':[], 'FTer_2a_Ed':[],'Non_EDGV':[], '3.0':[]}
        dbList = []
        try:
            if self.serverWidget.abstractDb:
                dbList = self.serverWidget.abstractDb.getEDGVDbsFromServer(parentWidget = self)
            else:
                self.clearPostgisTab()
                return
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
            self.clearPostgisTab()
        dbList.sort()
        for (dbname, dbversion) in dbList:
            if dbversion in self.dbDict.keys():
                self.dbDict[dbversion].append(dbname)
            else:
                self.dbDict['Non_EDGV'].append(dbname)
        comboText = self.postgisEdgvComboFilter.currentText()
        self.postgisCustomSelector.setInitialState(self.dbDict[self.comboDict[comboText]]) 
    
    def populateSpatialiteSelector(self):
        """
        Populates the spatialite database list according to the databse type
        """
        self.dbDict = {'2.1.3':[], 'FTer_2a_Ed':[],'Non_EDGV':[], '3.0':[]}
        self.spatialiteDict = dict()
        dbList = []
        try:
            for dbPath in self.customFileSelector.fileNameList:
                auxAbstractDb = self.dbFactory.createDbFactory('QSQLITE')
                dbName = os.path.basename(dbPath).split('.')[0]
                self.path = os.path.dirname(dbPath)
                auxAbstractDb.connectDatabase(conn = dbPath)
                version = auxAbstractDb.getDatabaseVersion()
                dbList.append((dbName,version))
                self.spatialiteDict[dbName] = dbPath
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
            self.clearSpatialiteTab()
        dbList.sort()
        for (dbname, dbversion) in dbList:
            if dbversion in self.dbDict.keys():
                self.dbDict[dbversion].append(dbname)        
#         if len(self.dbDict['2.1.3']) == 0:
#             self.spatialiteEdgvComboFilter.setCurrentIndex(1)
        comboText = self.spatialiteEdgvComboFilter.currentText()
        self.spatialiteCustomSelector.setInitialState(self.dbDict[self.comboDict[comboText]]) 
    
    def clearSpatialiteTab(self):
        """
        Clears the postgis tab, returning it to the original state
        """
        self.spatialiteCustomSelector.clearAll()
        self.serverWidget.clearAll()
        self.dbDict = {'2.1.3':[], 'FTer_2a_Ed':[],'Non_EDGV':[],'3.0':[]}
        self.customFileSelector.resetAll()
        self.edgvType = None
        self.selectedDbsDict = dict()
        self.resetAll.emit()
    
    @pyqtSlot(int)
    def on_postgisEdgvComboFilter_currentIndexChanged(self):
        """
        Updates the postgis databases according to its type
        """
        comboText = self.postgisEdgvComboFilter.currentText()
        self.postgisCustomSelector.resetSelections()
        self.postgisCustomSelector.setInitialState(self.dbDict[self.comboDict[comboText]])
        self.serverConnectionTab
        self.edgvType = self.comboDict[comboText]
        self.resetAll.emit()
    
    @pyqtSlot(int)
    def on_spatialiteEdgvComboFilter_currentIndexChanged(self):
        """
        Updates the postgis databases according to its type
        """
        comboText = self.spatialiteEdgvComboFilter.currentText()
        self.spatialiteCustomSelector.setInitialState(self.dbDict[self.comboDict[comboText]])
        self.edgvType = self.comboDict[comboText]
        self.resetAll.emit()
    
    def clearPostgisTab(self):
        """
        Clears the spatialite tab, returning it to the original state
        """
        self.postgisCustomSelector.clearAll()
        self.serverWidget.clearAll()
        self.dbDict = {'2.1.3':[], 'FTer_2a_Ed':[],'Non_EDGV':[],'3.0':[]}
        self.edgvType = None
        self.selectedDbsDict = dict()
        self.resetAll.emit()
    
    def getStyles(self, type, abstractDb):
        """
        Gets database styles. If the structure to store styles is not yet created, we should create it.
        """
        dbVersion = abstractDb.getDatabaseVersion()
        abstractDb.checkAndCreateStyleTable()
        styles = abstractDb.getStyleDict(dbVersion)
        self.styleChanged.emit(type, styles)
예제 #35
0
class ExploreServerWidget(QtGui.QWidget, FORM_CLASS):
    abstractDbLoaded = pyqtSignal()
    clearWidgets = pyqtSignal()

    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.dbFactory = DbFactory()

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

    #TODO
    def browseServer(self, dbList, host, port, user, password):
        gen = self.factory.createSqlGenerator(False)
        edvgDbList = []
        for database in dbList:
            db = self.getPostGISDatabaseWithParams(database, host, port, user,
                                                   password)
            if not db.open():
                qgis.utils.iface.messageBar().pushMessage(
                    'DB :' + database + '| msg: ' +
                    db.lastError().databaseText(),
                    level=QgsMessageBar.CRITICAL)

            query = QSqlQuery(db)
            if query.exec_(gen.getEDGVVersion()):
                while query.next():
                    version = query.value(0)
                    if version:
                        edvgDbList.append((database, version))
        return edvgDbList

    #TODO
    def getDbsFromServer(self, name):
        gen = self.factory.createSqlGenerator(False)

        (host, port, user, password) = self.getServerConfiguration(name)
        database = 'postgres'

        db = self.getPostGISDatabaseWithParams(database, host, port, user,
                                               password)
        if not db.open():
            QgsMessageLog.logMessage(db.lastError().text(), "DSG Tools Plugin",
                                     QgsMessageLog.CRITICAL)

        query = QSqlQuery(gen.getDatabasesFromServer(), db)
        dbList = []
        while query.next():
            dbList.append(query.value(0))
        return self.browseServer(dbList, host, port, user, password)

    @pyqtSlot(bool)
    def on_createNewServerPushButton_clicked(self):
        createNewServer = ViewServers(self)
        createNewServer.exec_()
        self.populateServersCombo()

    def populateServersCombo(self):
        self.serversCombo.clear()
        self.serversCombo.addItem(self.tr('Select Server'))
        currentConnections = self.getServers()
        for connection in currentConnections:
            self.serversCombo.addItem(connection)

    @pyqtSlot(int)
    def on_serversCombo_currentIndexChanged(self):
        self.clearWidgets.emit()
        if self.serversCombo.currentIndex() != 0:
            self.abstractDb = self.dbFactory.createDbFactory('QPSQL')
            (host, port, user,
             password) = self.abstractDb.getServerConfiguration(
                 self.serversCombo.currentText())
            self.abstractDb.connectDatabaseWithParameters(
                host, port, 'postgres', user, password)
            self.abstractDbLoaded.emit()
예제 #36
0
class StyleManagerTool(QWidget, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """
        Constructor
        """
        super(StyleManagerTool, self).__init__(parent)
        self.setupUi(self)
        self.iface = iface
        self.splitter.hide()
        self.refreshDb()
        self.dbFactory = DbFactory()
        self.applyPushButton.setEnabled(False)
        self.utils = Utils()

    @pyqtSlot(bool)
    def on_layerPushButton_toggled(self, toggled):
        """
        Shows/Hides the tool bar
        """
        if toggled:
            self.refreshDb()
            self.splitter.show()
        else:
            self.splitter.hide()

    @pyqtSlot(bool, name='on_refreshPushButton_clicked')
    def refreshDb(self):
        self.dbComboBox.clear()
        self.dbComboBox.addItem(self.tr('Select Database'))
        #populate database list
        for dbName in self.getDatabaseList():
            self.dbComboBox.addItem(dbName)

    @pyqtSlot(int, name='on_dbComboBox_currentIndexChanged')
    @pyqtSlot(int, name='on_styleComboBox_currentIndexChanged')
    def enableApply(self):
        dbIdx = self.dbComboBox.currentIndex()
        stylesIdx = self.styleComboBox.currentIndex()
        if dbIdx > 0 and stylesIdx > 0:
            self.applyPushButton.setEnabled(True)
        else:
            self.applyPushButton.setEnabled(False)

    @pyqtSlot(bool)
    def on_applyPushButton_clicked(self):
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            dbName = self.dbComboBox.currentText()
            styleName = self.styleComboBox.currentText()
            lyrList = self.getLayers(dbName)
            abstractDb = self.getAbstractDb(dbName)
            dbVersion = abstractDb.getDatabaseVersion()
            stylesDict = abstractDb.getStyleDict(dbVersion)
            selectedStyle = stylesDict[styleName]
            localProgress = ProgressWidget(
                1,
                len(lyrList) - 1,
                self.tr('Loading style {0}').format(styleName),
                parent=self.iface.mapCanvas())
            for lyr in lyrList:
                try:
                    uri = QgsDataSourceURI(lyr.dataProvider().dataSourceUri())
                    fullPath = self.getStyle(abstractDb, selectedStyle,
                                             lyr.name())
                    if fullPath:
                        lyr.applyNamedStyle(fullPath)
                except:
                    pass
                localProgress.step()
            self.iface.mapCanvas().refreshAllLayers()
            QApplication.restoreOverrideCursor()
        except Exception as e:
            QgsMessageLog.logMessage(
                self.tr('Error setting style ') + styleName + ': ' +
                ':'.join(e.args), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            QApplication.restoreOverrideCursor()

    def getLayers(self, dbName):
        lyrList = []
        for lyr in self.iface.legendInterface().layers():
            if isinstance(lyr, QgsVectorLayer):
                candidateUri = QgsDataSourceURI(
                    lyr.dataProvider().dataSourceUri())
                if candidateUri.database() == dbName and lyr.providerType(
                ) in ['postgres', 'spatialite']:
                    lyrList.append(lyr)
        return lyrList

    def getDatabaseList(self):
        dbList = []
        for lyr in self.iface.legendInterface().layers():
            if isinstance(lyr, QgsVectorLayer):
                candidateUri = QgsDataSourceURI(
                    lyr.dataProvider().dataSourceUri())
                dbName = candidateUri.database()
                if dbName not in dbList and lyr.providerType() in [
                        'postgres', 'spatialite'
                ]:
                    dbList.append(dbName)
        return dbList

    def loadStylesCombo(self, abstractDb):
        dbVersion = abstractDb.getDatabaseVersion()
        styleDict = abstractDb.getStyleDict(dbVersion)
        self.styleComboBox.clear()
        styleList = styleDict.keys()
        numberOfStyles = len(styleList)
        if numberOfStyles > 0:
            self.styleComboBox.addItem(self.tr('Select Style'))
            for i in range(numberOfStyles):
                self.styleComboBox.addItem(styleList[i])
        else:
            self.styleComboBox.addItem(self.tr('No available styles'))

    def getParametersFromLyr(self, dbName):
        for lyr in self.iface.legendInterface().layers():
            if isinstance(lyr, QgsVectorLayer):
                candidateUri = QgsDataSourceURI(
                    lyr.dataProvider().dataSourceUri())
                if candidateUri.database() == dbName:
                    currLyr = lyr
                    break
        dbParameters = dict()
        if currLyr.providerType() == 'postgres':
            dbParameters['host'] = candidateUri.host()
            dbParameters['port'] = candidateUri.port()
            dbParameters['user'] = candidateUri.username()
            dbParameters['password'] = candidateUri.password()
            return dbParameters, 'QPSQL'
        if currLyr.providerType() == 'spatialite':
            dbParameters['dbPath'] = candidateUri.database()
            return dbParameters, 'QSQLITE'
        else:
            raise Exception(
                self.tr('Feature only implemented for PostGIS and Spatialite'))

    def getAbstractDb(self, dbName):
        dbParameters, driverName = self.getParametersFromLyr(dbName)
        abstractDb = self.dbFactory.createDbFactory(driverName)
        if 'host' in dbParameters.keys():
            abstractDb.connectDatabaseWithParameters(dbParameters['host'],
                                                     dbParameters['port'],
                                                     dbName,
                                                     dbParameters['user'],
                                                     dbParameters['password'])
        else:
            abstractDb.connectDatabase(dbParameters['dbPath'])
        return abstractDb

    @pyqtSlot(int)
    def on_dbComboBox_currentIndexChanged(self, idx):
        if idx <= 0:
            self.styleComboBox.clear()
            self.styleComboBox.addItem(self.tr('Select Style'))
            self.styleComboBox.setEnabled(False)
        elif idx > 0:
            self.styleComboBox.setEnabled(True)
            dbName = self.dbComboBox.currentText()
            abstractDb = self.getAbstractDb(dbName)
            self.loadStylesCombo(abstractDb)

    def getStyle(self, abstractDb, stylePath, className):
        if 'db:' in stylePath:
            return abstractDb.getStyle(stylePath.split(':')[-1], className)
        else:
            return self.getStyleFromFile(stylePath, className)

    def getStyleFromFile(self, stylePath, className):
        availableStyles = os.walk(stylePath).next()[2]
        styleName = className + '.qml'
        if styleName in availableStyles:
            path = os.path.join(stylePath, styleName)
            qml = self.utils.parseStyle(path)
            return qml
        else:
            return None
예제 #37
0
class CustomServerConnectionWidget(QtGui.QWidget, FORM_CLASS):
    selectionChanged = pyqtSignal()
    resetAll = pyqtSignal()
    dbDictChanged = pyqtSignal(str, list)
    styleChanged = pyqtSignal(dict)

    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 3.0'): '3.0',
            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': [],
            '3.0': []
        }
        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

    def selectedDatabases(self, dbList, type):
        """
        Selects databases from a name list and database type
        """
        #TODO: build selectedDbsDict and emit dbDictChanged()
        #1- Iterate over dbList and check if all layers on dbList are on dict. If not, add it.
        if type == 'added':
            (host, port, user, password
             ) = self.serverWidget.abstractDb.getParamsFromConectedDb()
            for dbName in dbList:
                if dbName not in self.selectedDbsDict.keys():
                    if host and port and user:
                        localDb = self.dbFactory.createDbFactory('QPSQL')
                        localDb.connectDatabaseWithParameters(
                            host, port, dbName, user, password)
                        self.selectedDbsDict[dbName] = localDb
                        #do get dicts
                        localDict = localDb.getStyleDict(
                            localDb.getDatabaseVersion())
                        for key in localDict.keys():
                            if key not in self.stylesDict.keys():
                                self.stylesDict[key] = dict()
                                self.stylesDict[key]['dbList'] = []
                            self.stylesDict[key]['style'] = localDict[key]
                            if dbName not in self.stylesDict[key]['dbList']:
                                self.stylesDict[key]['dbList'].append(dbName)
            self.dbDictChanged.emit('added', dbList)
            self.styleChanged.emit(self.stylesDict)
        #2- Iterate over selectedDbsDict and if there is a key not in dbList, close db and pop item
        if type == 'removed':
            for dbName in self.selectedDbsDict.keys():
                if dbName in dbList:
                    self.selectedDbsDict.pop(dbName)
            self.dbDictChanged.emit('removed', dbList)
            for key in self.stylesDict.keys():
                for db in self.stylesDict[key]['dbList']:
                    if db in dbList:
                        idx = self.stylesDict[key]['dbList'].index(db)
                        self.stylesDict[key]['dbList'].pop(idx)
                if len(self.stylesDict[key]['dbList']) == 0:
                    self.stylesDict.pop(key)
            self.styleChanged.emit(self.stylesDict)

    def selectedFiles(self, dbList, type):
        """
        Selects databases from a name list and database type
        """
        #TODO: build selectedDbsDict and emit dbDictChanged()
        #1- Iterate over dbList and check if all layers on dbList are on dict. If not, add it.
        if type == 'added':
            for dbName in dbList:
                if dbName not in self.selectedDbsDict.keys():
                    localDb = self.dbFactory.createDbFactory('QSQLITE')
                    localDb.connectDatabase(conn=self.spatialiteDict[dbName])
                    self.selectedDbsDict[dbName] = localDb
                    #do get dicts
                    localDict = localDb.getStyleDict(
                        localDb.getDatabaseVersion())
                    for key in localDict.keys():
                        if key not in self.stylesDict.keys():
                            self.stylesDict[key] = dict()
                            self.stylesDict[key]['dbList'] = []
                        self.stylesDict[key]['style'] = localDict[key]
                        if dbName not in self.stylesDict[key]['dbList']:
                            self.stylesDict[key]['dbList'].append(dbName)
            self.dbDictChanged.emit('added', dbList)
            self.styleChanged.emit(self.stylesDict)
        #2- Iterate over selectedDbsDict and if there is a key not in dbList, close db and pop item
        if type == 'removed':
            for dbName in self.selectedDbsDict.keys():
                if dbName in dbList:
                    self.selectedDbsDict.pop(dbName)
            self.dbDictChanged.emit('removed', dbList)
            for key in self.stylesDict.keys():
                for db in self.stylesDict[key]['dbList']:
                    if db in dbList:
                        idx = self.stylesDict[key]['dbList'].index(db)
                        self.stylesDict[key]['dbList'].pop(idx)
                if len(self.stylesDict[key]['dbList']) == 0:
                    self.stylesDict.pop(key)
            self.styleChanged.emit(self.stylesDict)

    @pyqtSlot(int)
    def on_serverConnectionTab_currentChanged(self, currentTab):
        """
        Changes the database type (spatialite/postgis)
        """
        if currentTab == 0:
            self.clearSpatialiteTab()
            self.populatePostgisSelector()
        elif currentTab == 1:
            self.clearPostgisTab()
            self.populateSpatialiteSelector()
        pass

    def populatePostgisSelector(self):
        """
        Populates the postgis database list according to the database type
        """
        self.dbDict = {
            '2.1.3': [],
            'FTer_2a_Ed': [],
            'Non_EDGV': [],
            '3.0': []
        }
        dbList = []
        try:
            if self.serverWidget.abstractDb:
                dbList = self.serverWidget.abstractDb.getEDGVDbsFromServer(
                    parentWidget=self)
            else:
                self.clearPostgisTab()
                return
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
            self.clearPostgisTab()
        dbList.sort()
        for (dbname, dbversion) in dbList:
            if dbversion in self.dbDict.keys():
                self.dbDict[dbversion].append(dbname)
            else:
                self.dbDict['Non_EDGV'].append(dbname)
        comboText = self.postgisEdgvComboFilter.currentText()
        self.postgisCustomSelector.setInitialState(
            self.dbDict[self.comboDict[comboText]])

    def populateSpatialiteSelector(self):
        """
        Populates the spatialite database list according to the databse type
        """
        self.dbDict = {
            '2.1.3': [],
            'FTer_2a_Ed': [],
            'Non_EDGV': [],
            '3.0': []
        }
        self.spatialiteDict = dict()
        dbList = []
        try:
            for dbPath in self.customFileSelector.fileNameList:
                auxAbstractDb = self.dbFactory.createDbFactory('QSQLITE')
                dbName = os.path.basename(dbPath).split('.')[0]
                self.path = os.path.dirname(dbPath)
                auxAbstractDb.connectDatabase(conn=dbPath)
                version = auxAbstractDb.getDatabaseVersion()
                dbList.append((dbName, version))
                self.spatialiteDict[dbName] = dbPath
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
            self.clearSpatialiteTab()
        dbList.sort()
        for (dbname, dbversion) in dbList:
            if dbversion in self.dbDict.keys():
                self.dbDict[dbversion].append(dbname)
#         if len(self.dbDict['2.1.3']) == 0:
#             self.spatialiteEdgvComboFilter.setCurrentIndex(1)
        comboText = self.spatialiteEdgvComboFilter.currentText()
        self.spatialiteCustomSelector.setInitialState(
            self.dbDict[self.comboDict[comboText]])

    def clearSpatialiteTab(self):
        """
        Clears the postgis tab, returning it to the original state
        """
        self.spatialiteCustomSelector.clearAll()
        self.serverWidget.clearAll()
        self.dbDict = {
            '2.1.3': [],
            'FTer_2a_Ed': [],
            'Non_EDGV': [],
            '3.0': []
        }
        self.customFileSelector.resetAll()
        self.edgvType = None
        self.selectedDbsDict = dict()
        self.resetAll.emit()

    @pyqtSlot(int)
    def on_postgisEdgvComboFilter_currentIndexChanged(self):
        """
        Updates the postgis databases according to its type
        """
        comboText = self.postgisEdgvComboFilter.currentText()
        self.postgisCustomSelector.resetSelections()
        self.postgisCustomSelector.setInitialState(
            self.dbDict[self.comboDict[comboText]])
        self.serverConnectionTab
        self.edgvType = self.comboDict[comboText]
        self.resetAll.emit()

    @pyqtSlot(int)
    def on_spatialiteEdgvComboFilter_currentIndexChanged(self):
        """
        Updates the postgis databases according to its type
        """
        comboText = self.spatialiteEdgvComboFilter.currentText()
        self.spatialiteCustomSelector.setInitialState(
            self.dbDict[self.comboDict[comboText]])
        self.edgvType = self.comboDict[comboText]
        self.resetAll.emit()

    def clearPostgisTab(self):
        """
        Clears the spatialite tab, returning it to the original state
        """
        self.postgisCustomSelector.clearAll()
        self.serverWidget.clearAll()
        self.dbDict = {
            '2.1.3': [],
            'FTer_2a_Ed': [],
            'Non_EDGV': [],
            '3.0': []
        }
        self.edgvType = None
        self.selectedDbsDict = dict()
        self.resetAll.emit()

    def getStyles(self, type, abstractDb):
        """
        Gets database styles. If the structure to store styles is not yet created, we should create it.
        """
        dbVersion = abstractDb.getDatabaseVersion()
        abstractDb.checkAndCreateStyleTable()
        styles = abstractDb.getStyleDict(dbVersion)
        self.styleChanged.emit(type, styles)
예제 #38
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.iface = iface
        
        self.dbButton.clicked.connect(self.getDataSources)
        self.dbCombo.activated.connect(self.updateComplexClass)
        self.complexCombo.activated.connect(self.loadAssociatedFeatures)
        self.iface.newProjectCreated.connect(self.clearDock)

        self.abstractDb = None
        self.databases = None
        self.abstractDbFactory = DbFactory()

    def __del__(self):
        """
        Destructor
        """
        self.renewDb
            
    def renewDb(self):
        """
        Deletes the current abstractDb
        """
        if self.abstractDb:
            del self.abstractDb
            self.abstractDb = None

    def clearDock(self):
        """
        Clears the complex dock widget
        """
        self.treeWidget.clear()
        self.dbCombo.clear()
        self.complexCombo.clear()

    #verificar se é necessario
    def isSpatialiteDatabase(self, dbName):
        """
        Checks if the database in use is a spatialite database
        """
        (dataSourceUri, credentials) = self.databases[dbName]
        if dataSourceUri.host() == "":
            return True
        return False

    def getUserCredentials(self, lyr):
        """
        Gets user credentials to acess the database
        """
        dataSourceUri = QgsDataSourceURI(lyr.dataProvider().dataSourceUri())
        if dataSourceUri.host() == '':
            return (None, None)

        if dataSourceUri.password() != '':
            return (dataSourceUri.username(), dataSourceUri.password())

        connInfo = dataSourceUri.connectionInfo()
        (success, user, passwd ) = QgsCredentials.instance().get(connInfo, dataSourceUri.username(), 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)
        else:
            return (None, None)

        return (user, passwd)

    def updateComplexClass(self):
        """
        Updates the complex classes in the complex combo box
        """
        self.renewDb()

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

        dbName = self.dbCombo.currentText()
        
        (dataSourceUri, credentials) = self.databases[dbName]
        #verifying the connection type
        if self.isSpatialiteDatabase(dbName):
            self.abstractDb = self.abstractDbFactory.createDbFactory('QSQLITE')
            self.abstractDb.connectDatabase(dataSourceUri.database())
        else:
            self.abstractDb = self.abstractDbFactory.createDbFactory('QPSQL')
            
            database = dbName
            host = dataSourceUri.host()
            port = int(dataSourceUri.port())
            user = credentials[0]
            password = credentials[1]
            
            self.abstractDb.connectDatabaseWithParameters(host, port, database, user, password)
        try:
            self.abstractDb.checkAndOpenDb()
            self.populateComboBox()
        except Exception as e:
            QMessageBox.critical(self.iface.mainWindow(), self.tr("Critical!"), ':'.join(e.args))

    def populateComboBox(self):
        """
        Fills the complex combo box with complex classes
        """
        #getting all complex tables
        self.complexCombo.clear()
        self.complexCombo.addItem(self.tr("select a complex class"))

        complexClasses = []
        try:
            complexClasses = self.abstractDb.listComplexClassesFromDatabase()
        except Exception as e:
            QMessageBox.critical(self.iface.mainWindow(), self.tr("Critical!"), ':'.join(e.args))
            QgsMessageLog.logMessage(e.args[0], 'DSG Tools Plugin', QgsMessageLog.CRITICAL)

        self.complexCombo.addItems(complexClasses)

    def getDataSources(self):
        """
        Obtains the available databases from the layers loaded in the TOC
        """
        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.keys():
                self.databases[dbName] = (dataSourceUri, self.getUserCredentials(layer))
                #populating the combo
                self.dbCombo.addItem(dbName)

    @pyqtSlot(bool)
    def on_managePushButton_clicked(self):
        """
        Opens the dialog to manage complex features
        """
        #opens a dialog to manage complexes
        if not self.abstractDb:
            QMessageBox.critical(self.iface.mainWindow(), self.tr("Critical!"), self.tr('Select a database before managing a complex!'))
            return
        dlg = ManageComplexDialog(self.iface, self.abstractDb, self.complexCombo.currentText())
        #connects a signal to update the tree widget when done
        QObject.connect(dlg, SIGNAL(("tableUpdated()")), self.loadAssociatedFeatures)
        #connects a signal to disassociate features from complex before removal
        QObject.connect(dlg, SIGNAL(("markedToRemove( PyQt_PyObject )")), self.disassociateFeatures)
        result = dlg.exec_()
        if result:
            pass

    @pyqtSlot(bool)
    def on_associatePushButton_clicked(self):
        """
        Slot used to associate features to a complex
        """
        self.associateFeatures()

    @pyqtSlot(bool)
    def on_zoomButton_clicked(self):
        """
        Slot used to zoom the mapcanvas to the features associated to a complex
        """
        #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 and i == 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 disassociateFeatures(self, toBeRemoved):
        """
        Disassociates features from a complex
        toBeremoved: uuid of the complex that will have all its associated features disassociated
        """
        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):
        """
        Disassociates a particular class from a complex
        item: aggregated class to be disassociated
        """
        aggregated_class = item.text(0)
        uuid = item.parent().text(1)
        complex = item.parent().parent().text(0)

        link_column = ''
        try:
            link_column = self.abstractDb.obtainLinkColumn(complex, aggregated_class)
        except Exception as e:
            QMessageBox.critical(self.iface.mainWindow(), self.tr('Critical'), self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), 'DSG Tools Plugin', QgsMessageLog.CRITICAL)

        #getting the layer the needs to be updated
        aggregated_layer = None
        layers = self.iface.mapCanvas().layers()
        for layer in layers:
            #in case of spatialite databases when a complex class is added as a layer it's name has 'complexos_'
            if layer.name() == aggregated_class or layer.name() == 'complexos_'+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):
        """
        Disassociates a particular feature from a complex
        item: aggregated feature to be disassociated
        """        
        aggregated_class = item.parent().text(0)
        uuid = item.parent().parent().text(1)
        complex = item.parent().parent().parent().text(0)

        link_column = ''
        try:
            link_column = self.abstractDb.obtainLinkColumn(complex, aggregated_class)
        except Exception as e:
            QMessageBox.critical(self.iface.mainWindow(), self.tr('Critical'), self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), 'DSG Tools Plugin', QgsMessageLog.CRITICAL)

        #getting the layer the needs to be updated
        aggregated_layer = None
        layers = self.iface.mapCanvas().layers()
        for layer in layers:
            #in case of spatialite databases when a complex class is added as a layer it's name has 'complexos_'
            if layer.name() == aggregated_class or layer.name() == 'complexos_'+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):
        """
        Updates the layer upon disassociation from complex
        layer: layer that will be afected
        aggregated_class: aggregated class
        link_column: link column between complex and class
        id: feature id
        """
        try:
            if self.abstractDb.isComplexClass(aggregated_class):
                    self.abstractDb.disassociateComplexFromComplex(aggregated_class, link_column, id)
            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})
        except Exception as e:
            QMessageBox.critical(self.iface.mainWindow(), self.tr("Critical!"), e.args[0])
            QgsMessageLog.logMessage(':'.join(e.args), 'DSG Tools Plugin', QgsMessageLog.CRITICAL)

    @pyqtSlot(bool)
    def on_disassociatePushButton_clicked(self):
        """
        Starts the disassociation process.
        It will firts check the depth of the item that need to be disassociated and them call the correct method to to the job.
        It can be a particular class or a particular feature
        """
        #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):
        """
        Loads all features associated to a complex
        """
        self.treeWidget.clear()

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

        complex = self.complexCombo.currentText()

        associatedDict = dict()
        try:
            associatedDict = self.abstractDb.loadAssociatedFeatures(complex)
        except Exception as e:
            QMessageBox.critical(self.iface.mainWindow(), self.tr('Critical'), self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), 'DSG Tools Plugin', QgsMessageLog.CRITICAL)
            
        for name in associatedDict.keys():
            for complex_uuid in associatedDict[name].keys():
                self.addAssociatedFeature(complex, name, complex_uuid, None, None)
                for aggregated_class in associatedDict[name][complex_uuid]:
                    for ogc_fid in associatedDict[name][complex_uuid][aggregated_class]:
                        self.addAssociatedFeature(complex, name, complex_uuid, aggregated_class, ogc_fid)

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

    def associateFeatures(self):
        """
        Associates all features selected in the map canvas to a complex.
        """
        #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()

        #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:
            if layer.type() != QgsMapLayer.VectorLayer:
                continue
            #case no fetures selected we proceed to the next one
            selectedFeatures = layer.selectedFeatures()
            if len(selectedFeatures) == 0:
                continue

            #obtaining the link column
            column_name = ''
            try:
                column_name = self.abstractDb.obtainLinkColumn(complex, layer.name())
            except Exception as e:
                QMessageBox.critical(self.iface.mainWindow(), self.tr('Critical'), self.tr('A problem occurred! Check log for details.'))
                QgsMessageLog.logMessage(':'.join(e.args), 'DSG Tools Plugin', QgsMessageLog.CRITICAL)

            #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 = ""):
        """
        Creates tree items
        parent: parent item
        text: item text
        uuid: complex 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):
        """
        Adds a feature to a complex
        className: class name
        complexName: complex name
        complexId: complex uuid
        associatedClass: associated class
        associatedId: associated id
        """
        #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
예제 #39
0
class BatchDbManager(QtGui.QDialog, FORM_CLASS):
    EDGV213, EDGV_FTer_2a_Ed, Non_EDGV = range(3)

    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'
        }

    @pyqtSlot(bool)
    def on_closePushButton_clicked(self):
        self.done(0)

    def showTabs(self, show=True):
        if show:
            self.tabWidget.show()
        else:
            self.tabWidget.hide()

    def populateListWithDatabasesFromServer(self):
        try:
            dbList = self.serverWidget.abstractDb.getEDGVDbsFromServer(
                parentWidget=self)
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))

        dbList.sort()
        for (dbname, dbversion) in dbList:
            if dbversion not in self.dbDict.keys():
                dbversion = 'Non_EDGV'
            if dbname not in self.dbDict[dbversion]:
                self.dbDict[dbversion].append(dbname)

    def setDatabases(self):
        self.populateListWithDatabasesFromServer()

    @pyqtSlot(int)
    def on_edgvComboFilter_currentIndexChanged(self, idx):
        if idx != -1 and idx != 0:
            self.dbsCustomSelector.setInitialState(self.dbDict[
                self.correspondenceDict[self.edgvComboFilter.currentText()]])

    def checkSuperUser(self):
        try:
            if self.serverWidget.abstractDb.checkSuperUser():
                self.setDatabases()
            else:
                QMessageBox.warning(
                    self, self.tr('Info!'),
                    self.
                    tr('Connection refused. Connect with a super user to inspect server.'
                       ))
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))

    def getSelectedDbList(self):
        return self.dbsCustomSelector.toLs

    def instantiateAbstractDbs(self, instantiateTemplates=False):
        dbsDict = dict()
        selectedDbNameList = self.getSelectedDbList()
        if instantiateTemplates:
            for templateName in ['template_213', 'template_FTer_2a_Ed']:
                if templateName not in selectedDbNameList:
                    if templateName != 'dsgtools_admindb':
                        selectedDbNameList.append(templateName)
        for dbName in selectedDbNameList:
            localDb = self.dbFactory.createDbFactory('QPSQL')
            localDb.connectDatabaseWithParameters(
                self.serverWidget.abstractDb.db.hostName(),
                self.serverWidget.abstractDb.db.port(), dbName,
                self.serverWidget.abstractDb.db.userName(),
                self.serverWidget.abstractDb.db.password())
            dbsDict[dbName] = localDb
        return dbsDict

    def closeAbstractDbs(self, dbsDict):
        exceptionDict = dict()
        for dbName in dbsDict.keys():
            try:
                dbsDict[dbName].db.close()
            except Exception as e:
                exceptionDict[dbName] = ':'.join(e.args)
        return exceptionDict

    def outputMessage(self, header, successList, exceptionDict):
        msg = header
        if len(successList) > 0:
            msg += self.tr('\nSuccessful databases: ')
            msg += ', '.join(successList)
        msg += self.logInternalError(exceptionDict)
        QMessageBox.warning(self, self.tr('Operation Complete!'), msg)

    def logInternalError(self, exceptionDict):
        msg = ''
        errorDbList = exceptionDict.keys()
        if len(errorDbList) > 0:
            msg += self.tr('\nDatabases with error:')
            msg += ', '.join(errorDbList)
            msg += self.tr(
                '\nError messages for each database were output in qgis log.')
            for errorDb in errorDbList:
                QgsMessageLog.logMessage(
                    self.tr('Error for database ') + errorDb + ': ' +
                    exceptionDict[errorDb], "DSG Tools Plugin",
                    QgsMessageLog.CRITICAL)
        return msg

    @pyqtSlot(bool)
    def on_dropDatabasePushButton_clicked(self):
        selectedDbNameList = self.getSelectedDbList()
        if len(selectedDbNameList) == 0:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Please select one or more databases to drop!'))
        if QtGui.QMessageBox.question(
                self, self.tr('Question'),
                self.tr('Do you really want to drop databases: ') +
                ', '.join(selectedDbNameList), QtGui.QMessageBox.Ok
                | QtGui.QMessageBox.Cancel) == QtGui.QMessageBox.Cancel:
            return
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchDropDbs(selectedDbNameList)
        QApplication.restoreOverrideCursor()
        self.setDatabases()
        header = self.tr('Drop operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)
        self.dbsCustomSelector.setInitialState(self.dbsCustomSelector.fromLs)

    @pyqtSlot(bool)
    def on_upgradePostgisPushButton_clicked(self):
        selectedDbNameList = self.getSelectedDbList()
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchUpgradePostgis(
            selectedDbNameList)
        QApplication.restoreOverrideCursor()
        self.setDatabases()
        header = self.tr('Upgrade Posgtis operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)

    def batchUpgradePostgis(self, dbList):
        exceptionDict = dict()
        successList = []
        dbsDict = self.instantiateAbstractDbs(instantiateTemplates=True)
        self.closeAbstractDbs(dbsDict)
        for dbName in dbsDict.keys():
            try:
                if self.serverWidget.abstractDb.checkIfTemplate(dbName):
                    self.serverWidget.abstractDb.setDbAsTemplate(
                        dbName=dbName, setTemplate=False)
                    dbsDict[dbName].upgradePostgis()
                    self.serverWidget.abstractDb.setDbAsTemplate(
                        dbName=dbName, setTemplate=True)
                    successList.append(dbName)
                else:
                    dbsDict[dbName].upgradePostgis()
                    successList.append(dbName)
            except Exception as e:
                exceptionDict[dbName] = ':'.join(e.args)
        return successList, exceptionDict

    def batchDropDbs(self, dbList):
        exceptionDict = dict()
        successList = []
        dbsDict = self.instantiateAbstractDbs()
        self.closeAbstractDbs(dbsDict)
        for dbName in dbList:
            try:
                self.serverWidget.abstractDb.dropDatabase(dbName)
                successList.append(dbName)
            except Exception as e:
                exceptionDict[dbName] = ':'.join(e.args)
        return successList, exceptionDict

    @pyqtSlot(bool)
    def on_importStylesPushButton_clicked(self):
        dbsDict = self.instantiateAbstractDbs()
        exceptionDict = dict()
        versionList = []

        for dbName in dbsDict.keys():
            try:
                version = dbsDict[dbName].getDatabaseVersion()
                if version not in versionList:
                    versionList.append(version)
            except Exception as e:
                exceptionDict[dbName] = ':'.join(e.args)
        if len(exceptionDict.keys()) > 0:
            self.logInternalError(exceptionDict)
        if len(versionList) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Multiple edgv versions are not allowed!'))
            return
        styleDir = self.getStyleDir(versionList)
        styleList = self.getStyleList(styleDir)
        dlg = SelectStyles(styleList)
        dlg.exec_()
        selectedStyles = dlg.selectedStyles
        if len(selectedStyles) == 0:
            return
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchImportStyles(
            dbsDict, styleDir, selectedStyles, versionList[0])
        QApplication.restoreOverrideCursor()
        header = self.tr('Import operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)
        self.populateStylesInterface()
        closeExceptionDict = self.closeAbstractDbs(dbsDict)
        self.logInternalError(closeExceptionDict)

    def getStyleList(self, styleDir):
        #TODO: Reimplement
        styleList = []
        version = None
        if os.path.basename(styleDir) in ['edgv_213', 'edgv_FTer_2a_Ed']:
            version = os.path.basename(styleDir)
        else:
            parentFolder = os.path.dirname(styleDir)
            version = os.path.basename(parentFolder)
        for style in os.walk(styleDir).next()[1]:
            styleList.append('/'.join([version, style]))
        if len(styleList) == 0:
            styleList = [version + '/' + os.path.basename(styleDir)]
        return styleList

    def batchImportStyles(self, dbsDict, styleDir, styleList, version):
        exceptionDict = dict()
        successList = []
        for dbName in dbsDict.keys():
            for style in styleList:
                try:
                    dbsDict[dbName].importStylesIntoDb(style)
                    successList.append(dbName)
                except Exception as e:
                    exceptionDict[dbName] = ':'.join(e.args)
        return successList, exceptionDict

    def getStyleDir(self, versionList):
        currentPath = os.path.join(
            os.path.dirname(__file__), '..', 'Styles',
            self.serverWidget.abstractDb.versionFolderDict[versionList[0]])
        return currentPath

    def getStylesFromDbs(self, perspective='style'):
        '''
        Returns a dict of styles in a form acording to perspective:
            if perspective = 'style'    : [styleName][dbName][tableName] = timestamp
            if perspective = 'database' : [dbName][styleName][tableName] = timestamp 
        '''
        dbsDict = self.instantiateAbstractDbs()
        allStylesDict = dict()
        exceptionDict = dict()
        for dbName in dbsDict.keys():
            try:
                newDict = dbsDict[dbName].getAllStylesDict(perspective)
                allStylesDict = self.utils.mergeDict(newDict, allStylesDict)
            except Exception as e:
                exceptionDict[dbName] = ':'.join(e.args)
        if len(exceptionDict.keys()) > 0:
            self.logInternalError(exceptionDict)
        return allStylesDict

    def createItem(self, parent, text, column):
        item = QtGui.QTreeWidgetItem(parent)
        item.setText(column, text)
        return item

    def populateStylesInterface(self):
        self.stylesTreeWidget.clear()
        allStylesDict = self.getStylesFromDbs()
        rootNode = self.stylesTreeWidget.invisibleRootItem()
        for styleName in allStylesDict.keys():
            parentStyleItem = self.createItem(rootNode, styleName, 0)
            dbList = allStylesDict[styleName].keys()
            parentTimeList = []
            for dbName in dbList:
                dbItem = self.createItem(parentStyleItem, dbName, 1)
                tableList = allStylesDict[styleName][dbName].keys()
                tableList.sort()
                timeList = []
                for table in tableList:
                    tableItem = self.createItem(dbItem, table, 2)
                    timeStamp = allStylesDict[styleName][dbName][
                        table].toString()
                    timeList.append(timeStamp)
                    tableItem.setText(
                        3, allStylesDict[styleName][dbName][table].toString())
                parentTimeList.append(max(timeList))
                dbItem.setText(3, max(timeList))

    @pyqtSlot(bool)
    def on_deleteStyles_clicked(self):
        dbsDict = self.instantiateAbstractDbs()
        styleDict = self.getStylesFromDbs()
        styleList = styleDict.keys()
        dlg = SelectStyles(styleList)
        dlg.exec_()
        selectedStyles = dlg.selectedStyles
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchDeleteStyles(dbsDict, styleDict)
        QApplication.restoreOverrideCursor()
        header = self.tr('Delete operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)
        self.populateStylesInterface()
        closeExceptionDict = self.closeAbstractDbs(dbsDict)
        self.logInternalError(closeExceptionDict)

    def batchDeleteStyles(self, dbsDict, styleDict):
        exceptionDict = dict()
        successList = []
        for style in styleDict.keys():
            for dbName in styleDict[style].keys():
                try:
                    dbsDict[dbName].deleteStyle(style)
                    successList.append(dbName)
                except Exception as e:
                    exceptionDict[dbName] = ':'.join(e.args)
        return successList, exceptionDict

    def getSQLFile(self):
        fd = QFileDialog()
        filename = fd.getOpenFileName(caption=self.tr('Select a SQL file'),
                                      filter=self.tr('sql file (*.sql)'))
        return filename

    @pyqtSlot(bool)
    def on_customizeFromSQLFilePushButton_clicked(self):
        dbsDict = self.instantiateAbstractDbs()
        sqlFilePath = self.getSQLFile()
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchCustomizeFromSQLFile(
            dbsDict, sqlFilePath)
        QApplication.restoreOverrideCursor()
        header = self.tr('Customize from SQL file operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)
        closeExceptionDict = self.closeAbstractDbs(dbsDict)
        self.logInternalError(closeExceptionDict)

    def batchCustomizeFromSQLFile(self, dbsDict, sqlFilePath):
        exceptionDict = dict()
        successList = []
        for dbName in dbsDict.keys():
            try:
                dbsDict[dbName].runSqlFromFile(sqlFilePath)
                successList.append(dbName)
            except Exception as e:
                exceptionDict[dbName] = ':'.join(e.args)
        return successList, exceptionDict

    def populateOtherInterfaces(self):
        dbsDict = self.instantiateAbstractDbs()
        if self.edgvComboFilter.currentIndex() != 0:
            edgvVersion = self.correspondenceDict[
                self.edgvComboFilter.currentText()]
            self.permissionWidget.setParameters(self.serverWidget.abstractDb,
                                                dbsDict, edgvVersion)
            # self.customizationManagerWidget.setParameters(self.serverWidget.abstractDb, edgvVersion, dbsDict = dbsDict)
            self.fieldToolBoxConfigManagerWidget.setParameters(
                self.serverWidget.abstractDb, edgvVersion, dbsDict=dbsDict)
            self.earthCoverageManagerWidget.setParameters(
                self.serverWidget.abstractDb, edgvVersion, dbsDict=dbsDict)
예제 #40
0
class ExploreServerWidget(QtGui.QWidget, FORM_CLASS):
    abstractDbLoaded = pyqtSignal()
    serverAbstractDbLoaded = pyqtSignal(AbstractDb)
    clearWidgets = pyqtSignal()

    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.superNeeded = False
        self.dbFactory = DbFactory()
        self.abstractDb = None

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

    def getServerConfiguration(self, name):
        """
        Gets server configuration
        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 browseServer(self, dbList, host, port, user, password):
        """
        Browses server for EDGV databases
        dbList: databases list
        host: server host ip address
        port: server port
        user: user name
        password: password
        """
        canLoad = True
        if self.superNeeded:
            canLoad = False
            try:
                if self.serverWidget.abstractDb.checkSuperUser():
                    canLoad = True
                else:
                    QMessageBox.warning(
                        self, self.tr('Info!'),
                        self.
                        tr('Connection refused. Connect with a super user to inspect server.'
                           ))
                    return []
            except Exception as e:
                QMessageBox.critical(self, self.tr('Critical!'),
                                     ':'.join(e.args))
        if canLoad:
            progress = ProgressWidget(
                1,
                len(dbList),
                self.tr('Loading databases from server... '),
                parent=self)
            progress.initBar()
            gen = self.factory.createSqlGenerator(False)
            edvgDbList = []
            for database in dbList:
                db = self.getPostGISDatabaseWithParams(database, host, port,
                                                       user, password)
                if not db.open():
                    qgis.utils.iface.messageBar().pushMessage(
                        'DB :' + database + '| msg: ' +
                        db.lastError().databaseText(),
                        level=QgsMessageBar.CRITICAL)

                query = QSqlQuery(db)
                if query.exec_(gen.getEDGVVersion()):
                    while query.next():
                        version = query.value(0)
                        if version:
                            edvgDbList.append((database, version))
                progress.step()
            return edvgDbList

    def getDbsFromServer(self, name):
        """
        Gets server databases
        name: server name
        """
        gen = self.factory.createSqlGenerator(False)

        (host, port, user, password) = self.getServerConfiguration(name)
        database = 'postgres'

        db = self.getPostGISDatabaseWithParams(database, host, port, user,
                                               password)
        if not db.open():
            QgsMessageLog.logMessage(db.lastError().text(), "DSG Tools Plugin",
                                     QgsMessageLog.CRITICAL)
            QMessageBox.critical(
                self.iface.mainWindow(), self.tr('Critical'),
                self.tr('A problem occurred! Check log for details.'))

        query = QSqlQuery(gen.getDatabasesFromServer(), db)
        if not query.isActive():
            QMessageBox.critical(
                self.iface.mainWindow(), self.tr('Critical'),
                self.tr("Problem executing query: ") +
                query.lastError().text())

        dbList = []
        while query.next():
            dbList.append(query.value(0))
        return self.browseServer(dbList, host, port, user, password)

    @pyqtSlot(bool)
    def on_createNewServerPushButton_clicked(self):
        """
        Opens the View Server dialog
        """
        createNewServer = ViewServers(self)
        result = createNewServer.exec_()
        self.populateServersCombo()

    def populateServersCombo(self):
        """
        Populates the server name combo box
        """
        self.serversCombo.clear()
        self.serversCombo.addItem(self.tr('Select Server'))
        currentConnections = self.getServers()
        for connection in currentConnections:
            (host, port, user,
             password) = self.getServerConfiguration(connection)
            self.serversCombo.addItem('{3} ({0}@{1}:{2})'.format(
                user, host, port, connection))

    @pyqtSlot(int)
    def on_serversCombo_currentIndexChanged(self):
        """
        Updates the server databases
        """
        self.clearWidgets.emit()
        if self.serversCombo.currentIndex() != 0:
            self.abstractDb = self.dbFactory.createDbFactory('QPSQL')
            if not self.abstractDb:
                QMessageBox.critical(
                    self.iface.mainWindow(), self.tr('Critical'),
                    self.tr('A problem occurred! Check log for details.'))
                return
            (host, port, user,
             password) = self.abstractDb.getServerConfiguration(
                 self.serversCombo.currentText().split('(')[0][0:-1])
            if host or port or user:
                self.abstractDb.connectDatabaseWithParameters(
                    host, port, 'postgres', user, password)
                if self.superNeeded:
                    try:
                        if not self.abstractDb.checkSuperUser():
                            QMessageBox.warning(
                                self, self.tr('Info!'),
                                self.
                                tr('Connection refused. Connect with a super user to inspect server.'
                                   ))
                            self.serversCombo.setCurrentIndex(0)
                            return
                    except Exception as e:
                        QMessageBox.critical(self, self.tr('Critical!'),
                                             ':'.join(e.args))
                self.abstractDbLoaded.emit()
        else:
            try:
                if self.abstractDb:
                    self.abstractDb.__del__()
                    self.abstractDb = None
            except:
                pass
        self.serverAbstractDbLoaded.emit(self.abstractDb)

    def getServerParameters(self):
        """
        Gets postgis server parameters
        """
        if self.serversCombo.currentIndex() != 0:
            return self.abstractDb.getServerConfiguration(
                self.serversCombo.currentText().split('(')[0][0:-1])
        else:
            return (None, None, None, None)

    def clearAll(self):
        """
        Resets the widget
        """
        try:
            if self.abstractDb:
                self.abstractDb.__del__()
                self.abstractDb = None
        except:
            pass
        self.serversCombo.setCurrentIndex(0)
예제 #41
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)
예제 #42
0
class ExploreDb(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.dbFactory = DbFactory()
        self.localDb = None
        self.serverWidget.populateServersCombo()
        #signal connections
        self.serverWidget.abstractDbLoaded.connect(self.checkSuperUser)
        self.serverWidget.clearWidgets.connect(self.clearAll)
        self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeWidget.customContextMenuRequested.connect(
            self.createMenuAssigned)

    def populateListWithDatabasesFromServer(self):
        '''
        Populates databases list from server
        '''
        dbList = []
        try:
            dbList = self.serverWidget.abstractDb.getEDGVDbsFromServer()
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))

        dbList.sort()
        for (dbname, dbversion) in dbList:
            item = QListWidgetItem(self.dbListWidget)
            item.setText(dbname + ' (EDGV v. ' + dbversion + ')')
            item.setData(Qt.UserRole, dbname)

    @pyqtSlot(bool)
    def on_closePushButton_clicked(self):
        '''
        Closes the dialog
        '''
        self.done(0)

    def renewDb(self):
        '''
        Renews the database
        '''
        if self.localDb:
            del self.localDb
            self.localDb = None

    def clearAll(self):
        '''
        Clears the database list
        '''
        self.dbListWidget.clear()
        self.treeWidget.clear()
        self.renewDb()

    def checkSuperUser(self):
        '''
        Checks if the user is a super user
        '''
        try:
            if self.serverWidget.abstractDb.checkSuperUser():
                self.populateListWithDatabasesFromServer()
            else:
                QMessageBox.warning(
                    self, self.tr('Info!'),
                    self.
                    tr('Connection refused. Connect with a super user to inspect server.'
                       ))
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))

    def createItem(self, parent, text, column):
        '''
        Creates a tree widget item
        '''
        item = QtGui.QTreeWidgetItem(parent)
        item.setFlags(QtCore.Qt.ItemIsEnabled)
        item.setText(column, text)
        return item

    @pyqtSlot(QListWidgetItem, QListWidgetItem)
    def on_dbListWidget_currentItemChanged(self, current, previous):
        '''
        Updates the information related with the database (e.g. users and roles for instance)
        '''
        self.treeWidget.clear()
        if not current:
            return
        self.localDb = self.dbFactory.createDbFactory('QPSQL')
        originalCon = self.serverWidget.abstractDb.makeOgrConn()
        self.localDb.connectDatabaseWithParameters(
            self.serverWidget.abstractDb.db.hostName(),
            self.serverWidget.abstractDb.db.port(),
            current.text().split(' ')[0],
            self.serverWidget.abstractDb.db.userName(),
            self.serverWidget.abstractDb.db.password())

        candidateUserList = []
        try:
            candidateUserList = self.localDb.getUsers()
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))

        for candidate in candidateUserList:
            installed, assigned = self.localDb.getUserRelatedRoles(candidate)
            if len(assigned) > 0:
                userItem = self.createItem(self.treeWidget.invisibleRootItem(),
                                           candidate, 0)
                for perm in assigned:
                    self.createItem(userItem, perm, 1)

    def createMenuAssigned(self, position):
        '''
        Creates a pop up menu
        '''
        menu = QMenu()
        item = self.treeWidget.itemAt(position)
        if item:
            menu.addAction(self.tr('Show properties'),
                           self.showAssignedProperties)
        menu.exec_(self.treeWidget.viewport().mapToGlobal(position))

    def showAssignedProperties(self):
        '''
        Shows information about the selected permissions model 
        '''
        permission = self.treeWidget.currentItem().text(1)
        dbname = self.dbListWidget.currentItem().text().split(' ')[0]

        permissionsDict = dict()
        try:
            permissionsDict = self.localDb.getRolePrivileges(
                permission, dbname)
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))

        dlg = PermissionProperties(permissionsDict)
        dlg.exec_()

    @pyqtSlot(bool)
    def on_dropDatabasePushButton_clicked(self):
        '''
        Drops a database and updates QSettings
        '''
        currentItem = self.dbListWidget.currentItem()
        if not currentItem:
            return
        if QtGui.QMessageBox.question(
                self, self.tr('Question'),
                self.tr('Do you really want to drop database: ') +
                currentItem.text().split(' ')[0], QtGui.QMessageBox.Ok
                | QtGui.QMessageBox.Cancel) == QtGui.QMessageBox.Cancel:
            return
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        localDbName = self.localDb.getDatabaseName()
        self.renewDb()
        try:
            self.serverWidget.abstractDb.dropDatabase(localDbName)
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(
                self, self.tr('Success!'),
                self.tr('Database ') + localDbName +
                self.tr(' dropped successfully!'))
            self.clearQSettings(localDbName)
        except Exception as e:
            QApplication.restoreOverrideCursor()
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
        self.clearAll()
        self.populateListWithDatabasesFromServer()

    @pyqtSlot(bool)
    def on_createViewsPushButton_clicked(self):
        '''
        Creates view button
        '''
        if not self.localDb:
            QMessageBox.critical(self, self.tr('Critical!'),
                                 self.tr('Select a database to create view'))
            return
        dlg = CreateView(self.localDb, self.dbListWidget.currentItem().text())
        dlg.exec_()
        pass

    def clearQSettings(self, database):
        '''
        Clear the database from QSettings
        '''
        name = self.serverWidget.serversCombo.currentText() + '_' + database
        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections/' + name)
        settings.remove('')
        settings.endGroup()

    @pyqtSlot(bool)
    def on_manageAuxStructPushButton_clicked(self):
        '''
        Opens the dialog to manage database auxiliar structure
        '''
        if not self.localDb:
            QMessageBox.critical(
                self, self.tr('Critical!'),
                self.tr('Select a database to manage auxiliar structure'))
            return
        dlg = ManageDBAuxiliarStructure(self.localDb)
        dlg.exec_()
        pass
예제 #43
0
class ConnectionWidget(QtGui.QWidget, FORM_CLASS):
    connectionChanged = pyqtSignal()
    problemOccurred = pyqtSignal(str)
    
    def __init__(self, parent = None):
        """Constructor."""
        super(ConnectionWidget, 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.setInitialState()
         
    def __del__(self):
        self.closeDatabase()

    def closeDatabase(self):
        if self.abstractDb:
            del self.abstractDb
            self.abstractDb = None

    def setInitialState(self):
        self.filename = ''
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        
        self.abstractDb = None
        self.isSpatialite = True
        self.tabWidget.setCurrentIndex(0)
        self.abstractDbFactory = DbFactory()
        self.utils = Utils()

        #populating the postgis combobox
        self.comboBoxPostgis.setCurrentIndex(0)
        self.populatePostGISConnectionsCombo()
        self.spatialiteFileEdit.setReadOnly(True)   
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setReadOnly(True)   
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setReadOnly(True)       

    @pyqtSlot(int)
    def on_comboBoxPostgis_currentIndexChanged(self):
        if self.comboBoxPostgis.currentIndex() > 0:
            self.postGISCrsEdit.setText('')
            self.postGISCrsEdit.setReadOnly(True)
            self.edgvPostgisVersionEdit.setText('')
            self.edgvPostgisVersionEdit.setReadOnly(True)  
            self.loadDatabase()
            self.connectionChanged.emit()
        
    @pyqtSlot(bool)
    def on_pushButtonOpenFile_clicked(self):  
        self.loadDatabase()
        if self.isDBConnected():
            self.connectionChanged.emit()
        
    @pyqtSlot(int)
    def on_tabWidget_currentChanged(self):
        self.filename = ''
        self.comboBoxPostgis.setCurrentIndex(0)
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.dbVersion = ''
        
        self.spatialiteFileEdit.setReadOnly(True)
        self.spatialiteFileEdit.setText(self.filename)
        self.postGISCrsEdit.setText('')
        self.postGISCrsEdit.setReadOnly(True)
        self.spatialiteCrsEdit.setText('')
        self.spatialiteCrsEdit.setReadOnly(True)   
        self.edgvSpatialiteVersionEdit.setText('')
        self.edgvSpatialiteVersionEdit.setReadOnly(True)
        self.edgvPostgisVersionEdit.setText('')
        self.edgvPostgisVersionEdit.setReadOnly(True)     
        
        
        #Setting the database type
        if self.tabWidget.currentIndex() == 0:
            self.isSpatialite = True
        else:
            self.isSpatialite = False

    def loadDatabase(self):
        self.closeDatabase()
        if self.isSpatialite:
            self.abstractDb = self.abstractDbFactory.createDbFactory('QSQLITE')
            self.abstractDb.connectDatabase()
            self.spatialiteFileEdit.setText(self.abstractDb.db.databaseName())
            self.edgvSpatialiteVersionEdit.setText(self.abstractDb.getDatabaseVersion())
                
        else:
            self.abstractDb = self.abstractDbFactory.createDbFactory('QPSQL')
            self.abstractDb.connectDatabase(self.comboBoxPostgis.currentText())
            self.edgvPostgisVersionEdit.setText(self.abstractDb.getDatabaseVersion())
        try:
            self.abstractDb.checkAndOpenDb()
            self.dbLoaded = True
            self.dbVersion = self.abstractDb.getDatabaseVersion()
            if self.dbVersion == '-1':
                self.problemOccurred.emit(self.tr('This is not a valid DsgTools database!'))
            else:
                self.setCRS()
        except Exception as e:
            QgsMessageLog.logMessage(e.args[0], "DSG Tools Plugin", QgsMessageLog.CRITICAL)    

    def setCRS(self):
        try:
            self.epsg = self.abstractDb.findEPSG()
            if self.epsg == -1:
                self.problemOccurred.emit(self.tr('Coordinate Reference System not set or invalid!'))
            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 populatePostGISConnectionsCombo(self):
        self.comboBoxPostgis.clear()
        self.comboBoxPostgis.addItem(self.tr('Select Database'))
        self.comboBoxPostgis.addItems(self.getPostGISConnections())
        
    def isDBConnected(self):
        return self.dbLoaded
        
    def getDBVersion(self):
        return self.abstractDb.getDatabaseVersion()
    
    def getQmlPath(self):
        return self.abstractDb.getQmlDir()
        
    @pyqtSlot(bool)
    def on_addConnectionButton_clicked(self):  
        newConnectionDialog =  ServerDBExplorer(self)
        retvalue = newConnectionDialog.exec_()
        self.populatePostGISConnectionsCombo()
        return retvalue
    
    def getPostGISConnections(self):
        settings = QSettings()
        settings.beginGroup('PostgreSQL/connections')
        currentConnections = settings.childGroups()
        settings.endGroup()
        return currentConnections
예제 #44
0
class ConnectionComboBox(DsgCustomComboBox):
    connectionChanged = pyqtSignal()
    dbChanged = pyqtSignal(AbstractDb)
    problemOccurred = pyqtSignal(str)
    def __init__(self, parent=None):
        super(ConnectionComboBox, self).__init__(parent)
        self.parent = parent
        self.abstractDb = None
        self.abstractDbFactory = DbFactory()
        self.serverAbstractDb = None
        self.displayDict = {'2.1.3':'EDGV 2.1.3', 'FTer_2a_Ed':'EDGV FTer 2a Ed', 'Non_EDGV':self.tr('Other database model')}
        self.lineEdit().setPlaceholderText(self.tr('Select a database'))
        self.currentIndexChanged.connect(self.loadDatabase)
        self.instantiateAbstractDb = False
    
    def closeDatabase(self):
        try:
            self.abstractDb.db.close()
            del self.abstractDb
            self.abstractDb = None
        except:
            self.abstractDb = None

    def clear(self):
        super(ConnectionComboBox, self).clear()
        self.closeDatabase()
    
    def setServerDb(self, serverAbstractDb):
        self.serverAbstractDb = serverAbstractDb
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        try:
            if self.serverAbstractDb:
                dbList = self.serverAbstractDb.getEDGVDbsFromServer(parentWidget = self.parent)
                dbList.sort()
                self.clear()
                self.addItem(self.tr('Select Database'))
                self.addItems(dbList)
            else:
                self.clear()
                self.abstractDb = None
                return
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
        QApplication.restoreOverrideCursor()
    
    def addItems(self, items):
        itemList = []
        if items == []:
            return
        elif isinstance(items[0], tuple) and len(items[0]) == 2:
            for item in items:
                if item[1] not in self.displayDict.keys():
                    version = item[1]
                else:
                    version = self.displayDict[item[1]]
                newText = item[0] + ' ({0})'.format(version)
                itemList.append(newText)
        if itemList == []:
            itemList = items
        super(ConnectionComboBox, self).addItems(itemList)
    
    def currentDb(self):
        if self.currentIndex() == 0:
            return None
        else:
            return self.currentText().split(' (')[0]
                
    def loadDatabase(self):
        """
        Loads the selected database
        """
        try:
            if self.serverAbstractDb and self.currentIndex() > 0:
                if not self.instantiateAbstractDb:
                    self.abstractDb = self.abstractDbFactory.createDbFactory('QPSQL')
                    (host, port, user, password) = self.serverAbstractDb.getDatabaseParameters()
                    dbName = self.currentText().split(' (')[0]
                    self.abstractDb.connectDatabaseWithParameters(host, port, dbName, user, password)
                    self.abstractDb.checkAndOpenDb()
                    self.dbChanged.emit(self.abstractDb)
        except Exception as e:
            self.closeDatabase()
            self.problemOccurred.emit(self.tr('A problem occurred! Check log for details.'))
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin", QgsMessageLog.CRITICAL)   
예제 #45
0
class CreateProfile(QtGui.QDialog, FORM_CLASS):
    profileCreated = pyqtSignal(str)
    
    def __init__(self, parent = None):
        """Constructor."""
        super(CreateProfile, 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.folder = os.path.join(os.path.dirname(__file__), 'profiles')

        self.abstractDb = None
        self.abstractDbFactory = DbFactory()

        self.populateTreeDict()
        
    def __del__(self):
        if self.abstractDb:
            del self.abstractDb
            self.abstractDb = None
        
    def getDbInfo(self):
        currentPath = os.path.dirname(__file__)
        if self.versionCombo.currentText() == '2.1.3':
            edgvPath = os.path.join(currentPath, '..', 'DbTools', 'SpatialiteTool', 'template', '213', 'seed_edgv213.sqlite')
        elif self.versionCombo.currentText() == 'FTer_2a_Ed':
            edgvPath = os.path.join(currentPath, '..', 'DbTools', 'SpatialiteTool', 'template', 'FTer_2a_Ed', 'seed_edgvfter_2a_ed.sqlite')

        self.abstractDb = self.abstractDbFactory.createDbFactory('QSQLITE')
        self.abstractDb.connectDatabase(edgvPath)

        try:
            self.abstractDb.checkAndOpenDb()
        except Exception as e:
            print e.args[0]

    def populateTreeDict(self):
        self.getDbInfo()

        tables = self.abstractDb.getTablesFromDatabase()
        
        self.profile = dict()
        categories = dict()
        for tableName in tables:
            #proceed only for edgv tables
            if tableName.split("_")[-1] == "p" or tableName.split("_")[-1] == "l" or tableName.split("_")[-1] == "a" or tableName.split("_")[0] == 'complexos':
                layerName = tableName.split('_')[0]+'.'+'_'.join(tableName.split('_')[1::])
                split = tableName.split('_')
                
                if len(split) < 2:
                    continue
                
                schema = split[0]
                category = split[1]
                if schema not in categories.keys():
                    categories[schema] = dict()
                    
                if category not in categories[schema].keys():
                    categories[schema][category] = dict()

                if layerName not in categories[schema][category]:
                    categories[schema][category][layerName] = dict()
                    categories[schema][category][layerName]['read'] = '0'
                    categories[schema][category][layerName]['write'] = '0'
                    
        self.profile['database'+'_'+self.versionCombo.currentText()] = categories

    @pyqtSlot()
    def on_buttonBox_accepted(self):
        if not self.lineEdit.text():
            QtGui.QMessageBox.warning(self, self.tr('Warning!'), self.tr('Fill the profile name!'))
            return
        else:
            profileName = self.lineEdit.text()
            
        path = os.path.join(self.folder, profileName+'.json')
        
        with open(path, 'w') as outfile:
            json.dump(self.profile, outfile, sort_keys=True, indent=4)
        self.profileCreated.emit(profileName)

    @pyqtSlot(int)
    def on_versionCombo_currentIndexChanged(self):
         self.populateTreeDict()
예제 #46
0
class BatchDbManager(QtGui.QDialog, FORM_CLASS):
    EDGV213, EDGV_FTer_2a_Ed, Non_EDGV = range(3)
    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':[], '3.0':[]}
        self.correspondenceDict = {self.tr('Load Database Model EDGV Version 2.1.3'):'2.1.3', self.tr('Load Database Model EDGV Version 3.0'):'3.0', self.tr('Load Database Model EDGV Version FTer_2a_Ed'):'FTer_2a_Ed',self.tr('Load Other Database Models'):'Non_EDGV'}

    @pyqtSlot(bool)
    def on_closePushButton_clicked(self):
        self.done(0)
    
    def showTabs(self, show = True):
        if show:
            self.tabWidget.show()
        else:
            self.tabWidget.hide()

    def populateListWithDatabasesFromServer(self):
        try:
            dbList = self.serverWidget.abstractDb.getEDGVDbsFromServer(parentWidget = self)
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))

        dbList.sort()
        for (dbname, dbversion) in dbList:
            if dbversion not in self.dbDict.keys():
                dbversion = 'Non_EDGV'
            if dbname not in self.dbDict[dbversion]:
                self.dbDict[dbversion].append(dbname)

    def setDatabases(self):
        self.populateListWithDatabasesFromServer()
    
    @pyqtSlot(int)
    def on_edgvComboFilter_currentIndexChanged(self, idx):
        if idx != -1 and idx != 0:
            self.dbsCustomSelector.setInitialState(self.dbDict[self.correspondenceDict[self.edgvComboFilter.currentText()]])

    def checkSuperUser(self):
        try:
            if self.serverWidget.abstractDb.checkSuperUser():
                self.setDatabases()
            else:
                QMessageBox.warning(self, self.tr('Info!'), self.tr('Connection refused. Connect with a super user to inspect server.'))
        except Exception as e:
            QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))

    def getSelectedDbList(self):
        return self.dbsCustomSelector.toLs
    
    def instantiateAbstractDbs(self, instantiateTemplates = False):
        dbsDict = dict()
        selectedDbNameList = self.getSelectedDbList()
        if instantiateTemplates:
            for templateName in ['template_edgv_213', 'template_edgv_fter_2a_ed', 'template_edgv_3']:
                if templateName not in selectedDbNameList:
                    if templateName != 'dsgtools_admindb':
                        selectedDbNameList.append(templateName)
        for dbName in selectedDbNameList:
            localDb = self.dbFactory.createDbFactory('QPSQL')
            localDb.connectDatabaseWithParameters(self.serverWidget.abstractDb.db.hostName(), self.serverWidget.abstractDb.db.port(), dbName, self.serverWidget.abstractDb.db.userName(), self.serverWidget.abstractDb.db.password())
            dbsDict[dbName] = localDb
        return dbsDict

    def closeAbstractDbs(self, dbsDict):
        exceptionDict = dict()
        for dbName in dbsDict.keys():
            try:
                dbsDict[dbName].db.close()
            except Exception as e:
                exceptionDict[dbName] =  ':'.join(e.args)
        return exceptionDict

    def outputMessage(self, header, successList, exceptionDict):
        msg = header
        if len(successList) > 0:
            msg += self.tr('\nSuccessful databases: ')
            msg +=', '.join(successList)
        msg += self.logInternalError(exceptionDict)
        QMessageBox.warning(self, self.tr('Operation Complete!'), msg)
    
    def logInternalError(self, exceptionDict):
        msg = ''
        errorDbList = exceptionDict.keys()
        if len(errorDbList)> 0:
            msg += self.tr('\nDatabases with error:')
            msg+= ', '.join(errorDbList)
            msg+= self.tr('\nError messages for each database were output in qgis log.')
            for errorDb in errorDbList:
                QgsMessageLog.logMessage(self.tr('Error for database ')+ errorDb + ': ' +exceptionDict[errorDb].decode('utf-8'), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
        return msg 

    @pyqtSlot(bool)
    def on_dropDatabasePushButton_clicked(self):
        selectedDbNameList = self.getSelectedDbList()
        if len(selectedDbNameList) == 0:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Please select one or more databases to drop!'))
        if QtGui.QMessageBox.question(self, self.tr('Question'), self.tr('Do you really want to drop databases: ')+', '.join(selectedDbNameList), QtGui.QMessageBox.Ok|QtGui.QMessageBox.Cancel) == QtGui.QMessageBox.Cancel:
            return
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchDropDbs(selectedDbNameList)
        QApplication.restoreOverrideCursor()
        self.setDatabases()
        header = self.tr('Drop operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)
        self.dbsCustomSelector.setInitialState(self.dbsCustomSelector.fromLs)

    @pyqtSlot(bool)
    def on_upgradePostgisPushButton_clicked(self):
        selectedDbNameList = self.getSelectedDbList()
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchUpgradePostgis(selectedDbNameList)
        QApplication.restoreOverrideCursor()
        self.setDatabases()
        header = self.tr('Upgrade Posgtis operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)

    def batchUpgradePostgis(self, dbList):
        exceptionDict = dict()
        successList = []
        dbsDict = self.instantiateAbstractDbs(instantiateTemplates = True)
        self.closeAbstractDbs(dbsDict)
        for dbName in dbsDict.keys():
            try:
                if self.serverWidget.abstractDb.checkIfTemplate(dbName):
                    self.serverWidget.abstractDb.setDbAsTemplate(dbName = dbName, setTemplate = False)
                    dbsDict[dbName].upgradePostgis()
                    self.serverWidget.abstractDb.setDbAsTemplate(dbName = dbName, setTemplate = True)
                    successList.append(dbName)
                else:
                    dbsDict[dbName].upgradePostgis()
                    successList.append(dbName)
            except Exception as e:
                exceptionDict[dbName] =  ':'.join(e.args)
        return successList, exceptionDict

    def batchDropDbs(self, dbList):
        exceptionDict = dict()
        successList = []
        dbsDict = self.instantiateAbstractDbs()
        self.closeAbstractDbs(dbsDict)
        for dbName in dbList:
            try:
                self.serverWidget.abstractDb.dropDatabase(dbName)
                successList.append(dbName)
            except Exception as e:
                exceptionDict[dbName] =  ':'.join(e.args)
        return successList, exceptionDict
    
    @pyqtSlot(bool)
    def on_importStylesPushButton_clicked(self):
        dbsDict = self.instantiateAbstractDbs()
        exceptionDict = dict()
        versionList = []
        
        for dbName in dbsDict.keys():
            try:
                version = dbsDict[dbName].getDatabaseVersion()
                if version not in versionList:
                    versionList.append(version)
            except Exception as e:
                exceptionDict[dbName] = ':'.join(e.args)
        if len(exceptionDict.keys())>0:
            self.logInternalError(exceptionDict)
        if len(versionList) > 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Multiple edgv versions are not allowed!'))
            return
        styleDir = self.getStyleDir(versionList)
        styleList = self.getStyleList(styleDir)
        dlg = SelectStyles(styleList)
        dlg.exec_()
        selectedStyles = dlg.selectedStyles
        if not selectedStyles:
            return
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchImportStyles(dbsDict, styleDir, selectedStyles, versionList[0])
        QApplication.restoreOverrideCursor()
        header = self.tr('Import operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)
        self.populateStylesInterface()
        closeExceptionDict = self.closeAbstractDbs(dbsDict)
        self.logInternalError(closeExceptionDict)            
            
    
    def getStyleList(self, styleDir):
        #TODO: Reimplement
        styleList = []
        version = None
        if os.path.basename(styleDir) in ['edgv_213','edgv_FTer_2a_Ed', 'edgv_3']:
            version = os.path.basename(styleDir)
        else:
            parentFolder = os.path.dirname(styleDir)
            version = os.path.basename(parentFolder)
        for style in os.walk(styleDir).next()[1]:
            styleList.append('/'.join([version,style]))
        if len(styleList) == 0:
            styleList = [version+'/'+os.path.basename(styleDir)]
        return styleList
    
    def batchImportStyles(self, dbsDict, styleDir, styleList, version):
        exceptionDict = dict()
        successList = []
        for dbName in dbsDict.keys():
            for style in styleList:
                currentStyleFilesDir = "{0}/{1}".format(styleDir, style.split("/")[1])
                fileList = os.listdir(currentStyleFilesDir)
                # iterate over the list of files and check if there are non-QML files
                onlyQml = bool(sum([int(".qml" in file.lower()) for file in fileList]))
                try:
                    if not onlyQml:
                        raise Exception(self.tr("There are non-QML files in directory {0}.").format(currentStyleFilesDir))
                    dbsDict[dbName].importStylesIntoDb(style)
                    successList.append(dbName)
                except Exception as e:
                    errors = []
                    for arg in e.args:
                        if isinstance(arg, basestring):
                            s = '{}'.format(arg.encode('utf-8'))
                        else:
                            s = str(arg)
                        errors.append(s)
                    exceptionDict[dbName] =  ':'.join(errors)
        return successList, exceptionDict
    
    def getStyleDir(self, versionList):
        currentPath = os.path.join(os.path.dirname(__file__),'..','Styles', self.serverWidget.abstractDb.versionFolderDict[versionList[0]])
        return currentPath
    
    def getStylesFromDbs(self, perspective = 'style'):
        '''
        Returns a dict of styles in a form acording to perspective:
            if perspective = 'style'    : [styleName][dbName][tableName] = timestamp
            if perspective = 'database' : [dbName][styleName][tableName] = timestamp 
        '''
        dbsDict = self.instantiateAbstractDbs()
        allStylesDict = dict()
        exceptionDict = dict()
        for dbName in dbsDict.keys():
            try:
                newDict =dbsDict[dbName].getAllStylesDict(perspective)
                allStylesDict = self.utils.mergeDict(newDict, allStylesDict)
            except Exception as e:
                exceptionDict[dbName] = ':'.join(e.args)
        if len(exceptionDict.keys())>0:
            self.logInternalError(exceptionDict)
        return allStylesDict

    def createItem(self, parent, text, column):
        item = QtGui.QTreeWidgetItem(parent)
        item.setText(column, text)
        return item

    def populateStylesInterface(self):
        self.stylesTreeWidget.clear()
        allStylesDict = self.getStylesFromDbs()
        rootNode = self.stylesTreeWidget.invisibleRootItem()
        for styleName in allStylesDict.keys():
            parentStyleItem = self.createItem(rootNode, styleName, 0)
            dbList = allStylesDict[styleName].keys()
            parentTimeList = []
            for dbName in dbList:
                dbItem = self.createItem(parentStyleItem, dbName, 1)
                tableList = allStylesDict[styleName][dbName].keys()
                tableList.sort()
                timeList = []
                for table in tableList:
                    tableItem = self.createItem(dbItem, table, 2)
                    timeStamp = allStylesDict[styleName][dbName][table].toString()
                    timeList.append(timeStamp)
                    tableItem.setText(3,allStylesDict[styleName][dbName][table].toString())
                parentTimeList.append(max(timeList))
                dbItem.setText(3,max(timeList))
    
    @pyqtSlot(bool)
    def on_deleteStyles_clicked(self):
        dbsDict = self.instantiateAbstractDbs()
        styleDict = self.getStylesFromDbs()
        styleList = styleDict.keys()
        dlg = SelectStyles(styleList)
        dlg.exec_()
        selectedStyles = dlg.selectedStyles
        if not selectedStyles:
            return
        else:
            removeStyleDict = { style : styleDict[style] for style in selectedStyles }
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchDeleteStyles(dbsDict, removeStyleDict)
        QApplication.restoreOverrideCursor()
        header = self.tr('Delete operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)
        self.populateStylesInterface()
        closeExceptionDict = self.closeAbstractDbs(dbsDict)
        self.logInternalError(closeExceptionDict)       
    
    def batchDeleteStyles(self, dbsDict, styleDict):
        exceptionDict = dict()
        successList = []
        for style in styleDict.keys():
            for dbName in styleDict[style].keys():
                try:
                    dbsDict[dbName].deleteStyle(style)
                    successList.append(dbName)
                except Exception as e:
                    exceptionDict[dbName] =  ':'.join(e.args)
        return successList, exceptionDict
    
    def getSQLFile(self):
        fd = QFileDialog()
        filename = fd.getOpenFileName(caption=self.tr('Select a SQL file'),filter=self.tr('sql file (*.sql)'))
        return filename
    
    @pyqtSlot(bool)
    def on_customizeFromSQLFilePushButton_clicked(self):
        dbsDict = self.instantiateAbstractDbs()
        sqlFilePath = self.getSQLFile()
        if sqlFilePath == '':
            return
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        successList, exceptionDict = self.batchCustomizeFromSQLFile(dbsDict, sqlFilePath)
        QApplication.restoreOverrideCursor()
        header = self.tr('Customize from SQL file operation complete. \n')
        self.outputMessage(header, successList, exceptionDict)
        closeExceptionDict = self.closeAbstractDbs(dbsDict)
        self.logInternalError(closeExceptionDict)
    
    def batchCustomizeFromSQLFile(self, dbsDict, sqlFilePath):
        exceptionDict = dict()
        successList = []
        for dbName in dbsDict.keys():
            try:
                dbsDict[dbName].runSqlFromFile(sqlFilePath)
                successList.append(dbName)
            except Exception as e:
                exceptionDict[dbName] =  ':'.join(e.args)
        return successList, exceptionDict

    def populateOtherInterfaces(self):
        dbsDict = self.instantiateAbstractDbs()
        if self.edgvComboFilter.currentIndex() != 0:
            edgvVersion = self.correspondenceDict[self.edgvComboFilter.currentText()]
            self.permissionWidget.setParameters(self.serverWidget.abstractDb, dbsDict, edgvVersion)
            # self.customizationManagerWidget.setParameters(self.serverWidget.abstractDb, edgvVersion, dbsDict = dbsDict)
            self.fieldToolBoxConfigManagerWidget.setParameters(self.serverWidget.abstractDb, edgvVersion, dbsDict = dbsDict)
            self.earthCoverageManagerWidget.setParameters(self.serverWidget.abstractDb, edgvVersion, dbsDict = dbsDict)
예제 #47
0
                self.tr('Process parameters setter for process {0}').format(
                    process))
            if dlg.exec_() == 0:
                return -1
            # get parameters
            params = dlg.values
            # adjusting the parameters in the process
            currProc.setParameters(params)
        #check status
        QgsMessageLog.logMessage('Process %s Log:\n' % currProc.getName(),
                                 "DSG Tools Plugin", QgsMessageLog.CRITICAL)
        ret = currProc.execute()  #run bitch run!
        #status = currProc.getStatus() #must set status
        QgsMessageLog.logMessage(
            'Process ran with status %s\n' % currProc.getStatusMessage(),
            "DSG Tools Plugin", QgsMessageLog.CRITICAL)
        currProc.logTotalTime()
        #checking for existing post process
        postProcessName = currProc.postProcess()
        if postProcessName:
            self.executeProcess(postProcessName)
        return ret


if __name__ == '__main__':
    from DsgTools.Factories.DbFactory.dbFactory import DbFactory
    abstractDb = DbFactory().createDbFactory('QPSQL')
    manager = ValidationManager(abstractDb)
    print manager
    pass
예제 #48
0
class ExploreServerWidget(QtGui.QWidget, FORM_CLASS):
    abstractDbLoaded = pyqtSignal()
    serverAbstractDbLoaded = pyqtSignal(AbstractDb)
    clearWidgets = pyqtSignal()
    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.superNeeded = False
        self.dbFactory = DbFactory()
        self.abstractDb = None

    def getServers(self):
        """
        Gets server from QSettings
        """
        settings = QSettings()
        settings.beginGroup('PostgreSQL/servers')
        currentConnections = settings.childGroups()
        settings.endGroup()
        return currentConnections
    
    def getServerConfiguration(self, name):
        """
        Gets server configuration
        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 browseServer(self, dbList, host, port, user, password):
        """
        Browses server for EDGV databases
        dbList: databases list
        host: server host ip address
        port: server port
        user: user name
        password: password
        """
        canLoad = True
        if self.superNeeded:
            canLoad = False
            try:
                if self.serverWidget.abstractDb.checkSuperUser():
                    canLoad = True
                else:
                    QMessageBox.warning(self, self.tr('Info!'), self.tr('Connection refused. Connect with a super user to inspect server.'))
                    return []
            except Exception as e:
                QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
        if canLoad:
            progress = ProgressWidget(1,len(dbList),self.tr('Loading databases from server... '), parent = self)
            progress.initBar()
            gen = self.factory.createSqlGenerator(False)
            edvgDbList = []
            for database in dbList:
                db = self.getPostGISDatabaseWithParams(database, host, port, user, password)
                if not db.open():
                    qgis.utils.iface.messageBar().pushMessage('DB :'+database+'| msg: '+db.lastError().databaseText(), level=QgsMessageBar.CRITICAL)
    
                query = QSqlQuery(db)
                if query.exec_(gen.getEDGVVersion()):
                    while query.next():
                        version = query.value(0)
                        if version:
                            edvgDbList.append((database, version))
                progress.step()
            return edvgDbList
    
    def getDbsFromServer(self, name):
        """
        Gets server databases
        name: server name
        """
        gen = self.factory.createSqlGenerator(False)
        
        (host, port, user, password) = self.getServerConfiguration(name)
        database = 'postgres'
        
        db = self.getPostGISDatabaseWithParams(database, host, port, user, password)
        if not db.open():
            QgsMessageLog.logMessage(db.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            QMessageBox.critical(self.iface.mainWindow(), self.tr('Critical'), self.tr('A problem occurred! Check log for details.'))
        
        query = QSqlQuery(gen.getDatabasesFromServer(), db)
        if not query.isActive():
            QMessageBox.critical(self.iface.mainWindow(), self.tr('Critical'), self.tr("Problem executing query: ")+query.lastError().text())
            
        dbList = []
        while query.next():
            dbList.append(query.value(0))
        return self.browseServer(dbList, host, port, user, password)
    
    @pyqtSlot(bool)
    def on_createNewServerPushButton_clicked(self):  
        """
        Opens the View Server dialog
        """
        createNewServer = ViewServers(self)
        result = createNewServer.exec_()
        self.populateServersCombo()

    def populateServersCombo(self):
        """
        Populates the server name combo box
        """
        self.serversCombo.clear()
        self.serversCombo.addItem(self.tr('Select Server'))
        currentConnections = self.getServers()
        for connection in currentConnections:
            (host, port, user, password) = self.getServerConfiguration(connection)
            self.serversCombo.addItem('{3} ({0}@{1}:{2})'.format(user, host, port, connection))
    
    @pyqtSlot(int)
    def on_serversCombo_currentIndexChanged(self):
        """
        Updates the server databases
        """
        self.clearWidgets.emit()
        if self.serversCombo.currentIndex() != 0:
            self.abstractDb = self.dbFactory.createDbFactory('QPSQL')
            if not self.abstractDb:
                QMessageBox.critical(self.iface.mainWindow(), self.tr('Critical'), self.tr('A problem occurred! Check log for details.'))
                return
            (host, port, user, password) = self.abstractDb.getServerConfiguration(self.serversCombo.currentText().split('(')[0][0:-1])
            if host or port or user:
                self.abstractDb.connectDatabaseWithParameters(host, port, 'postgres', user, password)
                if self.superNeeded:
                    try:
                        if not self.abstractDb.checkSuperUser():
                            QMessageBox.warning(self, self.tr('Info!'), self.tr('Connection refused. Connect with a super user to inspect server.'))
                            self.serversCombo.setCurrentIndex(0)
                            return
                    except Exception as e:
                        QMessageBox.critical(self, self.tr('Critical!'), ':'.join(e.args))
                self.abstractDbLoaded.emit()
        else:
            try:
                if self.abstractDb:
                    self.abstractDb.__del__()
                    self.abstractDb = None
            except:
                pass
        self.serverAbstractDbLoaded.emit(self.abstractDb)
    
    def getServerParameters(self):
        """
        Gets postgis server parameters
        """
        if self.serversCombo.currentIndex() != 0:
            return self.abstractDb.getServerConfiguration(self.serversCombo.currentText().split('(')[0][0:-1])
        else:
            return (None, None, None, None)
    
    def clearAll(self):
        """
        Resets the widget
        """
        try:
            if self.abstractDb:
                self.abstractDb.__del__()
                self.abstractDb = None
        except:
            pass
        self.serversCombo.setCurrentIndex(0)
예제 #49
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.iface = iface
        
        self.dbButton.clicked.connect(self.getDataSources)
        self.dbCombo.activated.connect(self.updateComplexClass)
        self.complexCombo.activated.connect(self.loadAssociatedFeatures)
        self.iface.newProjectCreated.connect(self.clearDock)

        self.abstractDb = None
        self.databases = None
        self.abstractDbFactory = DbFactory()

    def __del__(self):
        self.renewDb
            
    def renewDb(self):
        if self.abstractDb:
            del self.abstractDb
            self.abstractDb = None

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

    #verificar se é necessario
    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)

        if dataSourceUri.password() != '':
            return (dataSourceUri.username(), dataSourceUri.password())

        connInfo = dataSourceUri.connectionInfo()
        (success, user, passwd ) = QgsCredentials.instance().get(connInfo, dataSourceUri.username(), 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)
        else:
            return (None, None)

        return (user, passwd)

    def updateComplexClass(self):
        self.renewDb()

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

        dbName = self.dbCombo.currentText()
        
        (dataSourceUri, credentials) = self.databases[dbName]
        #verifying the connection type
        if self.isSpatialiteDatabase(dbName):
            self.abstractDb = self.abstractDbFactory.createDbFactory('QSQLITE')
            self.abstractDb.connectDatabase(dataSourceUri.database())
        else:
            self.abstractDb = self.abstractDbFactory.createDbFactory('QPSQL')
            
            database = dbName
            host = dataSourceUri.host()
            port = int(dataSourceUri.port())
            user = credentials[0]
            password = credentials[1]
            
            self.abstractDb.connectDatabaseWithParameters(host, port, database, user, password)
        try:
            self.abstractDb.checkAndOpenDb()
            self.populateComboBox()
        except Exception as e:
            QMessageBox.critical(self.iface.mainWindow(), self.tr("Critical!"), e.args[0])

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

        complexClasses = self.abstractDb.listComplexClassesFromDatabase()
        self.complexCombo.addItems(complexClasses)

    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.keys():
                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
        dlg = ManageComplexDialog(self.iface, self.abstractDb, self.complexCombo.currentText())
        #connects a signal to update the tree widget when done
        QObject.connect(dlg, SIGNAL(("tableUpdated()")), self.loadAssociatedFeatures)
        #connects a signal to disassociate features from complex before removal
        QObject.connect(dlg, SIGNAL(("markedToRemove( PyQt_PyObject )")), self.disassociateFeatures)
        result = 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 and i == 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 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)
        link_column = self.abstractDb.obtainLinkColumn(complex, aggregated_class)

        #getting the layer the needs to be updated
        aggregated_layer = None
        layers = self.iface.mapCanvas().layers()
        for layer in layers:
            #in case of spatialite databases when a complex class is added as a layer it's name has 'complexos_'
            if layer.name() == aggregated_class or layer.name() == 'complexos_'+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)
        link_column = self.abstractDb.obtainLinkColumn(complex, aggregated_class)

        #getting the layer the needs to be updated
        aggregated_layer = None
        layers = self.iface.mapCanvas().layers()
        for layer in layers:
            #in case of spatialite databases when a complex class is added as a layer it's name has 'complexos_'
            if layer.name() == aggregated_class or layer.name() == 'complexos_'+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.abstractDb.isComplexClass(aggregated_class):
            try:
                self.abstractDb.disassociateComplexFromComplex(aggregated_class, link_column, id)
            except Exception as e:
                QMessageBox.critical(self.iface.mainWindow(), self.tr("Critical!"), e.args[0])
        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})

    @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()

        associatedDict = self.abstractDb.loadAssociatedFeatures(complex)

        for name in associatedDict.keys():
            for complex_uuid in associatedDict[name].keys():
                self.addAssociatedFeature(str(complex), str(name), complex_uuid, None, None)
                for aggregated_class in associatedDict[name][complex_uuid]:
                    for ogc_fid in associatedDict[name][complex_uuid][aggregated_class]:
                        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 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()

        #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.abstractDb.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