示例#1
0
 def __init__(self, abstractDb, uiParameterJsonDict=None, parent=None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.abstractDb = abstractDb
     self.setupUi(self)
     self.jsonBuilder = CustomJSONBuilder()
     self.populateSchemaCombo()
     self.hideWidgetList([
         self.singleValueLabel, self.singleValueComboBox,
         self.actionComboBox
     ])
     self.singleAttribute = True
     self.filterCustomSelectorWidget.setTitle(
         self.tr('Select filter values'))
     self.populateSingleValue.connect(self.populateWidgetWithSingleValue)
     self.populateListValue.connect(self.populateWidgetWithListValue)
     geomTypeDict = self.abstractDb.getGeomTypeDict()
     geomDict = self.abstractDb.getGeomDict(geomTypeDict)
     self.domainDict = self.abstractDb.getDbDomainDict(geomDict)
     self.inhTree = self.abstractDb.getInheritanceTreeDict()
     self.utils = Utils()
     self.actionDict = {
         self.tr('Add to Filter (Leave empty if filter is empty)'):
         'addEmpty',
         self.tr('Add to Filter (Add value to empty filter)'): 'add',
         self.tr('Remove from Filter'): 'remove'
     }
     self.populateFromUiParameterJsonDict(uiParameterJsonDict)
示例#2
0
 def __init__(self):
     super(AbstractDb,self).__init__()
     self.conversionTypeDict = dict({'QPSQL':'postgis','QSQLITE':'spatialite'})
     self.utils = Utils()
     self.signals = DbSignals()
     self.slotConnected = False
     pass
示例#3
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'
     }
 def __init__(self, genericDbManager = None, parent = None):
     """
     Constructor
     """
     super(GenericManagerWidget, self).__init__(parent)
     self.setupUi(self)
     self.genericDbManager = genericDbManager
     self.versionDict = {'2.1.3':1, 'FTer_2a_Ed':2, 'Non_Edgv':3}
     self.textDict = {'EarthCoverage':self.tr('Earth Coverage'), 
                         'Customization':self.tr('Customization'), 
                         'Style':self.tr('Style'), 
                         'ValidationConfig':self.tr('Validation'), 
                         'FieldToolBoxConfig':self.tr('Field Toolbox Configuration'),
                         'Permission':self.tr('Permissions')}
     self.captionDict = {'EarthCoverage':self.tr('Earth Coverage'), 
                         'Customization':self.tr('Customization'), 
                         'Style':self.tr('Style'), 
                         'ValidationConfig':self.tr('Validation'), 
                         'FieldToolBoxConfig':self.tr('Reclassification Setup Files'),
                         'Permission':self.tr('Select a dsgtools permission profile')}
     self.filterDict = {'EarthCoverage':self.tr('Earth Coverage Setup File (*.dsgearthcov)'), 
                         'Customization':self.tr('DsgTools Customization File (*.dsgcustom)'), 
                         'Style':self.tr('DsgTools Styles File (*.dsgstyle)'), 
                         'ValidationConfig':self.tr('DsgTools Validation Configuration File (*.dsgvalidcfg)'), 
                         'FieldToolBoxConfig':self.tr('Reclassification Setup Files (*.reclas)'),
                         'Permission':self.tr('DsgTools Permission Profile File (*.dsgperm)')}
     self.widgetName = self.textDict[self.getWhoAmI()]
     self.genericDict = None
     self.setComponentsEnabled(False)
     self.utils = Utils()
     self.setHeaders()
     self.setButtons()
     self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
     self.treeWidget.customContextMenuRequested.connect(self.createMenuAssigned)
示例#5
0
 def __init__(self, customNumber=None, parent=None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.fromLs = []
     self.toLs = []
     self.utils = Utils()
     self.setupUi(self)
示例#6
0
 def __init__(self, iface, parent=None, parentMenu=None):
     """
     Constructor
     """
     super(DsgToolsOpInstaller, self).__init__()
     self.iface = iface
     self.parentMenu = parentMenu
     self.utils = Utils()
     self.parent = parent
     self.icon_path = ':/plugins/DsgTools/icons/militarySimbology.png'
示例#7
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()
示例#8
0
 def __init__(self, iface, abstractDb, loadCentroids):
     """Constructor."""
     super(EDGVLayerLoader, self).__init__()
     
     self.abstractDb = abstractDb
     self.uri = QgsDataSourceURI() 
     self.iface = iface
     self.utils = Utils()
     self.logErrorDict = dict()
     self.errorLog = ''
     self.geomTypeDict = self.abstractDb.getGeomTypeDict(loadCentroids)
     self.geomDict = self.abstractDb.getGeomDict(self.geomTypeDict)
     self.correspondenceDict = {'POINT':'Point', 'MULTIPOINT':'Point', 'LINESTRING':'Line','MULTILINESTRING':'Line', 'POLYGON':'Area', 'MULTIPOLYGON':'Area'}
示例#9
0
 def __init__(self, serverAbstractDb, dbDict, edgvVersion, parentWidget = None):
     super(GenericDbManager,self).__init__()
     self.parentWidget = parentWidget
     self.dbDict = dbDict
     self.serverAbstractDb = serverAbstractDb
     self.adminDb = self.instantiateAdminDb(serverAbstractDb)
     self.utils = Utils()
     self.extensionDict = {'EarthCoverage':'.dsgearthcov', 
                 'Customization':'.dsgcustom', 
                 'Style':'.dsgstyle', 
                 'ValidationConfig':'.dsgvalidcfg', 
                 'FieldToolBoxConfig':'.reclas',
                 'Permission':'.dsgperm'}
     self.edgvVersion = edgvVersion
 def __init__(self, customizationName, abstractDb, edgvVersion, customizationManager, customJsonDict = None, parent = None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.setupUi(self)
     self.customizationManager = customizationManager
     self.abstractDb = abstractDb
     self.edgvVersion = edgvVersion
     self.customizationName = customizationName
     self.contentsDict = dict()
     self.populateCustomizationCombo()
     self.setWidgetsEnabled(True)
     self.utils = Utils()
     if customJsonDict:
         self.createWidgetsFromCustomJsonDict(customJsonDict)
    def insertFrameIntoLayer(self,reprojected):
        self.utils = Utils()
        self.dbVersion = self.utils.getDatabaseVersion(self.db)
        self.qmlPath = self.utils.getQmlDir(self.db)

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

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

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

        bbox = self.iface.mapCanvas().mapSettings().layerToMapCoordinates(layer, bbox)
        self.iface.mapCanvas().setExtent(bbox)
        self.iface.mapCanvas().refresh()
示例#12
0
 def __init__(self, iface, parent=None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.iface = iface
     self.utils = Utils()
     self.setupUi(self)
     self.layerFactory = LayerLoaderFactory()
     self.customServerConnectionWidget.postgisCustomSelector.setTitle(
         self.tr('Select Databases'))
     self.customServerConnectionWidget.spatialiteCustomSelector.setTitle(
         self.tr('Selected Spatialites'))
     self.layersCustomSelector.setTitle(
         self.tr('Select layers to be loaded'))
     self.customServerConnectionWidget.dbDictChanged.connect(
         self.updateLayersFromDbs)
     self.customServerConnectionWidget.resetAll.connect(self.resetInterface)
     self.customServerConnectionWidget.styleChanged.connect(
         self.populateStyleCombo)
     self.headerList = [
         self.tr('Category'),
         self.tr('Layer Name'),
         self.tr('Geometry\nColumn'),
         self.tr('Geometry\nType'),
         self.tr('Layer\nType')
     ]
     self.layersCustomSelector.setHeaders(self.headerList)
     self.customServerConnectionWidget.postgisEdgvComboFilter.currentIndexChanged.connect(
         self.layersCustomSelector.setInitialState)
     self.customServerConnectionWidget.spatialiteEdgvComboFilter.currentIndexChanged.connect(
         self.layersCustomSelector.setInitialState)
     self.customServerConnectionWidget.serverConnectionTab.currentChanged.connect(
         self.layersCustomSelector.setInitialState)
     self.lyrDict = dict()
示例#13
0
 def __init__(self, customNumber = None, parent = None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.fromLs = []
     self.toLs = []
     self.utils = Utils()
     self.setupUi(self)
示例#14
0
 def __init__(self):
     '''
     Constructor
     '''
     super(AbstractDb, self).__init__()
     self.conversionTypeDict = dict({
         'QPSQL': 'postgis',
         'QSQLITE': 'spatialite'
     })
     self.utils = Utils()
     self.signals = DbSignals()
     self.slotConnected = False
     self.versionFolderDict = dict({
         '2.1.3': 'edgv_213',
         'FTer_2a_Ed': 'edgv_FTer_2a_Ed'
     })
     self.utmGrid = UtmGrid()
示例#15
0
 def __init__(self):
     '''
     Constructor
     '''
     super(AbstractDb,self).__init__()
     self.conversionTypeDict = dict({'QPSQL':'postgis','QSQLITE':'spatialite'})
     self.utils = Utils()
     self.signals = DbSignals()
     self.slotConnected = False
     self.versionFolderDict = dict({'2.1.3':'edgv_213','FTer_2a_Ed':'edgv_FTer_2a_Ed','3.0':'3'})
     self.utmGrid = UtmGrid()
示例#16
0
 def __init__(self, abstractDb, uiParameterJsonDict = None, parent = None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.abstractDb = abstractDb
     self.setupUi(self)
     self.jsonBuilder = CustomJSONBuilder()
     self.populateSchemaCombo()
     geomTypeDict = self.abstractDb.getGeomTypeDict()
     geomDict = self.abstractDb.getGeomDict(geomTypeDict)
     self.domainDict = self.abstractDb.getDbDomainDict(geomDict)
     self.utils = Utils()
     self.populateFromUiParameterJsonDict(uiParameterJsonDict)
示例#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 __init__(self, iface, abstractDb, loadCentroids):
     """Constructor."""
     super(EDGVLayerLoader, self).__init__()
     
     self.abstractDb = abstractDb
     self.uri = QgsDataSourceURI() 
     self.iface = iface
     self.utils = Utils()
     self.logErrorDict = dict()
     self.errorLog = ''
     self.geomTypeDict = self.abstractDb.getGeomTypeDict(loadCentroids)
     self.geomDict = self.abstractDb.getGeomDict(self.geomTypeDict)
     self.correspondenceDict = {'POINT':'Point', 'MULTIPOINT':'Point', 'LINESTRING':'Line','MULTILINESTRING':'Line', 'POLYGON':'Area', 'MULTIPOLYGON':'Area'}
示例#19
0
 def __init__(self, parent = None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     # Set up the user interface from Designer.
     # After setupUI you can access any designer object by doing
     # self.<objectname>, and you can use autoconnect slots - see
     # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
     # #widgets-and-dialogs-with-auto-connect
     self.setupUi(self)
     self.utils = Utils()
     self.factory = SqlGeneratorFactory()
     #setting the sql generator
     self.gen = self.factory.createSqlGenerator(False)
     self.serverWidget.populateServersCombo()
     self.serverWidget.abstractDbLoaded.connect(self.populateListWithDatabasesFromServer)
示例#20
0
 def __init__(self, edgvVersion, areas, lines, oldCoverage, propertyList, enableSetupFromFile = True, onlySetup = False, propertyName = None, parent=None):
     """
     Constructor
     """
     super(self.__class__, self).__init__()
     self.setupUi(self)
     self.utils = Utils()
     self.areas = areas
     self.lines = lines
     self.propertyName = propertyName
     self.edgvVersion = edgvVersion
     self.areasCustomSelector.setTitle(self.tr('Areas'))
     self.linesCustomSelector.setTitle(self.tr('Lines'))
     self.propertyList = propertyList
     self.button(QtGui.QWizard.NextButton).clicked.connect(self.buildTree)
     self.button(QtGui.QWizard.FinishButton).clicked.connect(self.buildDict)
     self.setupWizard(oldCoverage, enableSetupFromFile)
     self.configDict = dict()
示例#21
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'}
示例#22
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)
示例#23
0
 def __init__(self, abstractDb, uiParameterJsonDict = None, parent = None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.abstractDb = abstractDb
     self.setupUi(self)
     self.jsonBuilder = CustomJSONBuilder()
     self.populateSchemaCombo()
     self.hideWidgetList([self.singleValueLabel, self.singleValueComboBox, self.actionComboBox])
     self.singleAttribute = True
     self.filterCustomSelectorWidget.setTitle(self.tr('Select filter values'))
     self.populateSingleValue.connect(self.populateWidgetWithSingleValue)
     self.populateListValue.connect(self.populateWidgetWithListValue)
     geomTypeDict = self.abstractDb.getGeomTypeDict()
     geomDict = self.abstractDb.getGeomDict(geomTypeDict)
     self.domainDict = self.abstractDb.getDbDomainDict(geomDict)
     self.inhTree = self.abstractDb.getInheritanceTreeDict()
     self.utils = Utils()
     self.actionDict = {self.tr('Add to Filter (Leave empty if filter is empty)'):'addEmpty', self.tr('Add to Filter (Add value to empty filter)'):'add',self.tr('Remove from Filter'):'remove'}
     self.populateFromUiParameterJsonDict(uiParameterJsonDict)
示例#24
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)       
示例#25
0
    def __init__(self, parent=None):
        """Constructor."""
        super(LoadByClass, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.filename = ""
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.selectedClasses = []

        #Sql factory generator
        self.isSpatialite = True

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

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

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

        self.db = None
        #populating the postgis combobox
        self.populatePostGISConnectionsCombo()
 def __init__(self, parent = None):
     """Constructor."""
     super(self.__class__, self).__init__(parent)
     self.setupUi(self)
     self.utils = Utils()
     self.dbFactory = DbFactory()
     self.factory = SqlGeneratorFactory()
     self.serverWidget.populateServersCombo()
     self.serverWidget.abstractDbLoaded.connect(self.populatePostgisSelector)
     self.customFileSelector.filesSelected.connect(self.populateSpatialiteSelector)
     self.comboDict = {self.tr('Load Database Model EDGV Version 2.1.3'):'2.1.3', self.tr('Load Database Model EDGV Version FTer_2a_Ed'):'FTer_2a_Ed',self.tr('Load Other Database Models'):'Non_EDGV'}
     self.dbDict = {'2.1.3':[], 'FTer_2a_Ed':[],'Non_EDGV':[]}
     self.selectedDbsDict = dict()
     self.stylesDict = dict()
     self.postgisCustomSelector.selectionChanged.connect(self.selectedDatabases)
     self.spatialiteCustomSelector.selectionChanged.connect(self.selectedFiles)
     self.path = None
     self.customFileSelector.setCaption(self.tr('Select a DSGTools Spatialite file'))
     self.customFileSelector.setFilter(self.tr('Spatialite file databases (*.sqlite)'))
     self.customFileSelector.setType('multi')
     self.edgvType = None
示例#27
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)
示例#28
0
    def __init__(self, iface, db, table):
        """Constructor.
        """
        QDialog.__init__( self )
        self.setupUi( self )

        #qgis interface
        self.iface = iface

        #database conenction
        self.db = db
        #table name
        self.table = table
        #rows that are marked for removal
        self.toBeRemoved = []

        #adjusting the table name to match the correspondent qml file
        fileName = table.replace('complexos_', '')
        fileName = fileName.split('.')[-1]+'.qml'

        #obtaining the qml file path
        self.utils = Utils()
        qmlDirPath = self.utils.getQmlDir(db)
        qmlPath = os.path.join(qmlDirPath, fileName)

        #getting the domain dictionary that will be used to generate the comboboxes
        try:
            parser = QmlParser(qmlPath)
            self.domainDict = parser.getDomainDict()
        except:
            self.domainDict = dict()
            pass

        QObject.connect(self.addRow, SIGNAL(("clicked()")), self.addComplex)
        QObject.connect(self.removeRow, SIGNAL(("clicked()")), self.removeComplex)
        QObject.connect(self.updateButton, SIGNAL(("clicked()")), self.updateTable)
        QObject.connect(self.cancelButton, SIGNAL(("clicked()")), self.cancel)

        self.updateTableView()
示例#29
0
    def __init__(self, parent=None):
        """Constructor."""
        super(ConvertDatabase, 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.geomClasses = None
        self.complexClasses = None
        self.invalidatedDataDict = dict()

        self.comboBox.addItem(self.tr('Select a conversion'))
        self.comboBox.addItem(self.tr('postgis2spatialite'))
        self.comboBox.addItem(self.tr('spatialite2postgis'))
        self.widget.tabWidget.setTabEnabled(0, False)
        self.widget.tabWidget.setTabEnabled(1, False)
        self.widget_2.tabWidget.setTabEnabled(0, False)
        self.widget_2.tabWidget.setTabEnabled(1, False)
        self.allDataRadioButton.setEnabled(False)
        self.fixDataRadioButton.setEnabled(False)
示例#30
0
class EDGVLayerLoader(QObject):
    
    def __init__(self, iface, abstractDb, loadCentroids):
        """Constructor."""
        super(EDGVLayerLoader, self).__init__()
        
        self.abstractDb = abstractDb
        self.uri = QgsDataSourceURI() 
        self.iface = iface
        self.utils = Utils()
        self.logErrorDict = dict()
        self.errorLog = ''
        self.geomTypeDict = self.abstractDb.getGeomTypeDict(loadCentroids)
        self.geomDict = self.abstractDb.getGeomDict(self.geomTypeDict)
        self.correspondenceDict = {'POINT':'Point', 'MULTIPOINT':'Point', 'LINESTRING':'Line','MULTILINESTRING':'Line', 'POLYGON':'Area', 'MULTIPOLYGON':'Area'}
    
    def preLoadStep(self, inputList):
        if len(inputList) == 0:
            return [], False
        else:
            if isinstance(inputList[0], dict):
                lyrList = [i['tableName'] for i in inputList]
                return lyrList, True
            else:
                return inputList, False

    def load(self, layerList, useQml = False, uniqueLoad = False, useInheritance = False, stylePath = None, onlyWithElements = False):
        return None
    
    def getStyle(self, stylePath, className):
        if 'db:' in stylePath['style']:
            return self.abstractDb.getStyle(stylePath['style'].split(':')[-1], className)
        else:
            return self.getStyleFromFile(stylePath['style'], 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
    
    def prepareLoad(self):
        dbName = self.abstractDb.getDatabaseName()
        groupList =  iface.legendInterface().groups()
        if dbName in groupList:
            return groupList.index(dbName)
        else:
            parentTreeNode = iface.legendInterface().addGroup(self.abstractDb.getDatabaseName(), -1)
            return parentTreeNode

    def createMeasureColumn(self, layer):
        if layer.geometryType() == QGis.Polygon:
            layer.addExpressionField('$area', QgsField(self.tr('area_otf'), QVariant.Double))
        elif layer.geometryType() == QGis.Line:
            layer.addExpressionField('$length', QgsField(self.tr('lenght_otf'), QVariant.Double))
        return layer
    
    def getDatabaseGroup(self, groupList):
        dbName = self.abstractDb.getDatabaseName()
        if dbName in groupList:
            return groupList.index(dbName)
        else:
            return self.iface.legendInterface().addGroup(dbName, True, -1)

    def getLyrDict(self, inputList, isEdgv = True):
        """
        Builds lyrDict in order to build loading tree
        lyrList: list of layers to be loaded
        isEdgv: optional parameter to indicate when db is not edgv. If db is not edgv, layers will be grouped by schema.
        """
        lyrDict = dict()
        if isinstance(inputList, list):
            if len(inputList) > 0:
                if isinstance(inputList[0],dict):
                    for elem in inputList:
                        if elem['geomType'] == 'GEOMETRY':
                            continue
                        if self.correspondenceDict[elem['geomType']] not in lyrDict.keys():
                            lyrDict[self.correspondenceDict[elem['geomType']]] = dict()
                        if elem['cat'] not in lyrDict[self.correspondenceDict[elem['geomType']]].keys():
                            lyrDict[self.correspondenceDict[elem['geomType']]][elem['cat']] = []
                        lyrDict[self.correspondenceDict[elem['geomType']]][elem['cat']].append(elem)
                else:
                    for type in self.geomTypeDict.keys():
                        # some tables are only registered as GEOMETRY and should not be considered
                        if type == 'GEOMETRY':
                            continue
                        if self.correspondenceDict[type] not in lyrDict.keys():
                            lyrDict[self.correspondenceDict[type]] = dict()
                        for lyr in self.geomTypeDict[type]:
                            if lyr in inputList:
                                if isEdgv:
                                    cat = lyr.split('_')[0]
                                else:
                                    cat = self.abstractDb.getTableSchemaFromDb(lyr)
                                if cat not in lyrDict[self.correspondenceDict[type]].keys():
                                    lyrDict[self.correspondenceDict[type]][cat] = []
                                lyrDict[self.correspondenceDict[type]][cat].append(lyr)
                    for type in lyrDict.keys():
                        if lyrDict[type] == dict():
                            lyrDict.pop(type)
        return lyrDict

    def prepareGroups(self, groupList, parent, lyrDict):
        aux = dict()
        groupDict = dict()
        groupNodeList = lyrDict.keys()
        groupNodeList.sort(reverse=True)
        for geomNode in groupNodeList:
            groupDict[geomNode] = dict()
            aux = self.createGroup(groupList, geomNode, parent)
            catList = lyrDict[geomNode].keys()
            catList.sort()
            for catNode in catList:
                groupDict[geomNode][catNode] = self.createGroup(groupList, catNode, aux)
        return groupDict
    
    def createGroup(self, groupList, groupName, parent):
        subgroup = groupList[parent::]
        if groupName in subgroup:
            return parent+subgroup.index(groupName) #verificar
        else:
            return self.iface.legendInterface().addGroup(groupName, True, parent)
        
    def loadDomains(self, layerList, loadedLayers, domainGroup):
        domLayerDict = dict()
        qmlDict = self.abstractDb.getQmlDict(layerList)
        for lyr in layerList:
            if lyr in qmlDict.keys():
                for attr in qmlDict[lyr].keys():
                    domain = qmlDict[lyr][attr]
                    domLyr = self.checkLoaded(domain, loadedLayers)
                    if not domLyr:
                        domLyr = self.loadDomain(domain, domainGroup)
                        loadedLayers.append(domLyr)
                        domLyrName = domLyr.name()
                    if lyr not in domLayerDict.keys():
                        domLayerDict[lyr] = dict()
                    if attr not in domLayerDict[lyr].keys():
                        domLayerDict[lyr][attr] = domLyr
        return domLayerDict

    def logError(self):
        msg = ''
        for lyr in self.logErrorDict:
            msg += self.tr('Error for lyr ')+ lyr + ': ' +self.logErrorDict[lyr] + '\n'
        self.errorLog += msg

    def setDataSource(self, schema, layer, geomColumn, sql, pkColumn='id'):
        self.uri.setDataSource(schema, layer, geomColumn, sql, pkColumn)
        if sql == '':
            self.uri.disableSelectAtId(False)
        else:
            self.uri.disableSelectAtId(True)

    def setDomainsAndRestrictionsWithQml(self, vlayer):
        qmldir = ''
        try:
            qmldir, qmlType = self.abstractDb.getQml(vlayer.name())
        except Exception as e:
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
            return None
        if qmlType == 'db':
            vlayer.applyNamedStyle(qmldir)
        else:
            vlayerQml = os.path.join(qmldir, vlayer.name()+'.qml')
            #treat case of qml with multi
            vlayer.loadNamedStyle(vlayerQml, False)
        return vlayer
示例#31
0
class LoadByClass(QtGui.QDialog, load_by_class_base.Ui_LoadByClass):
    def __init__(self, parent=None):
        """Constructor."""
        super(LoadByClass, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.filename = ""
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.selectedClasses = []

        #Sql factory generator
        self.isSpatialite = True

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

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

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

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

    def __del__(self):
        self.closeDatabase()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def loadEDGVLayer(self, uri, layer_name, provider):
        vlayer = QgsVectorLayer(uri.uri(), layer_name, provider)
        vlayer.setCrs(self.crs)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer) #added due to api changes
        if self.isSpatialite and (self.dbVersion == '3.0' or self.dbVersion == '2.1.3'):
            lyr = '_'.join(layer_name.replace('\r', '').split('_')[1::])
        else:
            lyr = layer_name.replace('\r','')
        vlayerQml = os.path.join(self.qmlPath, lyr+'.qml')
        vlayer.loadNamedStyle(vlayerQml, False)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer)
        if not vlayer.isValid():
            QgsMessageLog.logMessage(vlayer.error().summary(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
示例#32
0
class AbstractDb(QObject):
    def __init__(self):
        '''
        Constructor
        '''
        super(AbstractDb, self).__init__()
        self.conversionTypeDict = dict({
            'QPSQL': 'postgis',
            'QSQLITE': 'spatialite'
        })
        self.utils = Utils()
        self.signals = DbSignals()
        self.slotConnected = False
        self.versionFolderDict = dict({
            '2.1.3': 'edgv_213',
            'FTer_2a_Ed': 'edgv_FTer_2a_Ed'
        })
        self.utmGrid = UtmGrid()

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

    def checkAndOpenDb(self):
        '''
        Check and open the database
        '''
        if not self.db.isOpen():
            if not self.db.open():
                raise Exception(
                    self.tr('Error opening database: ') +
                    self.db.lastError().text())

    def getType(self):
        '''
        Gets the driver name
        '''
        return self.db.driverName()

    def validateUUID(self, uuid):
        try:
            uuid = UUID(uuid)
            return True
        except:
            return False

    def countElements(self, layers):
        '''
        Counts the number of elements in each layer present in layers
        '''
        self.checkAndOpenDb()
        listaQuantidades = []
        for layer in layers:
            (table, schema) = self.getTableSchema(layer)
            if layer.split('_')[-1] in ['p', 'l', 'a'
                                        ] or schema == 'complexos':
                sql = self.gen.getElementCountFromLayer(layer)
                query = QSqlQuery(sql, self.db)
                query.next()
                number = query.value(0)
                if not query.exec_(sql):
                    raise Exception(
                        self.tr("Problem counting elements: ") +
                        query.lastError().text())
                listaQuantidades.append([layer, number])
        return listaQuantidades

    def getLayersWithElements(self, layerList):
        self.checkAndOpenDb()
        lyrWithElemList = []
        for lyr in layerList:
            schema = self.getTableSchemaFromDb(lyr)
            sql = self.gen.getElementCountFromLayer(schema, lyr)
            query = QSqlQuery(sql, self.db)
            query.next()
            if query.value(0) > 1:
                lyrWithElemList.appen(lyr)
        return lyrWithElemList

    def getLayersWithElementsV2(self, layerList, useInheritance=False):
        self.checkAndOpenDb()
        lyrWithElemList = []
        for layer in layerList:
            if isinstance(layer, dict):
                schema = layer['tableSchema']
                lyr = layer['tableName']
            else:
                if '.' in layer:
                    schema, lyr = layer.replace('"', '').split('.')
                else:
                    lyr = layer
                    schema = self.getTableSchemaFromDb(lyr)
            sql = self.gen.getElementCountFromLayerV2(schema, lyr,
                                                      useInheritance)
            query = QSqlQuery(sql, self.db)
            query.next()
            if query.value(0) > 0:
                lyrWithElemList.append(lyr)
        return lyrWithElemList

    def findEPSG(self, parameters=dict()):
        '''
        Finds the database EPSG
        '''
        self.checkAndOpenDb()
        sql = self.gen.getSrid(parameters=parameters)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(
                self.tr("Problem finding EPSG: ") + query.lastError().text())
        srid = -1
        while query.next():
            srid = query.value(0)
        return srid

    def listWithElementsFromDatabase(self, classList):
        '''
        List classes with elements
        classList: class list
        '''
        self.checkAndOpenDb()
        classListWithNumber = self.countElements(classList)
        classesWithElements = dict()
        for cl in classListWithNumber:
            if cl[1] > 0:
                classesWithElements[cl[0]] = cl[1]
        return classesWithElements

    def listClassesWithElementsFromDatabase(self,
                                            useComplex=True,
                                            primitiveFilter=[]):
        '''
        List classes with elements. Uses all classes (complex included)
        '''
        geomClassList = self.listGeomClassesFromDatabase(primitiveFilter)
        classList = []
        for g in geomClassList:
            classList.append(g)
        if useComplex:
            complexClassList = self.listComplexClassesFromDatabase()
            for c in complexClassList:
                classList.append(c)
        classList.sort()
        return self.listWithElementsFromDatabase(classList)

    def getAggregationAttributes(self):
        '''
        Gets complex link columns
        '''
        self.checkAndOpenDb()
        columns = []
        sql = self.gen.getAggregationColumn()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(
                self.tr("Problem getting aggregation attributes: ") +
                query.lastError().text())
        while query.next():
            value = query.value(0)
            columns.append(value)
        return columns

    def getOgrDatabase(self):
        '''
        Builds a OGR database
        '''
        if self.ogrDb != None:
            self.buildOgrDatabase()
            return self.ogrDb

    def buildFieldMap(self):
        '''
        Gets database structure according to the edgv version
        '''
        self.checkAndOpenDb()
        fieldMap = self.getStructureDict()
        return fieldMap

    def validateWithOutputDatabaseSchema(self, outputAbstractDb):
        return None

    def convertDatabase(self, outputAbstractDb, type):
        '''
        Converts database
        '''
        self.signals.clearLog.emit()
        if outputAbstractDb.db.driverName() == 'QPSQL':
            return self.convertToPostgis(outputAbstractDb, type)
        if outputAbstractDb.db.driverName() == 'QSQLITE':
            return self.convertToSpatialite(outputAbstractDb, type)
        return None

    def makeValidationSummary(self, invalidatedDataDict):
        '''
        Makes the database conversion validation summary
        '''
        hasErrors = False
        for key in invalidatedDataDict.keys():
            if len(invalidatedDataDict[key]) > 0:
                hasErrors = True
        if hasErrors:
            self.signals.updateLog.emit(
                '\n' +
                '{:-^60}'.format(self.tr('Validation Problems Summary')))
            for key in invalidatedDataDict.keys():

                if key == 'nullLine' and len(invalidatedDataDict[key]) > 0:
                    self.signals.updateLog.emit(
                        '\n\n' + self.tr('Classes with null lines:') + '\n')
                    self.signals.updateLog.emit(
                        '\n\n' + '{:<50}'.format(self.tr('Class')) +
                        self.tr('Elements') + '\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(
                            '{:<50}'.format(cl) +
                            str(invalidatedDataDict[key][cl]) + '\n')

                if key == 'nullPk' and len(invalidatedDataDict[key]) > 0:
                    self.signals.updateLog.emit(
                        '\n\n' + self.tr('Classes with null primary keys:') +
                        '\n')
                    self.signals.updateLog.emit(
                        '\n\n' + '{:<50}'.format(self.tr('Class')) +
                        self.tr('Elements') + '\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(
                            '{:<50}'.format(cl) +
                            str(invalidatedDataDict[key][cl]) + '\n')

                if key == 'notInDomain' and len(invalidatedDataDict[key]) > 0:
                    self.signals.updateLog.emit(
                        '\n\n' +
                        self.tr('Features with attributes not in domain:') +
                        '\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit('\n' + self.tr('Class: ') +
                                                    cl + '\n')
                        for id in invalidatedDataDict[key][cl].keys():
                            attrCommaList = '(id,' + ','.join(
                                invalidatedDataDict[key][cl]
                                [id].keys()) + ') = '
                            at = invalidatedDataDict[key][cl][id].keys()
                            valueList = '(' + str(id)
                            for i in range(len(at)):
                                valueList += ',' + str(
                                    invalidatedDataDict[key][cl][id][at[i]])
                            valueList += ')\n'
                            self.signals.updateLog.emit(attrCommaList +
                                                        valueList)

                if key == 'nullAttribute' and len(
                        invalidatedDataDict[key]) > 0:
                    self.signals.updateLog.emit('\n\n' + self.tr(
                        'Features with null attributes in a not null field:') +
                                                '\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(
                            self.tr('Class: ') + cl + '\n')
                        for id in invalidatedDataDict[key][cl].keys():
                            attrCommaList = '(id,' + ','.join(
                                invalidatedDataDict[key][cl]
                                [id].keys()) + ') = '
                            valueList = '(' + str(id)
                            for attr in invalidatedDataDict[key][cl][id].keys(
                            ):
                                valueList += ',' + str(
                                    invalidatedDataDict[key][cl][id][attr])
                            valueList += ')\n'
                            self.signals.updateLog.emit(attrCommaList +
                                                        valueList)

                if key == 'nullComplexFk' and len(
                        invalidatedDataDict[key]) > 0:
                    self.signals.updateLog.emit(
                        '\n\n' +
                        self.tr('Features with invalid uuid foreign key:') +
                        '\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(
                            self.tr('Class: ') + cl + '\n')
                        for id in invalidatedDataDict[key][cl].keys():
                            attrCommaList = '(id,' + ','.join(
                                invalidatedDataDict[key][cl]
                                [id].keys()) + ') = '
                            valueList = '(' + str(id)
                            for attr in invalidatedDataDict[key][cl][id].keys(
                            ):
                                valueList += ',' + str(
                                    invalidatedDataDict[key][cl][id][attr])
                            valueList += ')\n'
                            self.signals.updateLog.emit(attrCommaList +
                                                        valueList)

                if key == 'classNotFoundInOutput' and len(
                        invalidatedDataDict[key]) > 0:
                    self.signals.updateLog.emit('\n\n' + self.tr(
                        'Classes with classes that have elements but do not have output equivalent:'
                    ) + '\n\n')
                    for cl in invalidatedDataDict[key]:
                        self.signals.updateLog.emit(
                            self.tr('Class: ') + cl + '\n')

                if key == 'attributeNotFoundInOutput' and len(
                        invalidatedDataDict[key]) > 0:
                    self.signals.updateLog.emit('\n\n' + self.tr(
                        'Classes with attributes that have no output attribute equivalent:'
                    ) + '\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(
                            self.tr('Class: ') + cl + '\n')
                        valueList = '(' + ','.join(
                            invalidatedDataDict[key][cl]) + ')\n'
                        self.signals.updateLog.emit(valueList)

        return hasErrors

    def buildReadSummary(self, inputOgrDb, outputAbstractDb, classList):
        '''
        Builds the conversion read summary
        '''
        self.signals.clearLog.emit()  #Clears log
        inputType = self.conversionTypeDict[self.db.driverName()]
        outputType = self.conversionTypeDict[outputAbstractDb.db.driverName()]
        self.signals.updateLog.emit(
            self.tr('Conversion type: ') + inputType + '2' + outputType + '\n')
        self.signals.updateLog.emit('\n' + self.tr('Input database: ') +
                                    self.db.databaseName() + '\n')
        self.signals.updateLog.emit('\n' + self.tr('Output database: ') +
                                    outputAbstractDb.db.databaseName() + '\n')
        self.signals.updateLog.emit('\n' +
                                    '{:-^60}'.format(self.tr('Read Summary')))
        self.signals.updateLog.emit('\n\n' +
                                    '{:<50}'.format(self.tr('Class')) +
                                    self.tr('Elements') + '\n\n')
        for cl in classList:
            self.signals.updateLog.emit(
                '{:<50}'.format(cl) +
                str(inputOgrDb.GetLayerByName(str(cl)).GetFeatureCount()) +
                '\n')
        return None

    def makeTranslationMap(self, layerName, layer, outLayer, fieldMapper):
        '''
        Makes the translation map
        '''
        layerFieldMapper = fieldMapper[layerName]
        layerDef = layer.GetLayerDefn()
        outLayerDef = outLayer.GetLayerDefn()
        panMap = []
        for i in range(layerDef.GetFieldCount()):
            featureDef = layerDef.GetFieldDefn(i)
            fieldName = featureDef.GetName()
            if fieldName in layerFieldMapper.keys():
                name = layerFieldMapper[fieldName]
                fieldId = outLayerDef.GetFieldIndex(name)
                panMap.append(fieldId)
            else:
                panMap.append(-1)
        return panMap

    def translateLayer(self,
                       inputLayer,
                       inputLayerName,
                       outputLayer,
                       outputFileName,
                       layerPanMap,
                       errorDict,
                       defaults={},
                       translateValues={}):
        '''
        Makes the layer conversion
        '''
        inputLayer.ResetReading()
        inSpatialRef = inputLayer.GetSpatialRef()
        outSpatialRef = outputLayer.GetSpatialRef()
        coordTrans = None
        if not inSpatialRef.IsSame(outSpatialRef):
            coordTrans = osr.CoordinateTransformation(inSpatialRef,
                                                      outSpatialRef)
        initialCount = outputLayer.GetFeatureCount()
        count = 0
        feat = inputLayer.GetNextFeature()
        #for feat in inputLayer:
        while feat:
            if not feat.geometry():
                continue
            inputId = feat.GetFID()
            if feat.geometry().GetGeometryCount() > 1:
                #Deaggregator
                for geom in feat.geometry():
                    newFeat = ogr.Feature(outputLayer.GetLayerDefn())
                    newFeat.SetFromWithMap(feat, True, layerPanMap)
                    auxGeom = ogr.Geometry(
                        newFeat.geometry().GetGeometryType())
                    auxGeom.AssignSpatialReference(
                        newFeat.geometry().GetSpatialReference())
                    auxGeom.AddGeometry(geom)
                    if coordTrans <> None:
                        auxGeom.Transform(coordTrans)
                    newFeat.SetGeometry(auxGeom)
                    out = outputLayer.CreateFeature(newFeat)
                    if out <> 0:
                        self.utils.buildNestedDict(errorDict, [inputLayerName],
                                                   [inputId])
                    else:
                        count += 1
            else:
                newFeat = ogr.Feature(outputLayer.GetLayerDefn())
                newFeat.SetFromWithMap(feat, True, layerPanMap)
                if coordTrans <> None:
                    geom = feat.GetGeometryRef()
                    geom.Transform(coordTrans)
                    newFeat.SetGeometry(geom)
                out = outputLayer.CreateFeature(newFeat)
                if out <> 0:
                    self.utils.buildNestedDict(errorDict, [inputLayerName],
                                               [inputId])
                else:
                    count += 1
            feat = inputLayer.GetNextFeature()
        return count

    def translateDS(self,
                    inputDS,
                    outputDS,
                    fieldMap,
                    inputLayerList,
                    errorDict,
                    invalidated=None):
        '''
        Translates the data source
        '''
        self.signals.updateLog.emit('\n' +
                                    '{:-^60}'.format(self.tr('Write Summary')))
        self.signals.updateLog.emit('\n\n' +
                                    '{:<50}'.format(self.tr('Class')) +
                                    self.tr('Elements') + '\n\n')
        status = False
        for inputLyr in inputLayerList.keys():
            schema = self.getTableSchema(inputLyr)
            attrList = fieldMap[inputLyr].keys()

            #sql = self.gen.getFeaturesWithSQL(inputLyr,attrList) #order elements here
            #inputOgrLayer = inputDS.ExecuteSQL(sql.encode('utf-8'))
            #Here I had to change the way of loading because of features ids. I need to use inputDs.GetLayerByName

            inputOgrLayer = inputDS.GetLayerByName(
                str(inputLyr)
            )  #new way of loading layer. The old way was an attempt to make a general rule for conversion between edgv versions
            outputFileName = self.translateOGRLayerNameToOutputFormat(
                inputLyr, outputDS)
            outputLayer = outputDS.GetLayerByName(outputFileName)
            #order conversion here
            layerPanMap = self.makeTranslationMap(inputLyr, inputOgrLayer,
                                                  outputLayer, fieldMap)
            ini = outputLayer.GetFeatureCount()
            if invalidated == None:
                iter = self.translateLayer(inputOgrLayer, inputLyr,
                                           outputLayer, outputFileName,
                                           layerPanMap, errorDict)
            else:
                needsFix = False
                for keyDict in invalidated.values():
                    if len(keyDict) > 0:
                        if type(keyDict) == list:
                            if inputLyr in keyDict:
                                needsFix = True
                        if type(keyDict) == dict:
                            if inputLyr in keyDict.keys():
                                needsFix = True
                                break
                if needsFix:
                    iter = self.translateLayerWithDataFix(
                        inputOgrLayer, inputLyr, outputLayer, outputFileName,
                        layerPanMap, invalidated, errorDict)
                else:
                    iter = self.translateLayer(inputOgrLayer, inputLyr,
                                               outputLayer, outputFileName,
                                               layerPanMap, errorDict)
            if iter == -1:
                status = False
                self.signals.updateLog.emit('{:<50}'.format(
                    self.tr('Error on layer ') + inputLyr +
                    self.tr('. Conversion not performed.') + '\n'))
                return status
            diff = outputLayer.GetFeatureCount() - ini
            if iter == diff:
                status = True
            else:
                status = False
            self.signals.updateLog.emit('{:<50}'.format(str(outputFileName)) +
                                        str(diff) + '\n')
        self.writeErrorLog(errorDict)
        outputDS.Destroy()
        return status

    def buildInvalidatedDict(self):
        '''
        Builds the initial state of the conversion invalidated dictionary
        '''
        invalidated = dict()
        invalidated['nullLine'] = dict()
        invalidated['nullPk'] = dict()
        invalidated['notInDomain'] = dict()
        invalidated['nullAttribute'] = dict()
        invalidated['classNotFoundInOutput'] = []
        invalidated['attributeNotFoundInOutput'] = dict()
        invalidated['nullComplexFk'] = dict()
        return invalidated

    def prepareForConversion(self, outputAbstractDb):
        '''
        Executes preconditions for the conversion
        '''
        self.checkAndOpenDb()
        outputAbstractDb.checkAndOpenDb()
        fieldMap = self.buildFieldMap()
        inputOgrDb = self.buildOgrDatabase()
        outputOgrDb = outputAbstractDb.buildOgrDatabase()
        inputLayerList = self.listClassesWithElementsFromDatabase()
        errorDict = dict()
        self.buildReadSummary(inputOgrDb, outputAbstractDb, inputLayerList)
        return (inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict)

    def translateLayerWithDataFix(self,
                                  inputLayer,
                                  inputLayerName,
                                  outputLayer,
                                  outputFileName,
                                  layerPanMap,
                                  invalidated,
                                  errorDict,
                                  defaults={},
                                  translateValues={}):
        '''
        casos e tratamentos:
        1. nullLine: os atributos devem ser varridos e, caso seja linha nula, ignorar o envio
        2. nullPk: caso seja complexo, gerar uma chave
        3. notInDomain: excluir do mapeamento aquele atributo caso ele seja mapeado
        4. nullAttribute: excluir do mapeamento aquele atributo caso ele seja não nulo
        5. classNotFoundInOutput: pular classe na conversão e mostrar no warning
        6. attributeNotFoundInOutput: pular atributo e mostrar no warning para todas as feicoes
        7. nullGeometry: excluir a feicao do mapeamento
        8. nullComplexFk: fazer atributo id_% ficar nulo caso não seja uuid
        '''
        inputLayer.ResetReading()
        fieldCount = inputLayer.GetLayerDefn().GetFieldCount()
        initialCount = outputLayer.GetFeatureCount()
        inSpatialRef = inputLayer.GetSpatialRef()
        outSpatialRef = outputLayer.GetSpatialRef()
        coordTrans = None
        if inSpatialRef <> outSpatialRef:
            coordTrans = osr.CoordinateTransformation(inSpatialRef,
                                                      outSpatialRef)
        count = 0
        feat = inputLayer.GetNextFeature()
        (schema, className) = self.getTableSchema(inputLayerName)
        outputOgrLyrDict = self.getOgrLayerIndexDict(outputLayer)
        if inputLayerName not in invalidated['classNotFoundInOutput']:
            while feat:
                if not feat.geometry():
                    continue
                nullLine = True
                #Case 1: nullLine
                for i in range(fieldCount):
                    if feat.GetField(i) <> None:
                        nullLine = False
                        break
                if feat.GetFID() <> -1 or feat.geometry() <> None:
                    nullLine = False
                if not nullLine:
                    if inputLayerName not in invalidated[
                            'classNotFoundInOutput']:
                        newFeat = ogr.Feature(outputLayer.GetLayerDefn())
                        inputId = feat.GetFID()
                        #Case 2: nullPk in complex:
                        newFeat.SetFromWithMap(feat, True, layerPanMap)
                        if schema == 'complexos' and feat.GetFID() == -1:
                            newFeat.SetFID(uuid4())
                        #Case 3
                        for j in range(
                                inputLayer.GetLayerDefn().GetFieldCount()):
                            if layerPanMap[j] <> -1:
                                if inputLayerName in invalidated[
                                        'notInDomain'].keys():
                                    if inputId in invalidated['notInDomain'][
                                            inputLayerName].keys():
                                        if outputLayer.GetLayerDefn(
                                        ).GetFieldDefn(layerPanMap[j]).GetName(
                                        ) in invalidated['notInDomain'][
                                                inputLayerName][inputId].keys(
                                                ):
                                            newFeat.UnsetField(layerPanMap[j])
                                if inputLayerName in invalidated[
                                        'nullAttribute'].keys():
                                    if inputId in invalidated['nullAttribute'][
                                            inputLayerName].keys():
                                        if outputLayer.GetLayerDefn(
                                        ).GetFieldDefn(layerPanMap[j]).GetName(
                                        ) in invalidated['nullAttribute'][
                                                inputLayerName][inputId].keys(
                                                ):
                                            if outputLayer.GetLayerDefn(
                                            ).GetFieldDefn(
                                                    layerPanMap[j]
                                            ).GetTypeName() == 'String':
                                                newFeat.SetField(
                                                    layerPanMap[j], '-9999')
                                            if outputLayer.GetLayerDefn(
                                            ).GetFieldDefn(
                                                    layerPanMap[j]
                                            ).GetTypeName() == 'Integer':
                                                newFeat.SetField(
                                                    layerPanMap[j], -9999)
                                if inputLayerName in invalidated[
                                        'nullComplexFk'].keys():
                                    if inputId in invalidated['nullComplexFk'][
                                            inputLayerName].keys():
                                        if outputLayer.GetLayerDefn(
                                        ).GetFieldDefn(layerPanMap[j]).GetName(
                                        ) in invalidated['nullComplexFk'][
                                                inputLayerName][inputId].keys(
                                                ):
                                            newFeat.UnsetField(layerPanMap[j])
                        if newFeat.geometry().GetGeometryCount() > 1:
                            #Deaggregator
                            for geom in newFeat.geometry():
                                auxGeom = ogr.Geometry(
                                    newFeat.geometry().GetGeometryType())
                                auxGeom.AssignSpatialReference(
                                    newFeat.geometry().GetSpatialReference())
                                auxGeom.AddGeometry(geom)
                                if coordTrans <> None:
                                    auxGeom.Transform(coordTrans)
                                newFeat.SetGeometry(auxGeom)
                                out = outputLayer.CreateFeature(newFeat)
                                if out <> 0:
                                    self.utils.buildNestedDict(
                                        errorDict, [inputLayerName], [inputId])
                                else:
                                    count += 1
                        else:
                            if coordTrans <> None:
                                geom = feat.GetGeometryRef()
                                geom.Transform(coordTrans)
                                newFeat.SetGeometry(geom)
                            out = outputLayer.CreateFeature(newFeat)
                            if out <> 0:
                                self.utils.buildNestedDict(
                                    errorDict, [inputLayerName], [inputId])
                            else:
                                count += 1
                feat = inputLayer.GetNextFeature()
            return count
        else:
            return -1

    def buildOgrDatabase(self):
        '''
        Build a OGR database
        '''
        con = self.makeOgrConn()
        ogrDb = ogr.Open(con, update=1)
        return ogrDb

    def reorderTupleList(self, ls):
        '''
        Reorders a tuple list
        ls: list to be reordered
        '''
        if 'OGC_FID' in ls:
            idField = 'OGC_FID'
        else:
            idField = 'id'
        index = ls.index(idField)
        reordered = [ls[index]]
        reordered.extend(ls[0:index])
        reordered.extend(ls[index + 1::])
        return reordered

    def getOgrLayerIndexDict(self, lyr):
        '''
        Gets ogr field definitions
        '''
        ogrDict = dict()
        layerDef = lyr.GetLayerDefn()
        for i in range(layerDef.GetFieldCount()):
            ogrDict[i] = layerDef.GetFieldDefn(i).GetName()
        return ogrDict

    def writeErrorLog(self, errorDict):
        '''
        Writes conversion error log
        '''
        errorClasses = errorDict.keys()
        if len(errorClasses) > 0:
            self.signals.updateLog.emit(
                '\n' + '{:-^60}'.format(self.tr('Features not converted')))
            self.signals.updateLog.emit('\n\n' +
                                        '{:<50}'.format(self.tr('Class')) +
                                        self.tr('Feature id') + '\n\n')
            for cl in errorClasses:
                for id in errorDict[cl]:
                    self.signals.updateLog.emit('\n\n' +
                                                '{:<50}'.format(cl + str(id)))

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

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

    def getStyleDict(self, dbVersion):
        '''
        dbVersion: database version in the format of abstractDb.getVersion()
        The first iteration of walk lists all dirs as the second element of the list in os.walk(styleDir).next()[1]. 
        As only God and Mauricio were going to remember this, I wrote it down.
        '''
        currentPath = os.path.dirname(__file__)
        styleDir = os.path.join(currentPath, '..', '..', 'Styles')
        if dbVersion == '2.1.3':
            styleDir = os.path.join(styleDir, 'edgv_213')
        elif dbVersion == 'FTer_2a_Ed':
            styleDir = os.path.join(styleDir, 'edgv_FTer_2a_Ed')
        else:
            styleDir = os.path.join(styleDir, 'Non_EDGV')
        styleList = os.walk(styleDir).next()[1]
        styleDict = dict()
        try:
            for s in styleList:
                styleDict['dir:' + s] = os.path.join(styleDir, s)
            #here we get the styles from db if there are any
        except:
            pass
        try:
            dbStyles = self.getStylesFromDb(dbVersion)
            if dbStyles:
                for style in dbStyles:
                    name = style.split('/')[-1]
                    styleDict['db:' + name] = 'db:' + style
        except:
            pass
        return styleDict

    def makeValueRelationDict(self, table, codes):
        '''
        Makes the value relation dictionary (multi valued attributes)
        '''
        self.checkAndOpenDb()
        ret = dict()
        in_clause = '(%s)' % ",".join(map(str, codes))
        sql = self.gen.makeRelationDict(table, in_clause)
        query = QSqlQuery(sql, self.db)
        while query.next():
            code = str(query.value(0))
            code_name = query.value(1)
            ret[code_name] = code
        return ret

    def createFrameFromInom(self, inom):
        frame = self.utmGrid.getQgsPolygonFrame(inom)
        return frame

    def insertFrame(self, scale, mi, inom, frame, paramDict=dict()):
        self.checkAndOpenDb()
        srid = self.findEPSG()
        geoSrid = QgsCoordinateReferenceSystem(
            int(srid)).geographicCRSAuthId().split(':')[-1]
        sql = self.gen.insertFrame(scale,
                                   mi,
                                   inom,
                                   frame,
                                   srid,
                                   geoSrid,
                                   paramDict=paramDict)
        self.db.transaction()
        query = QSqlQuery(self.db)
        if not query.exec_(sql):
            self.db.rollback()
            self.db.close()
            raise Exception(
                self.tr('Problem inserting frame: ') +
                query.lastError().text())
        self.db.commit()
        self.db.close()

    def prepareCreateFrame(self, type, scale, param):
        if type == 'mi':
            mi = str(param)
            if scale == '250k':
                inom = self.utmGrid.getINomenFromMIR(str(param))
            else:
                inom = self.utmGrid.getINomenFromMI(str(param))
        elif type == 'inom':
            inom = str(param)
            if scale == '250k':
                mi = self.utmGrid.getINomenFromMIR(inom)
            else:
                mi = self.utmGrid.getMIfromInom(inom)
        frame = self.createFrameFromInom(inom)
        return mi, inom, frame
示例#33
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)
示例#34
0
class DsgToolsOpInstaller(QObject):
    def __init__(self, iface, parent=None, parentMenu=None):
        """
        Constructor
        """
        super(DsgToolsOpInstaller, self).__init__()
        self.iface = iface
        self.parentMenu = parentMenu
        self.utils = Utils()
        self.parent = parent
        self.icon_path = ':/plugins/DsgTools/icons/militarySimbology.png'

    def createAuxFolder(self):
        """
        Creates a auxiliary foldes to unzip the installer zip file
        """
        # current path point to DsgToolsOp folder
        currentPath = os.path.abspath(os.path.dirname(__file__))
        # folder "auxiliar" inside DsgToolsOp folder
        auxFolder = os.path.join(currentPath, 'auxiliar')
        # creating and returning the folder
        os.makedirs(auxFolder)
        return auxFolder

    def deleteAuxFolder(self):
        """
        Deletes the auxiliar folder
        """
        # current path point to DsgToolsOp folder
        currentPath = os.path.abspath(os.path.dirname(__file__))
        # working on MilitaryTools folder
        auxPath = os.path.join(currentPath, 'auxiliar')
        shutil.rmtree(auxPath, ignore_errors=True)

    def uninstallDsgToolsOp(self):
        """
        Uninstall all folders and files created
        """
        parentUi = self.iface.mainWindow()
        if QMessageBox.question(
                parentUi, self.tr('Question'),
                self.
                tr('DsgToolsOp is going to be uninstalled. Would you like to continue?'
                   ),
                QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Cancel:
            return

        # current path point to DsgToolsOp folder
        currentPath = os.path.abspath(os.path.dirname(__file__))
        # working on MilitaryTools folder
        toolsPath = os.path.join(currentPath, 'MilitaryTools')
        for root, dirs, files in os.walk(toolsPath):
            # deleting directories from MilitaryTools folder
            for dir_ in dirs:
                top = os.path.join(currentPath, 'MilitaryTools', dir_)
                shutil.rmtree(top, ignore_errors=True)
            # deleting files (keeping __init__.py) files MilitaryTools folder
            for file_ in files:
                if file_ != '__init__.py':
                    os.remove(os.path.join(toolsPath, file_))

        QMessageBox.information(
            parentUi, self.tr('Success!'),
            self.tr('DsgToolsOp uninstalled successfully!'))

    def installDsgToolsOp(self, fullZipPath, parentUi=None):
        """
        Install files present into installer zip file
        :param fullZipPath: zip file path
        """
        try:
            reinstalled = False
            # current path point to DsgToolsOp folder
            currentPath = os.path.abspath(os.path.dirname(__file__))
            # creating auxiliar folder
            auxFolder = self.createAuxFolder()
            destFolder = os.path.join(currentPath, 'MilitaryTools')
            # unzipping files into Military tools
            self.unzipFiles(fullZipPath, auxFolder)
            # checking the zip file before installation
            if not self.checkZipFile():
                self.deleteAuxFolder()
                return
            # check if installed
            if self.checkIfInstalled():
                # if installed, get the version
                installedVersion = self.getInstalledVersion()
                # getting the version to be installed
                toBeInstalledVersion = self.getFilesVersion(auxFolder)
                # checks if the version to be installed is already installed
                if installedVersion == toBeInstalledVersion:
                    QMessageBox.warning(
                        parentUi, self.tr('Warning!'),
                        self.tr('DsgToolsOp version already installed!'))
                    self.deleteAuxFolder()
                    return
                # Checks if the version to be installed is lower
                if installedVersion > toBeInstalledVersion:
                    if QMessageBox.question(
                            parentUi, self.tr('Question'),
                            self.
                            tr('Selected version is lower than installed one. Would you like to continue?'
                               ), QMessageBox.Ok
                            | QMessageBox.Cancel) == QMessageBox.Cancel:
                        self.deleteAuxFolder()
                        return
                # deleting previous version files
                self.uninstallDsgToolsOp()
                reinstalled = True
            # copying files to destination folder
            self.copyFiles(auxFolder, destFolder)
            QMessageBox.information(
                parentUi, self.tr('Success!'),
                self.tr('DsgToolsOp installed successfully!'))
            if reinstalled:
                QMessageBox.warning(
                    parentUi, self.tr('Warning!'),
                    self.
                    tr('Please, reload QGIS to access the new installed version!'
                       ))
        except Exception as e:
            try:
                self.deleteAuxFolder()
            except:
                pass
            QMessageBox.critical(
                self.parentMenu, self.tr('Critical!'),
                self.tr('Problem installing DsgToolsOp: ') + '|'.join(e.args))

    def addUninstall(self, icon_path, parent, parentMenu):
        """
        Creates the uninstall action menu
        """
        action = parent.add_action(icon_path,
                                   text=parent.tr('DsgTools Op Uninstaller'),
                                   callback=parent.uninstallDsgToolsOp,
                                   parent=parentMenu,
                                   add_to_menu=False,
                                   add_to_toolbar=False)
        parentMenu.addAction(action)

    def unzipFiles(self, fullZipPath, auxFolder):
        """
        Unzips files inside a zip into a folder
        :param fullZipPath: zip file path
        :param auxFolder: unzip folder
        """
        zip = zipfile.ZipFile(fullZipPath)
        zip.extractall(auxFolder)
        currentPath = os.path.abspath(os.path.dirname(__file__))
        init = open(os.path.join(currentPath, 'auxiliar', '__init__.py'), 'w')
        init.close()

    def copyFiles(self, auxFolder, destFolder):
        """
        Copies all files to destination folder
        :param destFolder: destination folder
        :param auxFolder: source folder
        """
        for src_dir, dirs, files in os.walk(auxFolder):
            if 'expression' == src_dir.split(os.path.sep)[-1]:
                for file_ in files:
                    src_file = os.path.join(src_dir, file_)
                    expression_dir = os.path.join(
                        os.path.abspath(os.path.dirname(__file__)), '..', '..',
                        '..', 'expressions')
                    expression_file = os.path.join(expression_dir, file_)
                    if os.path.exists(expression_file):
                        os.remove(expression_file)
                    shutil.move(src_file, expression_dir)
            else:
                dst_dir = src_dir.replace(auxFolder, destFolder, 1)
                if not os.path.exists(dst_dir):
                    os.makedirs(dst_dir)
                for file_ in files:
                    src_file = os.path.join(src_dir, file_)
                    dst_file = os.path.join(dst_dir, file_)
                    if os.path.exists(dst_file):
                        os.remove(dst_file)
                    shutil.move(src_file, dst_dir)
        # deleting auxiliar folder
        self.copyToExpressions(auxFolder, destFolder)
        self.deleteAuxFolder()
        self.loadTools()

    def copyToExpressions(self, auxFolder, destFolder):
        pass

    def checkIfInstalled(self):
        """
        Checks if the files are already installed
        """
        installPath = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                   'MilitaryTools')
        w = os.walk(installPath).next()[2]
        # checking the number of files in the folder
        if len(w) <= 2:
            return False
        else:
            return True

    def getInstalledVersion(self):
        """
        Checks the current installed version
        """
        versionPath = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                   'MilitaryTools', 'dsgtoolsop_version.json')
        jsonDict = self.utils.readJsonFile(versionPath)
        return jsonDict['version']

    def getFilesVersion(self, filesFolder):
        """
        Gets the version to be installed
        """
        versionPath = os.path.join(filesFolder, 'dsgtoolsop_version.json')
        jsonDict = self.utils.readJsonFile(versionPath)
        return jsonDict['version']

    def checkZipFile(self):
        """
        Verifies the zip file prior to install
        """
        try:
            from DsgTools.DsgToolsOp.auxiliar.toolLoader import ToolLoader
            return True
        except Exception as e:
            QMessageBox.critical(
                self.parentMenu, self.tr('Critical!'),
                self.tr('Invalid Zip file: ') + '|'.join(e.args))
            return False

    def loadTools(self):
        """
        Loads the tools present in the installer zip file
        """
        try:
            self.toolList = []
            from DsgTools.DsgToolsOp.MilitaryTools.toolLoader import ToolLoader
            self.toolLoader = ToolLoader(self.parentMenu, self.parent,
                                         self.icon_path)
            self.toolLoader.loadTools()
            self.addUninstall(self.icon_path, self.parent, self.parentMenu)
        except Exception as e:
            QMessageBox.critical(
                self.parentMenu, self.tr('Critical!'),
                self.tr('Problem installing DsgToolsOp: ') + '|'.join(e.args))
示例#35
0
class AbstractDb(QObject):
    def __init__(self):
        super(AbstractDb,self).__init__()
        self.conversionTypeDict = dict({'QPSQL':'postgis','QSQLITE':'spatialite'})
        self.utils = Utils()
        self.signals = DbSignals()
        self.slotConnected = False
        pass
    
    def __del__(self):
        if self.db.isOpen():
            self.db.close()
            self.db = None
            
    def getDatabaseName(self):
        return None
    
    def checkAndOpenDb(self):
        if not self.db.isOpen():
            if not self.db.open():
                raise Exception(self.tr('Error when opening database.')+'\n'+self.db.lastError().text())

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

    def connectDatabaseWithQSettings(self,name):
        return None

    def connectDatabaseWithGui(self):
        return None
    
    def getDatabaseVersion(self):
        return None

    def getType(self):
        return self.db.driverName()
    
    def listGeomClassesFromDatabase(self):
        return None

    def listComplexClassesFromDatabase(self):
        return None    

    def getConnectionFromQSettings(self, conName):
        return None

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

    def countElements(self, layers):
        try:
            self.checkAndOpenDb()
        except:
            return []
        listaQuantidades = []
        for layer in layers:
            (table,schema)=self.getTableSchema(layer)
            if layer.split('_')[-1] in ['p','l','a'] or schema == 'complexos':
                sql = self.gen.getElementCountFromLayer(layer)
                query = QSqlQuery(sql,self.db)
                query.next()
                number = query.value(0)
                if not query.exec_(sql):
                    QgsMessageLog.logMessage(self.tr("Problem counting elements: ")+query.lastError().text(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
                listaQuantidades.append([layer, number])
        return listaQuantidades     

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

    def listWithElementsFromDatabase(self, classList):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        classListWithNumber = self.countElements(classList)
        classesWithElements = dict()
        for cl in classListWithNumber:
            if cl[1]>0:
                classesWithElements[cl[0]]=cl[1]   
        return classesWithElements

    def listClassesWithElementsFromDatabase(self):
        geomClassList = self.listGeomClassesFromDatabase()
        complexClassList = self.listComplexClassesFromDatabase()
        classList = []
        for g in geomClassList:
            classList.append(g)
        for c in complexClassList:
            classList.append(c)
        classList.sort()
        return self.listWithElementsFromDatabase(classList)

    def getStructureDict(self):
        return None

    def makeOgrConn(self):
        return None    

    def getNotNullDict(self):
        return None

    def getDomainDict(self):
        return None

    def getAggregationAttributes(self):
        try:
            self.checkAndOpenDb()
        except:
            return []       
        columns = []
        sql = self.gen.getAggregationColumn()
        query = QSqlQuery(sql, self.db)
        while query.next():
            value = query.value(0)
            columns.append(value)
        return columns

    def getOgrDatabase(self):
        if self.ogrDb != None:
            self.buildOgrDatabase()
            return self.ogrDb

    def buildFieldMap(self):
        try:
            self.checkAndOpenDb()
        except:
            return dict()
        fieldMap = self.getStructureDict()
        return fieldMap

    def validateWithOutputDatabaseSchema(self,outputAbstractDb):
        return None
    
    def convertDatabase(self,outputAbstractDb,type):
        self.signals.clearLog.emit()
        if outputAbstractDb.db.driverName() == 'QPSQL':
            return self.convertToPostgis(outputAbstractDb,type)
        if outputAbstractDb.db.driverName() == 'QSQLITE':
            return self.convertToSpatialite(outputAbstractDb,type)
        return None
    
    def convertToPostgis(self, outputAbstractDb,type):
        return None
    
    def convertToSpatialite(self, outputAbstractDb,type):
        return None 

    def buildInvalidatedDict(self):
        return None
    
    def makeValidationSummary(self,invalidatedDataDict):
        hasErrors = False
        for key in invalidatedDataDict.keys():
            if len(invalidatedDataDict[key]) > 0:
                hasErrors = True
        if hasErrors:
            self.signals.updateLog.emit('\n'+'{:-^60}'.format(self.tr('Validation Problems Summary')))
            for key in invalidatedDataDict.keys():
                
                if key == 'nullLine' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Classes with null lines:')+'\n')
                    self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Elements')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit('{:<50}'.format(cl)+str(invalidatedDataDict[key][cl])+'\n')

                if key == 'nullPk' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Classes with null primary keys:')+'\n')
                    self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Elements')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit('{:<50}'.format(cl)+str(invalidatedDataDict[key][cl])+'\n')

                if key == 'notInDomain' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Features with attributes not in domain:')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit('\n'+self.tr('Class: ')+cl+'\n')
                        for id in invalidatedDataDict[key][cl].keys():
                            attrCommaList = '(id,'+','.join(invalidatedDataDict[key][cl][id].keys())+') = '
                            at = invalidatedDataDict[key][cl][id].keys()
                            valueList = '('+str(id)
                            for i in range(len(at)):
                                valueList += ','+str(invalidatedDataDict[key][cl][id][at[i]])
                            valueList += ')\n'
                            self.signals.updateLog.emit(attrCommaList+valueList)

                if key == 'nullAttribute' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Features with null attributes in a not null field:')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(self.tr('Class: ')+cl+'\n')
                        for id in invalidatedDataDict[key][cl].keys():
                            attrCommaList = '(id,'+','.join(invalidatedDataDict[key][cl][id].keys())+') = '
                            valueList = '('+str(id)
                            for attr in invalidatedDataDict[key][cl][id].keys():
                                valueList += ','+str(invalidatedDataDict[key][cl][id][attr])
                            valueList += ')\n'
                            self.signals.updateLog.emit(attrCommaList+valueList)
                            
                if key == 'classNotFoundInOutput' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Classes with classes that have elements but do not have output equivalent:')+'\n\n')
                    for cl in invalidatedDataDict[key]:
                            self.signals.updateLog.emit(self.tr('Class: ')+cl+'\n')
                
                if key == 'attributeNotFoundInOutput' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Classes with attributes that have no output attribute equivalent:')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(self.tr('Class: ')+cl+'\n')
                        valueList = '('+','.join(invalidatedDataDict[key][cl])+')\n'
                        self.signals.updateLog.emit(valueList)
                
        return hasErrors

    def translateAbstractDbLayerNameToOutputFormat(self,lyr,outputAbstractDb):
        return None
    
    def translateOGRLayerNameToOutputFormat(self,lyr,ogrOutput):
        return None
    
    def getTableSchema(self,lyr):
        return None
            
    def buildReadSummary(self,inputOgrDb,outputAbstractDb,classList):
        self.signals.clearLog.emit() #Clears log
        inputType = self.conversionTypeDict[self.db.driverName()]
        outputType = self.conversionTypeDict[outputAbstractDb.db.driverName()]
        self.signals.updateLog.emit(self.tr('Conversion type: ')+inputType+'2'+outputType+'\n')
        self.signals.updateLog.emit('\n'+self.tr('Input database: ')+self.db.databaseName()+'\n')
        self.signals.updateLog.emit('\n'+self.tr('Output database: ')+outputAbstractDb.db.databaseName()+'\n')
        self.signals.updateLog.emit('\n'+'{:-^60}'.format(self.tr('Read Summary')))
        self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Elements')+'\n\n')
        for cl in classList:
            self.signals.updateLog.emit('{:<50}'.format(cl)+str(inputOgrDb.GetLayerByName(str(cl)).GetFeatureCount())+'\n')
        return None
    
    def makeTranslationMap(self, layerName, layer, outLayer, fieldMapper):
        layerFieldMapper=fieldMapper[layerName]
        layerDef = layer.GetLayerDefn()
        outLayerDef = outLayer.GetLayerDefn()
        panMap = []        
        for i in range(layerDef.GetFieldCount()):
            featureDef = layerDef.GetFieldDefn(i)
            fieldName = featureDef.GetName()
            if fieldName in layerFieldMapper.keys():
                name = layerFieldMapper[fieldName]
                fieldId = outLayerDef.GetFieldIndex(name)
                panMap.append(fieldId) 
            else:
                panMap.append(-1)
        return panMap
    
    def translateLayer(self, inputLayer, inputLayerName, outputLayer, outputFileName, layerPanMap, errorDict, defaults={}, translateValues={}):
        inputLayer.ResetReading()
        inSpatialRef = inputLayer.GetSpatialRef()
        outSpatialRef = outputLayer.GetSpatialRef()
        coordTrans = None
        if inSpatialRef <> outSpatialRef:
            coordTrans = osr.CoordinateTransformation(inSpatialRef, outSpatialRef)
        initialCount = outputLayer.GetFeatureCount()
        count = 0
        feat=inputLayer.GetNextFeature()
        #for feat in inputLayer:
        while feat:
            inputId = feat.GetFID()
            newFeat=ogr.Feature(outputLayer.GetLayerDefn())
            newFeat.SetFromWithMap(feat,True,layerPanMap)
            if newFeat.geometry().GetGeometryCount() > 1:
                #Deaggregator
                for geom in newFeat.geometry():
                    auxGeom = ogr.Geometry(newFeat.geometry().GetGeometryType())
                    auxGeom.AssignSpatialReference(newFeat.geometry().GetSpatialReference())
                    auxGeom.AddGeometry(geom)
                    if coordTrans <> None:
                        auxGeom.Transform(coordTrans)
                    newFeat.SetGeometry(auxGeom)
                    out=outputLayer.CreateFeature(newFeat)
                    if out <> 0:
                        self.utils.buildNestedDict(errorDict, [inputLayerName], [inputId])
                    else:
                        count += 1
            else:
                if coordTrans <> None:
                    geom = feat.GetGeometryRef()
                    geom.Transform(coordTrans)
                    newFeat.SetGeometry(geom)
                out=outputLayer.CreateFeature(newFeat)
                if out <> 0:
                    self.utils.buildNestedDict(errorDict, [inputLayerName], [inputId])
                else:
                    count += 1
            feat=inputLayer.GetNextFeature()
            
        return count
    
    def translateDS(self, inputDS, outputDS, fieldMap, inputLayerList, errorDict,invalidated=None): 
        self.signals.updateLog.emit('\n'+'{:-^60}'.format(self.tr('Write Summary')))
        self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Elements')+'\n\n')
        status = False
        for inputLyr in inputLayerList.keys():
            schema = self.getTableSchema(inputLyr)
            attrList = fieldMap[inputLyr].keys()
            
            #sql = self.gen.getFeaturesWithSQL(inputLyr,attrList) #order elements here
            #inputOgrLayer = inputDS.ExecuteSQL(sql.encode('utf-8'))
            #Here I had to change the way of loading because of features ids. I need to use inputDs.GetLayerByName
            
            inputOgrLayer = inputDS.GetLayerByName(str(inputLyr)) #new way of loading layer. The old way was an attempt to make a general rule for conversion between edgv versions
            outputFileName = self.translateOGRLayerNameToOutputFormat(inputLyr,outputDS)
            outputLayer=outputDS.GetLayerByName(outputFileName)
            #order conversion here
            layerPanMap=self.makeTranslationMap(inputLyr, inputOgrLayer,outputLayer, fieldMap)
            ini = outputLayer.GetFeatureCount()
            if invalidated == None:
                iter=self.translateLayer(inputOgrLayer, inputLyr, outputLayer, outputFileName, layerPanMap, errorDict)
            else:
                needsFix = False
                for keyDict in invalidated.values():
                    if len(keyDict) > 0:
                        if type(keyDict) == list:
                            if inputLyr in keyDict:
                                needsFix = True
                        if type(keyDict) == dict:
                            if inputLyr in keyDict.keys():
                                needsFix = True
                                break
                if needsFix:
                    iter = self.translateLayerWithDataFix(inputOgrLayer, inputLyr, outputLayer, outputFileName, layerPanMap, invalidated, errorDict)
                else:
                    iter=self.translateLayer(inputOgrLayer, inputLyr, outputLayer, outputFileName, layerPanMap, errorDict)
            if iter == -1:
                status = False
                self.signals.updateLog.emit('{:<50}'.format(self.tr('Error on layer ')+inputLyr+self.tr('. Conversion not performed.')+'\n'))
                return status
            diff = outputLayer.GetFeatureCount()-ini
            if iter == diff:
                status = True
            else:
                status = False
            self.signals.updateLog.emit('{:<50}'.format(str(outputFileName))+str(diff)+'\n')
        self.writeErrorLog(errorDict)
        outputDS.Destroy()
        return status
    
    def buildInvalidatedDict(self):
        invalidated = dict()
        invalidated['nullLine'] = dict()       
        invalidated['nullPk'] = dict()
        invalidated['notInDomain'] = dict()
        invalidated['nullAttribute'] = dict()
        invalidated['classNotFoundInOutput'] = []
        invalidated['attributeNotFoundInOutput'] = dict()
        return invalidated
    
    def prepareForConversion(self,outputAbstractDb):
        try:
            self.checkAndOpenDb()
            outputAbstractDb.checkAndOpenDb()
        except:
            return (None, None, dict(), [], dict())
        fieldMap = self.buildFieldMap()
        inputOgrDb = self.buildOgrDatabase()
        outputOgrDb = outputAbstractDb.buildOgrDatabase()
        inputLayerList = self.listClassesWithElementsFromDatabase()
        errorDict = dict()
        self.buildReadSummary(inputOgrDb,outputAbstractDb,inputLayerList)
        return (inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict)

    def translateLayerWithDataFix(self, inputLayer, inputLayerName, outputLayer, outputFileName, layerPanMap, invalidated, errorDict, defaults={}, translateValues={}):
        '''casos e tratamentos:
        1. nullLine: os atributos devem ser varridos e, caso seja linha nula, ignorar o envio
        2. nullPk: caso seja complexo, gerar uma chave
        3. notInDomain: excluir do mapeamento aquele atributo caso ele seja mapeado
        4. nullAttribute: excluir do mapeamento aquele atributo caso ele seja não nulo
        5. classNotFoundInOutput: pular classe na conversão e mostrar no warning
        6. attributeNotFoundInOutput: pular atributo e mostrar no warning para todas as feicoes
        '''
        inputLayer.ResetReading()
        fieldCount = inputLayer.GetLayerDefn().GetFieldCount()
        initialCount = outputLayer.GetFeatureCount()
        inSpatialRef = inputLayer.GetSpatialRef()
        outSpatialRef = outputLayer.GetSpatialRef()
        coordTrans = None
        if inSpatialRef <> outSpatialRef:
            coordTrans = osr.CoordinateTransformation(inSpatialRef, outSpatialRef)
        count = 0
        feat=inputLayer.GetNextFeature()
        (schema,className) = self.getTableSchema(inputLayerName)
        outputOgrLyrDict = self.getOgrLayerIndexDict(outputLayer)
        if inputLayerName not in invalidated['classNotFoundInOutput']:
            while feat:
                nullLine = True
                #Case 1: nullLine
                for i in range(fieldCount):
                    if feat.GetField(i) <> None:
                        nullLine = False
                        break
                if feat.GetFID() <> -1 or feat.geometry() <> None:
                    nullLine = False
                if not nullLine:
                    if inputLayerName not in invalidated['classNotFoundInOutput']:
                        newFeat=ogr.Feature(outputLayer.GetLayerDefn())
                        inputId = feat.GetFID()
                        #Case 2: nullPk in complex:
                        newFeat.SetFromWithMap(feat,True,layerPanMap)
                        if schema == 'complexos' and feat.GetFID() == -1:
                            newFeat.SetFID(uuid4())
                        #Case 3
                        for j in range(inputLayer.GetLayerDefn().GetFieldCount()):
                            if layerPanMap[j] <> -1:
                                if inputLayerName in invalidated['notInDomain'].keys():
                                    if inputId in invalidated['notInDomain'][inputLayerName].keys():
                                        if outputLayer.GetLayerDefn().GetFieldDefn(layerPanMap[j]).GetName() in invalidated['notInDomain'][inputLayerName][inputId].keys():
                                            newFeat.UnsetField(layerPanMap[j])
                                if inputLayerName in invalidated['nullAttribute'].keys():
                                    if inputId in invalidated['nullAttribute'][inputLayerName].keys():
                                        if outputLayer.GetLayerDefn().GetFieldDefn(layerPanMap[j]).GetName() in invalidated['nullAttribute'][inputLayerName][inputId].keys():
                                            if outputLayer.GetLayerDefn().GetFieldDefn(layerPanMap[j]).GetTypeName() == 'String':
                                                newFeat.SetField(layerPanMap[j],'-9999')
                                            if outputLayer.GetLayerDefn().GetFieldDefn(layerPanMap[j]).GetTypeName() == 'Integer':
                                                newFeat.SetField(layerPanMap[j],-9999)
                        if newFeat.geometry().GetGeometryCount() > 1:
                            #Deaggregator
                            for geom in newFeat.geometry():
                                auxGeom = ogr.Geometry(newFeat.geometry().GetGeometryType())
                                auxGeom.AssignSpatialReference(newFeat.geometry().GetSpatialReference())
                                auxGeom.AddGeometry(geom)
                                if coordTrans <> None:
                                    auxGeom.Transform(coordTrans)
                                newFeat.SetGeometry(auxGeom)
                                out=outputLayer.CreateFeature(newFeat)
                                if out <> 0:
                                    self.utils.buildNestedDict(errorDict, [inputLayerName], [inputId])
                                else:
                                    count += 1
                        else:
                            if coordTrans <> None:
                                geom = feat.GetGeometryRef()
                                geom.Transform(coordTrans)
                                newFeat.SetGeometry(geom)
                            out=outputLayer.CreateFeature(newFeat)
                            if out <> 0:
                                self.utils.buildNestedDict(errorDict, [inputLayerName], [inputId])
                            else:
                                count += 1
                feat=inputLayer.GetNextFeature()
            return count
        else:
            return -1
    
    def buildOgrDatabase(self):
        con = self.makeOgrConn()
        ogrDb = ogr.Open(con,update=1)
        return ogrDb
    
    def reorderTupleList(self,ls):
        if 'OGC_FID' in ls:
            idField = 'OGC_FID'
        else:
            idField = 'id'
        index = ls.index(idField)
        reordered = [ls[index]]
        reordered.extend(ls[0:index])
        reordered.extend(ls[index+1::])
        return reordered
    
    def getOgrLayerIndexDict(self,lyr):
        ogrDict = dict()
        layerDef = lyr.GetLayerDefn()
        for i in range(layerDef.GetFieldCount()):
            ogrDict[i] = layerDef.GetFieldDefn(i).GetName() 
        return ogrDict
    
    def writeErrorLog(self,errorDict):
        errorClasses = errorDict.keys()
        if len(errorClasses)>0:
            self.signals.updateLog.emit('\n'+'{:-^60}'.format(self.tr('Features not converted')))
            self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Feature id')+'\n\n')
            for cl in errorClasses:
                for id in errorDict[cl]:
                    self.signals.updateLog.emit('\n\n'+'{:<50}'.format(cl+str(id)))
        return None
    
    def getQmlDir(self):
        try:
            self.checkAndOpenDb()
        except:
            return ''
        currentPath = os.path.dirname(__file__)
        if qgis.core.QGis.QGIS_VERSION_INT >= 20600:
            qmlVersionPath = os.path.join(currentPath, '..', '..', 'Qmls', 'qgis_26')
        else:
            qmlVersionPath = os.path.join(currentPath, '..', '..', 'Qmls', 'qgis_22')

        version = self.getDatabaseVersion()
        if version == '3.0':
            qmlPath = os.path.join(qmlVersionPath, 'edgv_30')
        elif version == '2.1.3':
            qmlPath = os.path.join(qmlVersionPath, 'edgv_213')
        elif version == 'FTer_2a_Ed':
            qmlPath = os.path.join(qmlVersionPath, 'FTer_2a_Ed')
        
        else:
            qmlPath = ''
        return qmlPath
    
    def obtainLinkColumn(self, complexClass, aggregatedClass):
        return None
    
    def loadAssociatedFeatures(self, complex):
        return None
    
    def isComplexClass(self, className):
        return None
    
    def disassociateComplexFromComplex(aggregated_class, link_column, id):
        pass
    
    def getUsers(self):
        return None
    
    def getUserRelatedRoles(self, username):
        return None
    
    def getRoles(self):
        return None

    def createRole(self, role, dict):
        pass
    
    def dropRole(self, role):
        pass

    def alterUserPass(self, user, newpassword):
        pass

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

    def removeUser(self, user):
        pass

    def grantRole(self, user, role):
        pass

    def revokeRole(self, user, role):
        pass

    def getTablesFromDatabase(self):
        return None

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

    def getEDGVDbsFromServer(self,name):
        return None

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

    def dropDatabase(self,abstractCandidate):
        return None

    def createResolvedDomainViews(self, createViewClause, fromClause):
        pass
    
    def getSqlViewFile(self):
        pass
示例#36
0
class ChangeFilterWidget(QtGui.QWidget, FORM_CLASS):
    populateSingleValue = pyqtSignal()
    populateListValue = pyqtSignal()

    def __init__(self, abstractDb, uiParameterJsonDict=None, parent=None):
        """Constructor."""
        super(self.__class__, self).__init__(parent)
        self.abstractDb = abstractDb
        self.setupUi(self)
        self.jsonBuilder = CustomJSONBuilder()
        self.populateSchemaCombo()
        self.hideWidgetList([
            self.singleValueLabel, self.singleValueComboBox,
            self.actionComboBox
        ])
        self.singleAttribute = True
        self.filterCustomSelectorWidget.setTitle(
            self.tr('Select filter values'))
        self.populateSingleValue.connect(self.populateWidgetWithSingleValue)
        self.populateListValue.connect(self.populateWidgetWithListValue)
        geomTypeDict = self.abstractDb.getGeomTypeDict()
        geomDict = self.abstractDb.getGeomDict(geomTypeDict)
        self.domainDict = self.abstractDb.getDbDomainDict(geomDict)
        self.inhTree = self.abstractDb.getInheritanceTreeDict()
        self.utils = Utils()
        self.actionDict = {
            self.tr('Add to Filter (Leave empty if filter is empty)'):
            'addEmpty',
            self.tr('Add to Filter (Add value to empty filter)'): 'add',
            self.tr('Remove from Filter'): 'remove'
        }
        self.populateFromUiParameterJsonDict(uiParameterJsonDict)

    def populateFromUiParameterJsonDict(self, uiParameterJsonDict):
        """
        {
            'schemaComboBox': --current text of schemaComboBox --
            'tableComboBox': ---current text of tableComboBox --
            'attributeComboBox': ---current text of attributeComboBox --
            'allAttributesCheckBox': --current state of allAttributesCheckBox--
            'allTablesCheckBox': --current state of allTablesCheckBox--
            'filterCustomSelectorWidgetToList': [--list of selected values on filterCustomSelectorWidget--]
            'singleValueComboBox': --current text of singleValueComboBox--
            'actionComboBoxIdx': --current index of actionComboBoxIdx--
        }
        """
        if uiParameterJsonDict:
            if uiParameterJsonDict['allTablesCheckBox']:
                self.allTablesCheckBox.setCheckState(Qt.Checked)
                singleValueIdx = self.singleValueComboBox.findText(
                    uiParameterJsonDict['singleValueComboBox'],
                    flags=Qt.MatchExactly)
                self.singleValueComboBox.setCurrentIndex(singleValueIdx)
                self.actionComboBox.setCurrentIndex(
                    uiParameterJsonDict['actionComboBoxIdx'])
            else:
                schemaIdx = self.schemaComboBox.findText(
                    uiParameterJsonDict['schemaComboBox'],
                    flags=Qt.MatchExactly)
                self.schemaComboBox.setCurrentIndex(schemaIdx)
                tableIdx = self.tableComboBox.findText(
                    uiParameterJsonDict['tableComboBox'],
                    flags=Qt.MatchExactly)
                self.tableComboBox.setCurrentIndex(tableIdx)
                if uiParameterJsonDict['allAttributesCheckBox']:
                    self.allAttributesCheckBox.setCheckState(Qt.Checked)
                    singleValueIdx = self.singleValueComboBox.findText(
                        uiParameterJsonDict['singleValueComboBox'],
                        flags=Qt.MatchExactly)
                    self.singleValueComboBox.setCurrentIndex(singleValueIdx)
                    self.actionComboBox.setCurrentIndex(
                        uiParameterJsonDict['actionComboBoxIdx'])
                else:
                    attributeIdx = self.attributeComboBox.findText(
                        uiParameterJsonDict['attributeComboBox'],
                        flags=Qt.MatchExactly)
                    self.attributeComboBox.setCurrentIndex(attributeIdx)
                    self.filterCustomSelectorWidget.selectItems(
                        True,
                        selectedItems=uiParameterJsonDict[
                            'filterCustomSelectorWidgetToList'])

    def populateInheritanceTree(self, nodeList):
        self.treeWidget.clear()
        rootNode = self.treeWidget.invisibleRootItem()
        for node in nodeList:
            firstNonRootNode = self.utils.find_all_paths(
                self.inhTree, 'root', node)[0][1]
            self.utils.createTreeWidgetFromDict(
                rootNode,
                {firstNonRootNode: self.inhTree['root'][firstNonRootNode]},
                self.treeWidget, 0)
        self.treeWidget.sortItems(0, Qt.AscendingOrder)
        self.treeWidget.expandAll()

    def populateSchemaCombo(self):
        self.schemaComboBox.clear()
        self.schemaComboBox.addItem(self.tr('Select a schema'))
        schemaList = self.abstractDb.getGeometricSchemaList()
        for schema in schemaList:
            if schema not in ['views', 'validation']:
                self.schemaComboBox.addItem(schema)

    def hideWidgetList(self, widgetList):
        for widget in widgetList:
            widget.hide()

    def showWidgetList(self, widgetList):
        for widget in widgetList:
            widget.show()

    @pyqtSlot(int)
    def on_schemaComboBox_currentIndexChanged(self, idx):
        if idx == 0:
            self.tableComboBox.clear()
            self.tableComboBox.setEnabled(False)
            self.attributeComboBox.clear()
            self.attributeComboBox.setEnabled(False)
        else:
            schema = self.schemaComboBox.currentText()
            self.tableComboBox.setEnabled(True)
            self.tableComboBox.clear()
            self.tableComboBox.addItem(self.tr('Select a table'))
            tableList = self.abstractDb.getGeometricTableListFromSchema(schema)
            for table in tableList:
                self.tableComboBox.addItem(table)

    @pyqtSlot(int)
    def on_tableComboBox_currentIndexChanged(self, idx):
        if idx == 0:
            self.attributeComboBox.clear()
            self.attributeComboBox.setEnabled(False)
        else:
            schema = self.schemaComboBox.currentText()
            tableName = self.tableComboBox.currentText()
            self.attributeComboBox.setEnabled(True)
            self.attributeComboBox.clear()
            self.attributeComboBox.addItem(self.tr('Select an attribute'))
            if tableName in self.domainDict.keys():
                attributeList = self.domainDict[tableName]['columns'].keys()
                for attribute in attributeList:
                    self.attributeComboBox.addItem(attribute)

    @pyqtSlot(int, name='on_schemaComboBox_currentIndexChanged')
    @pyqtSlot(int, name='on_attributeComboBox_currentIndexChanged')
    @pyqtSlot(int, name='on_tableComboBox_currentIndexChanged')
    def populateWidgetWithSingleValue(self):
        if self.allTablesCheckBox.checkState() == 2 or (
                self.allAttributesCheckBox.checkState() == 2
                and self.schemaComboBox.currentIndex() <> 0
                and self.tableComboBox.currentIndex() <> 0):
            self.attributeComboBox.clear()
            self.attributeComboBox.setEnabled(False)
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            self.singleValueComboBox.clear()
            self.singleValueComboBox.addItem(
                self.tr('Select a value to alter'))
            if self.allAttributesCheckBox.checkState() == 2:
                tableList = [self.tableComboBox.currentText()]
            else:
                tableList = self.domainDict.keys()
            allValueList = []
            idxList = []
            for tableName in tableList:
                for attrName in self.domainDict[tableName]['columns'].keys():
                    for code in self.domainDict[tableName]['columns'][
                            attrName]['values']:
                        value = self.domainDict[tableName]['columns'][
                            attrName]['values'][code]
                        if value not in allValueList:
                            allValueList.append(value)

            for value in allValueList:
                for tableName in tableList:
                    for attrName in self.domainDict[tableName]['columns'].keys(
                    ):
                        if value not in self.domainDict[tableName]['columns'][
                                attrName]['values'].values():
                            idx = allValueList.index(value)
                            if idx not in idxList:
                                idxList.append(idx)
            idxList.sort(reverse=True)
            for idx in idxList:
                allValueList.pop(idx)
            for value in allValueList:
                self.singleValueComboBox.addItem(value)
            self.populateInheritanceTree(tableList)
            QApplication.restoreOverrideCursor()

    @pyqtSlot(int, name='on_schemaComboBox_currentIndexChanged')
    @pyqtSlot(int, name='on_attributeComboBox_currentIndexChanged')
    @pyqtSlot(int, name='on_tableComboBox_currentIndexChanged')
    def populateWidgetWithListValue(self):
        self.filterCustomSelectorWidget.clearAll()
        if self.allTablesCheckBox.checkState(
        ) == 2 or self.allAttributesCheckBox.checkState() == 2:
            return
        if self.schemaComboBox.currentIndex() == 0:
            return
        if self.tableComboBox.currentIndex() == 0:
            self.treeWidget.clear()
            return
        tableName = self.tableComboBox.currentText()
        self.populateInheritanceTree([tableName])
        if self.attributeComboBox.currentIndex() == 0:
            return
        filterList = []
        attributeName = self.attributeComboBox.currentText()
        tableFilter = []
        filterToList = []
        if tableName in self.domainDict.keys():
            if attributeName in self.domainDict[tableName]['columns'].keys():
                attrDomainDict = self.domainDict[tableName]['columns'][
                    attributeName]['values']
                tableFilter = self.domainDict[tableName]['columns'][
                    attributeName]['constraintList']
                filterToList = [attrDomainDict[i] for i in tableFilter]
                filterFromList = [
                    i for i in attrDomainDict.values() if i not in filterToList
                ]
                self.filterCustomSelectorWidget.setFromList(filterFromList,
                                                            unique=True)
                self.filterCustomSelectorWidget.setToList(filterToList)

    @pyqtSlot(int)
    def on_allTablesCheckBox_stateChanged(self, state):
        self.hideOrShowWidgets()
        if state == 0:
            self.allAttributesCheckBox.setEnabled(True)
            self.schemaComboBox.setCurrentIndex(0)
            self.schemaComboBox.setEnabled(True)
        elif state == 2:
            self.allAttributesCheckBox.setEnabled(False)
            self.allAttributesCheckBox.setCheckState(0)
            self.schemaComboBox.setCurrentIndex(0)
            self.schemaComboBox.setEnabled(False)

    @pyqtSlot(int)
    def on_allAttributesCheckBox_stateChanged(self, state):
        if state == 2:
            self.allTablesCheckBox.setEnabled(False)
            self.allTablesCheckBox.setCheckState(0)
            self.attributeComboBox.setCurrentIndex(0)
            self.attributeComboBox.setEnabled(False)
        if state == 0:
            self.allTablesCheckBox.setEnabled(True)
            self.attributeComboBox.setEnabled(True)
        self.hideOrShowWidgets()

    def hideOrShowWidgets(self):
        if self.allAttributesCheckBox.checkState(
        ) == 2 or self.allTablesCheckBox.checkState() == 2:
            self.filterCustomSelectorWidget.hide()
            self.singleValueLabel.show()
            self.singleValueComboBox.show()
            self.actionComboBox.show()
            self.populateSingleValue.emit()
        else:
            self.filterCustomSelectorWidget.show()
            self.singleValueLabel.hide()
            self.singleValueComboBox.hide()
            self.actionComboBox.hide()
            self.tableComboBox.currentIndexChanged.emit(
                self.tableComboBox.currentIndex())
            self.populateListValue.emit()

    def getTitle(self):
        return self.title

    def setTitle(self, title):
        self.title = title

    def validate(self):
        if self.allTablesCheckBox.checkState() == 2:
            if self.singleValueComboBox.currentIndex() == 0:
                return False
            if self.actionComboBox.currentIndex() == 0:
                return False
        elif self.allAttributesCheckBox.checkState() == 2:
            if self.singleValueComboBox.currentIndex() == 0:
                return False
            if self.actionComboBox.currentIndex() == 0:
                return False
            if self.schemaComboBox.currentIndex() == 0:
                return False
            if self.tableComboBox.currentIndex() == 0:
                return False
        else:
            if self.schemaComboBox.currentIndex() == 0:
                return False
            if self.tableComboBox.currentIndex() == 0:
                return False
            if self.attributeComboBox.currentIndex() == 0:
                return False
        return True

    def validateDiagnosis(self):
        invalidatedReason = ''
        if self.allTablesCheckBox.checkState() == 2:
            if self.singleValueComboBox.currentIndex() == 0:
                invalidatedReason += self.tr('A value must be chosen.\n')
            if self.actionComboBox.currentIndex() == 0:
                invalidatedReason += self.tr('An action must be chosen.\n')
        elif self.allAttributesCheckBox.checkState() == 2:
            if self.singleValueComboBox.currentIndex() == 0:
                invalidatedReason += self.tr('A value must be chosen.\n')
            if self.actionComboBox.currentIndex() == 0:
                invalidatedReason += self.tr('An action must be chosen.\n')
            if self.schemaComboBox.currentIndex() == 0:
                invalidatedReason += self.tr('A schema must be chosen.\n')
            if self.tableComboBox.currentIndex() == 0:
                invalidatedReason += self.tr('A table must be chosen.\n')
        else:
            if self.schemaComboBox.currentIndex() == 0:
                invalidatedReason += self.tr('A schema must be chosen.\n')
            if self.tableComboBox.currentIndex() == 0:
                invalidatedReason += self.tr('A table must be chosen.\n')
            if self.attributeComboBox.currentIndex() == 0:
                invalidatedReason += self.tr('An attribute must be chosen.\n')
        return invalidatedReason

    def getJSONTag(self):
        if not self.validate():
            raise Exception(
                self.tr('Error in change filter customization ') + self.title +
                ' : ' + self.validateDiagnosis())
        jsonList = []
        inhConstrDict = self.abstractDb.getInheritanceConstraintDict()
        if self.allAttributesCheckBox.checkState() == 2:
            tableName = self.tableComboBox.currentText()
            schema = self.schemaComboBox.currentText()
            self.batchGetJsonTag(schema, tableName, jsonList, inhConstrDict)
        elif self.allTablesCheckBox.checkState() == 2:
            tableList = self.inhTree['root'].keys()
            for tableName in tableList:
                schema = self.abstractDb.getTableSchemaFromDb(tableName)
                self.batchGetJsonTag(schema, tableName, jsonList,
                                     inhConstrDict)
        else:
            tableName = self.tableComboBox.currentText()
            schema = self.schemaComboBox.currentText()
            attrName = self.attributeComboBox.currentText()
            if tableName in self.domainDict.keys():
                if attrName in self.domainDict[tableName]['columns'].keys():
                    attrDomainDict = self.domainDict[tableName]['columns'][
                        attrName]['values']
                    isMulti = self.domainDict[tableName]['columns'][attrName][
                        'isMulti']
            newFilter = [
                i for i in attrDomainDict.keys()
                if attrDomainDict[i] in self.filterCustomSelectorWidget.toLs
            ]
            self.getJsonTagFromOneTable(schema, tableName, attrName, jsonList,
                                        inhConstrDict, newFilter, isMulti)
        return jsonList

    def batchGetJsonTag(self, schema, tableName, jsonList, inhConstrDict):
        if tableName in self.domainDict.keys():
            for attrName in self.domainDict[tableName]['columns'].keys():
                attrDomainDict = self.domainDict[tableName]['columns'][
                    attrName]['values']
                isMulti = self.domainDict[tableName]['columns'][attrName][
                    'isMulti']
                newFilter = self.domainDict[tableName]['columns'][attrName][
                    'constraintList']
                valueText = self.singleValueComboBox.currentText()
                code = [
                    i for i in attrDomainDict.keys()
                    if attrDomainDict[i] == valueText
                ][0]
                if self.actionDict[self.actionComboBox.currentText()] == 'add':
                    if code not in newFilter: newFilter.append(code)
                elif self.actionDict[
                        self.actionComboBox.currentText()] == 'addEmpty':
                    if newFilter == []:
                        continue
                else:
                    if code in newFilter: newFilter.pop(code)
                self.getJsonTagFromOneTable(schema, tableName, attrName,
                                            jsonList, inhConstrDict, newFilter,
                                            isMulti)

    def getJsonTagFromOneTable(self, schema, tableName, attrName, jsonList,
                               inhConstrDict, newFilter, isMulti):
        originalFilterList = []
        if tableName in inhConstrDict.keys():
            if attrName in inhConstrDict[tableName].keys():
                originalFilterList = inhConstrDict[tableName][attrName]
        if originalFilterList == newFilter: return
        elif originalFilterList <> []:
            for item in originalFilterList:
                newElement = self.jsonBuilder.alterFilterElement(
                    item['schema'], item['tableName'], attrName,
                    item['constraintName'], item['filter'], newFilter, isMulti)
                if newElement not in jsonList:
                    jsonList.append(newElement)
        else:
            nodeLineage = self.utils.getNodeLineage(tableName, self.inhTree)
            firstInLineage = None
            for node in nodeLineage:
                if node in self.domainDict.keys():
                    if attrName in self.domainDict[node]['columns'].keys():
                        firstInLineage = node
                        break
                else:
                    schema = self.abstractDb.getTableSchemaFromDb(node)
                    if node in self.abstractDb.getAttributeListFromTable(
                            schema, node):
                        firstInLineage = node
                        break
            newElement = self.jsonBuilder.alterFilterElement(
                schema, firstInLineage, attrName,
                '_'.join([firstInLineage, attrName,
                          'ks']), [], newFilter, isMulti)
            if newElement not in jsonList:
                jsonList.append(newElement)

    def getUiParameterJsonDict(self):
        """
        builds a dict with the following format:
        {
            'schemaComboBox': --current text of schemaComboBox --
            'tableComboBox': ---current text of tableComboBox --
            'attributeComboBox': ---current text of attributeComboBox --
            'allAttributesCheckBox': --current state of allAttributesCheckBox--
            'allTablesCheckBox': --current state of allTablesCheckBox--
            'filterCustomSelectorWidgetToList': [--list of selected values on filterCustomSelectorWidget--]
            'singleValueComboBox': --current text of singleValueComboBox--
            'actionComboBoxIdx': --current index of actionComboBox--
        }
        """
        uiParameterJsonDict = dict()
        uiParameterJsonDict[
            'schemaComboBox'] = self.schemaComboBox.currentText()
        uiParameterJsonDict['tableComboBox'] = self.tableComboBox.currentText()
        uiParameterJsonDict[
            'attributeComboBox'] = self.attributeComboBox.currentText()
        uiParameterJsonDict[
            'allAttributesCheckBox'] = self.allAttributesCheckBox.isChecked()
        uiParameterJsonDict[
            'allTablesCheckBox'] = self.allTablesCheckBox.isChecked()
        uiParameterJsonDict[
            'filterCustomSelectorWidgetToList'] = self.filterCustomSelectorWidget.toLs
        uiParameterJsonDict[
            'singleValueComboBox'] = self.singleValueComboBox.currentText()
        uiParameterJsonDict[
            'actionComboBoxIdx'] = self.actionComboBox.currentIndex()
        return uiParameterJsonDict
class CreateInomDialog(QtGui.QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(CreateInomDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        self.iface = iface
        #Sql factory generator
        self.isSpatialite = True
        self.tabWidget.setCurrentIndex(0)
        self.factory = SqlGeneratorFactory()
        self.gen = self.factory.createSqlGenerator(self.isSpatialite)

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

        self.restoreInitialState()

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

        self.map_index = UtmGrid()

        self.disableAll()

        self.setValidCharacters()

        self.setMask()

    def __del__(self):
        self.closeDatabase()

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

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

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

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

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

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

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

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

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

        return None

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    @pyqtSlot(bool)
    def on_inomRadioButton_toggled(self, toggled):
        if toggled:
            self.inomLineEdit.setEnabled(True)
        else:
            self.inomLineEdit.setEnabled(False)
示例#38
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
示例#39
0
class SetupEarthCoverage(QtGui.QWizard, FORM_CLASS):
    coverageChanged = pyqtSignal()
    def __init__(self, edgvVersion, areas, lines, oldCoverage, propertyList, enableSetupFromFile = True, onlySetup = False, propertyName = None, parent=None):
        """
        Constructor
        """
        super(self.__class__, self).__init__()
        self.setupUi(self)
        self.utils = Utils()
        self.areas = areas
        self.lines = lines
        self.propertyName = propertyName
        self.edgvVersion = edgvVersion
        self.areasCustomSelector.setTitle(self.tr('Areas'))
        self.linesCustomSelector.setTitle(self.tr('Lines'))
        self.propertyList = propertyList
        self.button(QtGui.QWizard.NextButton).clicked.connect(self.buildTree)
        self.button(QtGui.QWizard.FinishButton).clicked.connect(self.buildDict)
        self.setupWizard(oldCoverage, enableSetupFromFile)
        self.configDict = dict()

    def setupFromFile(self):
        """
        Opens a earth coverage file
        """
        if QMessageBox.question(self, self.tr('Question'), self.tr('Do you want to open an earth coverage file?'), QMessageBox.Ok|QMessageBox.Cancel) == QMessageBox.Cancel:
            return
        filename = QFileDialog.getOpenFileName(self, self.tr('Open Earth Coverage Setup configuration'), '', self.tr('Earth Coverage Files (*.json)'))
        return filename

    def setupWizard(self, oldCoverage, enableSetupFromFile):
        """
        Prepares the wizard
        oldCoverage: old configuration
        """
        if oldCoverage:
            # self.abstractDb.dropCentroids(oldCoverage.keys())
            self.setupUiFromDict(oldCoverage)
            return
        else:
            self.populateFrameListWidget(self.areas)
        if enableSetupFromFile:
            filename = self.setupFromFile()
        else:
            filename = None
        if filename:
            self.setupUiFromFile(filename)
        else:
            self.areasCustomSelector.setFromList(self.areas)
            self.linesCustomSelector.setFromList(self.lines)
        if self.propertyName:
            self.nameLineEdit.setText(self.propertyName)
            self.nameLineEdit.setEnabled(False)
    
    def setupUiFromFile(self, filename):
        """
        Populates ui from parameters of json
        """
        #read json
        jsonDict = self.utils.readJsonFile(filename)
        self.setupUiFromDict(jsonDict)

    def setupUiFromDict(self, jsonDict):
        """
        Populates ui from parameters of json
        """
        #set nameLineEdit
        self.nameLineEdit.setText(jsonDict['configName'])
        #populate listWidget
        self.populateFrameListWidget(self.areas, frame = jsonDict['frameLayer'])
        linesFromList, linesToList, areasFromList, areasToList = self.populateLists(jsonDict['earthCoverageDict'])
        self.areasCustomSelector.setToList(areasToList)
        self.areasCustomSelector.setFromList(areasFromList)
        self.linesCustomSelector.setToList(linesToList)
        self.linesCustomSelector.setFromList(linesFromList)
        self.buildTree()
        self.checkDelimiters(jsonDict['earthCoverageDict'])
    
    def populateFrameListWidget(self, areas, frame = None):
        areas.sort()
        self.listWidget.clear()
        self.listWidget.addItems(areas)
        if frame:
            try:
                frameItem = self.listWidget.findItems(frame, Qt.MatchExactly)[0]
                self.listWidget.setCurrentItem(frameItem)
            except:
                pass
    
    def populateLists(self, setupDict):
        areasToList = setupDict.keys()
        linesToList = []
        for key in areasToList:
            lines = setupDict[key]
            for line in lines:
                if line not in linesToList:
                    linesToList.append(line)
        areasFromList = [area for area in self.areas if area not in areasToList]
        linesFromList = [line for line in self.lines if line not in linesToList]
        return linesFromList, linesToList, areasFromList, areasToList

    def checkDelimiters(self, setupDict):
        """
        Check delimiters
        """
        for i in range(self.treeWidget.invisibleRootItem().childCount()):
            areaItem = self.treeWidget.invisibleRootItem().child(i)
            for j in range(self.treeWidget.invisibleRootItem().child(i).childCount()):
                delimiterItem = areaItem.child(j)
                if areaItem.text(0) in setupDict.keys():
                    if delimiterItem.text(1) not in setupDict[areaItem.text(0)]:
                        delimiterItem.setCheckState(1,Qt.Unchecked)

    def loadJson(self, filename):
        """
        Loads a json file
        """
        filename = QFileDialog.getOpenFileName(self, self.tr('Open Field Setup configuration'), self.folder, self.tr('Earth Coverage Setup File (*.dsgearthcov)'))
        if not filename:
            return
        return self.readJsonFile(filename)

    def populateClasses(self):
        """
        Populates area classes
        """
        self.treeWidget.clear()
        selectedAreaClasses = self.areasCustomSelector.toLs
        for i in range(len(selectedAreaClasses)):
            treeItem = QtGui.QTreeWidgetItem()
            treeItem.setText(0,selectedAreaClasses[i])
            self.treeWidget.insertTopLevelItem(0,treeItem)

    def populateDelimiters(self):
        """
        Populates line classes (area delimiters)
        """
        delimiterList = []
        for i in range(self.linesCustomSelector.toList.__len__()):
            delimiterList.append(self.linesCustomSelector.toList.item(i).text())
        for i in range(self.treeWidget.invisibleRootItem().childCount()):
            for delimiter in delimiterList:
                treeItem = QtGui.QTreeWidgetItem(self.treeWidget.invisibleRootItem().child(i))
                treeItem.setText(1,delimiter)
                treeItem.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                treeItem.setCheckState(1,Qt.Checked)
            self.treeWidget.invisibleRootItem().child(i).setExpanded(True)

    def getEarthCoverageDictFromTree(self):
        """
        Gets earth coverage configuration from the tree widget
        """
        invRootItem = self.treeWidget.invisibleRootItem()
        earthCoverageDict = dict()
        for i in range(invRootItem.childCount()):
            childClass = invRootItem.child(i)
            earthCoverageDict[childClass.text(0)] = []
            for j in range(childClass.childCount()):
                if childClass.child(j).checkState(1) == Qt.Checked:
                    earthCoverageDict[childClass.text(0)].append(childClass.child(j).text(1))
        return earthCoverageDict
    
    def buildDict(self):
        '''
        Gets earth coverage dict from interface
        '''
        self.configDict['edgvVersion'] = self.edgvVersion
        self.configDict['configName'] = self.nameLineEdit.text()
        self.configDict['frameLayer'] = self.listWidget.currentItem().text()
        self.configDict['earthCoverageDict'] = self.getEarthCoverageDictFromTree()

    def buildTree(self):
        """
        Builds the earth coverage tree using the selected areas and lines
        """
        self.populateClasses()
        self.populateDelimiters()
        self.treeWidget.expandAll()
        self.treeWidget.header().setResizeMode(QtGui.QHeaderView.ResizeToContents)
        self.treeWidget.header().setStretchLastSection(False)
    
    def on_filterLineEdit_textChanged(self, text):
        """
        Filters the items to make it easier to spot and select them
        """
        classes = [edgvClass for edgvClass in self.areas if text in edgvClass]
        self.listWidget.clear()
        self.listWidget.addItems(classes)
        self.listWidget.sortItems()
    
    def validateEarthCoverageTreeWidget(self):
        rootNode = self.treeWidget.invisibleRootItem()
        childCount = rootNode.childCount()
        for i in range(childCount):
            areaItem = rootNode.child(i)
            lineChildCount = areaItem.childCount()
            hasSelected = False
            for j in range(lineChildCount):
                lineChild = areaItem.child(j)
                if lineChild.checkState(1) == Qt.Checked:
                    hasSelected = True
                    break
            if not hasSelected:
                return False
        return True

    def validateCurrentPage(self):
        if self.currentId() == 0:
            errorMsg = ''
            isValidated = True
            if self.nameLineEdit.text() == '':
                errorMsg += self.tr('An Earth Coverage name must be set.\n')
                isValidated = False
            if self.nameLineEdit.text() in self.propertyList:
                errorMsg += self.tr('An Earth Coverage with this name already exists.\n')
                isValidated = False
            if self.listWidget.currentRow() == -1:
                errorMsg += self.tr('A frame layer must be chosen.\n')
                isValidated = False
            if not isValidated:
                QMessageBox.warning(self, self.tr('Error!'), errorMsg)
            return isValidated
        elif self.currentId() == 1:
            if self.areasCustomSelector.toLs == []:
                errorMsg = self.tr('Areas must be chosen for Earth Coverage.\n')
                QMessageBox.warning(self, self.tr('Error!'), errorMsg)
                return False
            return True
        elif self.currentId() == 2:
            if self.linesCustomSelector.toLs == []:
                errorMsg = self.tr('Lines must be chosen for Earth Coverage.\n')
                QMessageBox.warning(self, self.tr('Error!'), errorMsg)
                return False
            return True
        elif self.currentId() == 3:
        #at least one line selected for each area
            if not self.validateEarthCoverageTreeWidget():
                errorMsg = self.tr('At least one line must be chosen for each Earth Coverage area.\n')
                QMessageBox.warning(self, self.tr('Error!'), errorMsg)
                return False
            return True
        else:
            return True
class CreateDatabaseCustomization(QtGui.QDialog, FORM_CLASS):
    def __init__(self, customizationName, abstractDb, edgvVersion, customizationManager, customJsonDict = None, parent = None):
        """Constructor."""
        super(self.__class__, self).__init__(parent)
        self.setupUi(self)
        self.customizationManager = customizationManager
        self.abstractDb = abstractDb
        self.edgvVersion = edgvVersion
        self.customizationName = customizationName
        self.contentsDict = dict()
        self.populateCustomizationCombo()
        self.setWidgetsEnabled(True)
        self.utils = Utils()
        if customJsonDict:
            self.createWidgetsFromCustomJsonDict(customJsonDict)

    def clearWidgets(self):
        rootItem = self.customizationTreeWidget.invisibleRootItem()
        childNodeCount = rootItem.childCount()
        #remove widgets
        for i in range(childNodeCount):
            typeChild = rootItem.child(i)
            childCount = typeChild.childCount()
            childTextList = []
            for j in range(childCount):
                childTextList.append(typeChild.child(i).text(0))
            for childText in childTextList:
                self.removeWidget(widgetText = childText)
    
    def setWidgetsEnabled(self, enabled):
        self.customizationSelectionComboBox.setEnabled(enabled)
        self.addAttributePushButton.setEnabled(enabled)
        self.customizationTreeWidget.setEnabled(enabled)
        self.removeSelectedPushButton.setEnabled(enabled)
    
    def populateCustomizationCombo(self):
        '''
        Populates the customization combo and also defines customDict.
        '''
        self.customDict = dict()
        self.customDict['attribute'] = self.tr('Attribute Customization')
        self.customDict['class'] = self.tr('Class Customization')
        self.customDict['codeName'] = self.tr('Code Name Customization')
        self.customDict['default'] = self.tr('Default Customization')
        self.customDict['domain'] = self.tr('Domain Customization')
        self.customDict['domainValue'] = self.tr('Domain Value Customization')
        self.customDict['nullity'] = self.tr('Attribute Nullity Customization')
        self.customDict['filter'] = self.tr('Attribute Filter Customization')
        rootNode = self.customizationTreeWidget.invisibleRootItem()
        for type in self.customDict.keys():
            if self.customDict[type] not in self.contentsDict.keys():
                self.contentsDict[self.customDict[type]] = dict()
            self.customizationSelectionComboBox.addItem(self.customDict[type])
            self.contentsDict[self.customDict[type]]['widgetList'] = []
            self.contentsDict[self.customDict[type]]['treeItem'] = self.createItem(rootNode, self.customDict[type], 0)
        self.customizationTreeWidget.expandAll()
    
    @pyqtSlot(bool)
    def on_addAttributePushButton_clicked(self):
        if self.customizationSelectionComboBox.currentText() == self.tr('Attribute Customization'):
            self.addAttributeWidget()
        elif self.customizationSelectionComboBox.currentText() == self.tr('Class Customization'):
            self.addClassWidget()
        elif self.customizationSelectionComboBox.currentText() == self.tr('Code Name Customization'):
            self.addCodeNameWidget()
        elif self.customizationSelectionComboBox.currentText() == self.tr('Default Customization'):
            self.addDefaultWidget()
        elif self.customizationSelectionComboBox.currentText() == self.tr('Domain Customization'):
            self.addDomainWidget()
        elif self.customizationSelectionComboBox.currentText() == self.tr('Domain Value Customization'):
            self.addDomainValueWidget()
        elif self.customizationSelectionComboBox.currentText() == self.tr('Attribute Nullity Customization'):
            self.addNullityWidget()
        elif self.customizationSelectionComboBox.currentText() == self.tr('Attribute Filter Customization'):
            self.addFilterWidget()
        else:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Select a custom operation!'))
    
    def addWidgetItem(self, contentsKey, widgetTitle, widget):
        widgetList = self.contentsDict[contentsKey]['widgetList']
        if len(widgetList) > 0:
            i = int(widgetList[-1].layout().itemAt(0).widget().getTitle().split('#')[-1])
        else:
            i = 0
        title = widgetTitle+' #{0}'.format(i+1) #add number
        widget.setTitle(title)
        self.contentsDict[contentsKey]['widgetList'].append(self.addWidget(widget, title))
        self.createItem(self.contentsDict[contentsKey]['treeItem'], title, 0)
    
    def addAttributeWidget(self,uiParameterJsonDict=None):
        widget = NewAttributeWidget(self.abstractDb,uiParameterJsonDict = uiParameterJsonDict)
        self.addWidgetItem(self.tr('Attribute Customization'), self.tr('New Custom Attribute'), widget)
    
    def addClassWidget(self,uiParameterJsonDict=None):
        widget = NewClassWidget(self.abstractDb,uiParameterJsonDict = uiParameterJsonDict)
        self.addWidgetItem(self.tr('Class Customization'), self.tr('New Custom Class'), widget)
    
    def addCodeNameWidget(self,uiParameterJsonDict=None):
        widget = CodeNameCustomizationWidget(self.abstractDb,uiParameterJsonDict = uiParameterJsonDict)
        self.addWidgetItem(self.tr('Code Name Customization'), self.tr('New Custom Code Name'), widget)

    def addDefaultWidget(self,uiParameterJsonDict=None):
        widget = AlterDefaultWidget(self.abstractDb,uiParameterJsonDict = uiParameterJsonDict)
        self.addWidgetItem(self.tr('Default Customization'), self.tr('New Custom Default'), widget) 

    def addDomainWidget(self,uiParameterJsonDict=None):
        widget = NewDomainWidget(self.abstractDb,uiParameterJsonDict = uiParameterJsonDict)
        self.addWidgetItem(self.tr('Domain Customization'), self.tr('New Custom Domain'), widget)

    def addDomainValueWidget(self,uiParameterJsonDict=None):
        widget = NewDomainValueWidget(self.abstractDb,uiParameterJsonDict = uiParameterJsonDict)
        self.addWidgetItem(self.tr('Domain Value Customization'), self.tr('New Domain Value'), widget)

    def addNullityWidget(self,uiParameterJsonDict=None):
        widget = ChangeNullityWidget(self.abstractDb,uiParameterJsonDict = uiParameterJsonDict)
        self.addWidgetItem(self.tr('Attribute Nullity Customization'), self.tr('New Custom Attribute Nullity'), widget)

    def addFilterWidget(self,uiParameterJsonDict=None):
        widget = ChangeFilterWidget(self.abstractDb,uiParameterJsonDict = uiParameterJsonDict)
        self.addWidgetItem(self.tr('Attribute Filter Customization'), self.tr('New Custom Attribute Filter'), widget)
    
    def addWidget(self, widget, title):
        layout = QtGui.QFormLayout()
        layout.addRow(widget)
        groupBox = QgsCollapsibleGroupBox(title)
        groupBox.setCollapsed(False)
        groupBox.setSaveCollapsedState(False)
        groupBox.setLayout(layout)
        self.scrollAreaLayout.addWidget(groupBox)
        return groupBox
    
    def createItem(self, parent, text, column):
        item = QtGui.QTreeWidgetItem(parent)
        item.setText(column, text)
        return item
    
    def getWidgetIndexFromTreeItem(self, treeItem):
        parent = treeItem.parent()
        widgetName = treeItem.text(0) 
        if not parent:
            return
        if parent == self.customizationTreeWidget.invisibleRootItem():
            return None
        childCount = parent.childCount()
        for i in range(childCount):
            child = parent.child(i)
            if child.text(0) == widgetName:
                return i
    
    @pyqtSlot(bool, name='on_removeSelectedPushButton_clicked')
    def removeWidget(self, widgetText = None):
        if not widgetText:
            treeItemList = [self.customizationTreeWidget.currentItem()]
        else:
            treeItemList = self.customizationTreeWidget.findItems(widgetText, flags = Qt.MatchExactly)
        if len(treeItemList)>0:
            for treeItem in treeItemList:
                parent = treeItem.parent()
                if parent == self.customizationTreeWidget.invisibleRootItem():
                    return
                idx = self.getWidgetIndexFromTreeItem(treeItem)
                itemToRemove = self.contentsDict[parent.text(0)]['widgetList'].pop(idx)
                itemToRemove.setParent(None)
                self.contentsDict[parent.text(0)]['treeItem'].removeChild(treeItem)
    
    @pyqtSlot()
    def on_buttonBox_accepted(self):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        exceptionList = []
        customJsonDict = dict()
        for i in self.customDict.keys():
            customJsonDict[i] = []
        correspondenceDict = {self.customDict[i]:i for i in self.customDict.keys()}
        nCustom = 0
        for key in self.contentsDict.keys():
            for widgetItem in self.contentsDict[key]['widgetList']:
                nCustom += 1
        progress = ProgressWidget(1,nCustom,self.tr('Preparing to export customizations... '), parent = self)
        progress.initBar()
        for key in self.contentsDict.keys():
            jsonTagList = []
            for widget in self.contentsDict[key]['widgetList']:
                currJsonItem = {'jsonUi':None, 'dbJsonTagList':[]}
                currentWidget = widget.layout().itemAt(0).widget()
                try:
                    jsonTagList = currentWidget.getJSONTag()
                    jsonUi = currentWidget.getUiParameterJsonDict()
                except Exception as e:
                    exceptionList.append(':'.join(e.args))
                if len(exceptionList) == 0:
                    currJsonItem['jsonUi'] = jsonUi
                    for jsonItem in jsonTagList:
                        if jsonItem not in currJsonItem['dbJsonTagList']:
                            currJsonItem['dbJsonTagList'].append(jsonItem)
                    if currJsonItem not in customJsonDict[correspondenceDict[key]]:
                        customJsonDict[correspondenceDict[key]].append(currJsonItem)
                progress.step()
        QApplication.restoreOverrideCursor()
        if self.validateJsonDict(customJsonDict) and len(exceptionList) == 0:
            versionText = 'database_'+self.edgvVersion
            finalJsonDict = {versionText:customJsonDict}
            self.customizationManager.createSetting(self.customizationName, self.edgvVersion, finalJsonDict)
            QMessageBox.information(self, self.tr('Success!'), self.tr('Database Customization ') + self.customizationName + self.tr(' created successfuly!'))
            #EMIT to reload?
            self.close()
        else:
            msg = ''
            if len(exceptionList)> 0:
                msg += self.tr('\Errors occured while trying to export customs built. Check qgis log for further details.')
                for error in exceptionList:
                    QgsMessageLog.logMessage(self.tr('Customization error: ') + error, "DSG Tools Plugin", QgsMessageLog.CRITICAL)
                QMessageBox.warning(self, self.tr('Error!'), msg)
    
    def validateJsonDict(self, customJsonDict):
        """
        Method to apply validation to customJsonDict
        """
        #TODO
        return True

    def populateWidgetsFromSelectedFile(self):
        jsonFileName = self.selectFileWidget.fileNameList
        customJsonDict = self.utils.readJsonFile(jsonFileName)
        self.createWidgetsFromCustomJsonDict(customJsonDict)
    
    def createWidgetsFromCustomJsonDict(self, customJsonDict):
        for key in customJsonDict.keys():
            for jsonTag in customJsonDict[key]:
                self.createWidgetFromKey(key, jsonTag['jsonUi'])
    
    def createWidgetFromKey(self, key, uiParameterJsonDict):
        if key == 'attribute':
            self.addAttributeWidget(uiParameterJsonDict=uiParameterJsonDict)
        elif key == 'class':
            self.addClassWidget(uiParameterJsonDict=uiParameterJsonDict)
        elif key == 'codeName':
            self.addCodeNameWidget(uiParameterJsonDict=uiParameterJsonDict)
        elif key == 'default':
            self.addDefaultWidget(uiParameterJsonDict=uiParameterJsonDict)
        elif key == 'domain':
            self.addDomainWidget(uiParameterJsonDict=uiParameterJsonDict)
        elif key == 'domainValue':
            self.addDomainValueWidget(uiParameterJsonDict=uiParameterJsonDict)
        elif key == 'nullity':
            self.addNullityWidget(uiParameterJsonDict=uiParameterJsonDict)
        elif key == 'filter':
            self.addFilterWidget(uiParameterJsonDict=uiParameterJsonDict)
        else:
            pass
示例#41
0
class AbstractDb(QObject):
    def __init__(self):
        '''
        Constructor
        '''
        super(AbstractDb,self).__init__()
        self.conversionTypeDict = dict({'QPSQL':'postgis','QSQLITE':'spatialite'})
        self.utils = Utils()
        self.signals = DbSignals()
        self.slotConnected = False
        self.versionFolderDict = dict({'2.1.3':'edgv_213','FTer_2a_Ed':'edgv_FTer_2a_Ed','3.0':'3'})
        self.utmGrid = UtmGrid()

    def __del__(self):
        '''
        Destructor
        '''
        if self.db.isOpen():
            self.db.close()
            self.db = None
            
    def checkAndOpenDb(self):
        '''
        Check and open the database
        '''
        if not self.db.isOpen():
            if not self.db.open():
                raise Exception(self.tr('Error opening database: ')+self.db.lastError().text())

    def getType(self):
        '''
        Gets the driver name
        '''
        return self.db.driverName()

    def validateUUID(self, uuid):
        try:
            uuid = UUID(uuid)
            return True
        except:
            return False

    def countElements(self, layers):
        '''
        Counts the number of elements in each layer present in layers
        '''
        self.checkAndOpenDb()
        listaQuantidades = []
        for layer in layers:
            (table,schema)=self.getTableSchema(layer)
            if layer.split('_')[-1] in ['p','l','a'] or schema == 'complexos':
                sql = self.gen.getElementCountFromLayer(layer)
                query = QSqlQuery(sql,self.db)
                query.next()
                number = query.value(0)
                if not query.exec_(sql):
                    raise Exception(self.tr("Problem counting elements: ")+query.lastError().text())
                listaQuantidades.append([layer, number])
        return listaQuantidades
    
    def getLayersWithElements(self, layerList):
        self.checkAndOpenDb()
        lyrWithElemList = []
        for lyr in layerList:
            schema=self.getTableSchemaFromDb(lyr)
            sql = self.gen.getElementCountFromLayer(schema,lyr)
            query = QSqlQuery(sql,self.db)
            query.next()
            if query.value(0) > 1:
                lyrWithElemList.appen(lyr)
        return lyrWithElemList

    def getLayersWithElementsV2(self, layerList, useInheritance = False):
        self.checkAndOpenDb()
        lyrWithElemList = []
        for layer in layerList:
            if isinstance(layer, dict):
                schema = layer['tableSchema']
                lyr = layer['tableName']
            else:
                if '.' in layer:
                    schema, lyr = layer.replace('"','').split('.')
                else:
                    lyr = layer
                    schema = self.getTableSchemaFromDb(lyr)
            sql = self.gen.getElementCountFromLayerV2(schema, lyr, useInheritance)
            query = QSqlQuery(sql,self.db)
            query.next()
            if query.value(0) > 0:
                lyrWithElemList.append(lyr)
        return lyrWithElemList
    
    def findEPSG(self, parameters=dict()):
        '''
        Finds the database EPSG
        '''
        self.checkAndOpenDb()
        sql = self.gen.getSrid(parameters=parameters)
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(self.tr("Problem finding EPSG: ")+query.lastError().text())
        srid = -1
        while query.next():
            srid = query.value(0)
        return srid

    def listWithElementsFromDatabase(self, classList):
        '''
        List classes with elements
        classList: class list
        '''
        self.checkAndOpenDb()
        classListWithNumber = self.countElements(classList)
        classesWithElements = dict()
        for cl in classListWithNumber:
            if cl[1]>0:
                classesWithElements[cl[0]]=cl[1]   
        return classesWithElements

    def listClassesWithElementsFromDatabase(self, useComplex = True, primitiveFilter = []):
        '''
        List classes with elements. Uses all classes (complex included)
        '''
        geomClassList = self.listGeomClassesFromDatabase(primitiveFilter)
        classList = []
        for g in geomClassList:
            classList.append(g)
        if useComplex:
            complexClassList = self.listComplexClassesFromDatabase()
            for c in complexClassList:
                classList.append(c)
        classList.sort()
        return self.listWithElementsFromDatabase(classList)

    def getAggregationAttributes(self):
        '''
        Gets complex link columns
        '''
        self.checkAndOpenDb()
        columns = []
        sql = self.gen.getAggregationColumn()
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(self.tr("Problem getting aggregation attributes: ")+query.lastError().text())
        while query.next():
            value = query.value(0)
            columns.append(value)
        return columns

    def getOgrDatabase(self):
        '''
        Builds a OGR database
        '''
        if self.ogrDb != None:
            self.buildOgrDatabase()
            return self.ogrDb

    def buildFieldMap(self):
        '''
        Gets database structure according to the edgv version
        '''
        self.checkAndOpenDb()
        fieldMap = self.getStructureDict()
        return fieldMap

    def validateWithOutputDatabaseSchema(self, outputAbstractDb):
        return None
    
    def convertDatabase(self, outputAbstractDb, type):
        '''
        Converts database
        '''
        self.signals.clearLog.emit()
        if outputAbstractDb.db.driverName() == 'QPSQL':
            return self.convertToPostgis(outputAbstractDb,type)
        if outputAbstractDb.db.driverName() == 'QSQLITE':
            return self.convertToSpatialite(outputAbstractDb,type)
        return None
    
    def makeValidationSummary(self, invalidatedDataDict):
        '''
        Makes the database conversion validation summary
        '''
        hasErrors = False
        for key in invalidatedDataDict.keys():
            if len(invalidatedDataDict[key]) > 0:
                hasErrors = True
        if hasErrors:
            self.signals.updateLog.emit('\n'+'{:-^60}'.format(self.tr('Validation Problems Summary')))
            for key in invalidatedDataDict.keys():
                
                if key == 'nullLine' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Classes with null lines:')+'\n')
                    self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Elements')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit('{:<50}'.format(cl)+str(invalidatedDataDict[key][cl])+'\n')

                if key == 'nullPk' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Classes with null primary keys:')+'\n')
                    self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Elements')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit('{:<50}'.format(cl)+str(invalidatedDataDict[key][cl])+'\n')

                if key == 'notInDomain' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Features with attributes not in domain:')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit('\n'+self.tr('Class: ')+cl+'\n')
                        for id in invalidatedDataDict[key][cl].keys():
                            attrCommaList = '(id,'+','.join(invalidatedDataDict[key][cl][id].keys())+') = '
                            at = invalidatedDataDict[key][cl][id].keys()
                            valueList = '('+str(id)
                            for i in range(len(at)):
                                valueList += ','+str(invalidatedDataDict[key][cl][id][at[i]])
                            valueList += ')\n'
                            self.signals.updateLog.emit(attrCommaList+valueList)

                if key == 'nullAttribute' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Features with null attributes in a not null field:')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(self.tr('Class: ')+cl+'\n')
                        for id in invalidatedDataDict[key][cl].keys():
                            attrCommaList = '(id,'+','.join(invalidatedDataDict[key][cl][id].keys())+') = '
                            valueList = '('+str(id)
                            for attr in invalidatedDataDict[key][cl][id].keys():
                                valueList += ','+str(invalidatedDataDict[key][cl][id][attr])
                            valueList += ')\n'
                            self.signals.updateLog.emit(attrCommaList+valueList)

                if key == 'nullComplexFk' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Features with invalid uuid foreign key:')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(self.tr('Class: ')+cl+'\n')
                        for id in invalidatedDataDict[key][cl].keys():
                            attrCommaList = '(id,'+','.join(invalidatedDataDict[key][cl][id].keys())+') = '
                            valueList = '('+str(id)
                            for attr in invalidatedDataDict[key][cl][id].keys():
                                valueList += ','+str(invalidatedDataDict[key][cl][id][attr])
                            valueList += ')\n'
                            self.signals.updateLog.emit(attrCommaList+valueList)
                            
                if key == 'classNotFoundInOutput' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Classes with classes that have elements but do not have output equivalent:')+'\n\n')
                    for cl in invalidatedDataDict[key]:
                            self.signals.updateLog.emit(self.tr('Class: ')+cl+'\n')
                
                if key == 'attributeNotFoundInOutput' and len(invalidatedDataDict[key])>0:
                    self.signals.updateLog.emit('\n\n'+self.tr('Classes with attributes that have no output attribute equivalent:')+'\n\n')
                    for cl in invalidatedDataDict[key].keys():
                        self.signals.updateLog.emit(self.tr('Class: ')+cl+'\n')
                        valueList = '('+','.join(invalidatedDataDict[key][cl])+')\n'
                        self.signals.updateLog.emit(valueList)
                
        return hasErrors
            
    def buildReadSummary(self,inputOgrDb,outputAbstractDb,classList):
        '''
        Builds the conversion read summary
        '''
        self.signals.clearLog.emit() #Clears log
        inputType = self.conversionTypeDict[self.db.driverName()]
        outputType = self.conversionTypeDict[outputAbstractDb.db.driverName()]
        self.signals.updateLog.emit(self.tr('Conversion type: ')+inputType+'2'+outputType+'\n')
        self.signals.updateLog.emit('\n'+self.tr('Input database: ')+self.db.databaseName()+'\n')
        self.signals.updateLog.emit('\n'+self.tr('Output database: ')+outputAbstractDb.db.databaseName()+'\n')
        self.signals.updateLog.emit('\n'+'{:-^60}'.format(self.tr('Read Summary')))
        self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Elements')+'\n\n')
        for cl in classList:
            self.signals.updateLog.emit('{:<50}'.format(cl)+str(inputOgrDb.GetLayerByName(str(cl)).GetFeatureCount())+'\n')
        return None
    
    def makeTranslationMap(self, layerName, layer, outLayer, fieldMapper):
        '''
        Makes the translation map
        '''
        layerFieldMapper=fieldMapper[layerName]
        layerDef = layer.GetLayerDefn()
        outLayerDef = outLayer.GetLayerDefn()
        panMap = []        
        for i in range(layerDef.GetFieldCount()):
            featureDef = layerDef.GetFieldDefn(i)
            fieldName = featureDef.GetName()
            if fieldName in layerFieldMapper.keys():
                name = layerFieldMapper[fieldName]
                fieldId = outLayerDef.GetFieldIndex(name)
                panMap.append(fieldId) 
            else:
                panMap.append(-1)
        return panMap
    
    def translateLayer(self, inputLayer, inputLayerName, outputLayer, outputFileName, layerPanMap, errorDict, defaults={}, translateValues={}):
        '''
        Makes the layer conversion
        '''
        inputLayer.ResetReading()
        inSpatialRef = inputLayer.GetSpatialRef()
        outSpatialRef = outputLayer.GetSpatialRef()
        coordTrans = None
        if not inSpatialRef.IsSame(outSpatialRef):
            coordTrans = osr.CoordinateTransformation(inSpatialRef, outSpatialRef)
        initialCount = outputLayer.GetFeatureCount()
        count = 0
        feat=inputLayer.GetNextFeature()
        #for feat in inputLayer:
        while feat:
            if not feat.geometry():
                continue
            inputId = feat.GetFID()
            if feat.geometry().GetGeometryCount() > 1:
                #Deaggregator
                for geom in feat.geometry():
                    newFeat=ogr.Feature(outputLayer.GetLayerDefn())
                    newFeat.SetFromWithMap(feat,True,layerPanMap)
                    auxGeom = ogr.Geometry(newFeat.geometry().GetGeometryType())
                    auxGeom.AssignSpatialReference(newFeat.geometry().GetSpatialReference())
                    auxGeom.AddGeometry(geom)
                    if coordTrans <> None:
                        auxGeom.Transform(coordTrans)
                    newFeat.SetGeometry(auxGeom)
                    out=outputLayer.CreateFeature(newFeat)
                    if out <> 0:
                        self.utils.buildNestedDict(errorDict, [inputLayerName], [inputId])
                    else:
                        count += 1
            else:
                newFeat=ogr.Feature(outputLayer.GetLayerDefn())
                newFeat.SetFromWithMap(feat,True,layerPanMap)
                if coordTrans <> None:
                    geom = feat.GetGeometryRef()
                    geom.Transform(coordTrans)
                    newFeat.SetGeometry(geom)
                out=outputLayer.CreateFeature(newFeat)
                if out <> 0:
                    self.utils.buildNestedDict(errorDict, [inputLayerName], [inputId])
                else:
                    count += 1
            feat=inputLayer.GetNextFeature()
        return count
    
    def translateDS(self, inputDS, outputDS, fieldMap, inputLayerList, errorDict,invalidated=None):
        '''
        Translates the data source
        '''
        self.signals.updateLog.emit('\n'+'{:-^60}'.format(self.tr('Write Summary')))
        self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Elements')+'\n\n')
        status = False
        for inputLyr in inputLayerList.keys():
            schema = self.getTableSchema(inputLyr)
            attrList = fieldMap[inputLyr].keys()
            
            #sql = self.gen.getFeaturesWithSQL(inputLyr,attrList) #order elements here
            #inputOgrLayer = inputDS.ExecuteSQL(sql.encode('utf-8'))
            #Here I had to change the way of loading because of features ids. I need to use inputDs.GetLayerByName
            
            inputOgrLayer = inputDS.GetLayerByName(str(inputLyr)) #new way of loading layer. The old way was an attempt to make a general rule for conversion between edgv versions
            outputFileName = self.translateOGRLayerNameToOutputFormat(inputLyr,outputDS)
            outputLayer=outputDS.GetLayerByName(outputFileName)
            #order conversion here
            layerPanMap=self.makeTranslationMap(inputLyr, inputOgrLayer,outputLayer, fieldMap)
            ini = outputLayer.GetFeatureCount()
            if invalidated == None:
                iter=self.translateLayer(inputOgrLayer, inputLyr, outputLayer, outputFileName, layerPanMap, errorDict)
            else:
                needsFix = False
                for keyDict in invalidated.values():
                    if len(keyDict) > 0:
                        if type(keyDict) == list:
                            if inputLyr in keyDict:
                                needsFix = True
                        if type(keyDict) == dict:
                            if inputLyr in keyDict.keys():
                                needsFix = True
                                break
                if needsFix:
                    iter = self.translateLayerWithDataFix(inputOgrLayer, inputLyr, outputLayer, outputFileName, layerPanMap, invalidated, errorDict)
                else:
                    iter=self.translateLayer(inputOgrLayer, inputLyr, outputLayer, outputFileName, layerPanMap, errorDict)
            if iter == -1:
                status = False
                self.signals.updateLog.emit('{:<50}'.format(self.tr('Error on layer ')+inputLyr+self.tr('. Conversion not performed.')+'\n'))
                return status
            diff = outputLayer.GetFeatureCount()-ini
            if iter == diff:
                status = True
            else:
                status = False
            self.signals.updateLog.emit('{:<50}'.format(str(outputFileName))+str(diff)+'\n')
        self.writeErrorLog(errorDict)
        outputDS.Destroy()
        return status
    
    def buildInvalidatedDict(self):
        '''
        Builds the initial state of the conversion invalidated dictionary
        '''
        invalidated = dict()
        invalidated['nullLine'] = dict()       
        invalidated['nullPk'] = dict()
        invalidated['notInDomain'] = dict()
        invalidated['nullAttribute'] = dict()
        invalidated['classNotFoundInOutput'] = []
        invalidated['attributeNotFoundInOutput'] = dict()
        invalidated['nullComplexFk'] = dict()
        return invalidated
    
    def prepareForConversion(self,outputAbstractDb):
        '''
        Executes preconditions for the conversion
        '''
        self.checkAndOpenDb()
        outputAbstractDb.checkAndOpenDb()
        fieldMap = self.buildFieldMap()
        inputOgrDb = self.buildOgrDatabase()
        outputOgrDb = outputAbstractDb.buildOgrDatabase()
        inputLayerList = self.listClassesWithElementsFromDatabase()
        errorDict = dict()
        self.buildReadSummary(inputOgrDb,outputAbstractDb,inputLayerList)
        return (inputOgrDb, outputOgrDb, fieldMap, inputLayerList, errorDict)

    def translateLayerWithDataFix(self, inputLayer, inputLayerName, outputLayer, outputFileName, layerPanMap, invalidated, errorDict, defaults={}, translateValues={}):
        '''
        casos e tratamentos:
        1. nullLine: os atributos devem ser varridos e, caso seja linha nula, ignorar o envio
        2. nullPk: caso seja complexo, gerar uma chave
        3. notInDomain: excluir do mapeamento aquele atributo caso ele seja mapeado
        4. nullAttribute: excluir do mapeamento aquele atributo caso ele seja não nulo
        5. classNotFoundInOutput: pular classe na conversão e mostrar no warning
        6. attributeNotFoundInOutput: pular atributo e mostrar no warning para todas as feicoes
        7. nullGeometry: excluir a feicao do mapeamento
        8. nullComplexFk: fazer atributo id_% ficar nulo caso não seja uuid
        '''
        inputLayer.ResetReading()
        fieldCount = inputLayer.GetLayerDefn().GetFieldCount()
        initialCount = outputLayer.GetFeatureCount()
        inSpatialRef = inputLayer.GetSpatialRef()
        outSpatialRef = outputLayer.GetSpatialRef()
        coordTrans = None
        if inSpatialRef <> outSpatialRef:
            coordTrans = osr.CoordinateTransformation(inSpatialRef, outSpatialRef)
        count = 0
        feat=inputLayer.GetNextFeature()
        (schema,className) = self.getTableSchema(inputLayerName)
        outputOgrLyrDict = self.getOgrLayerIndexDict(outputLayer)
        if inputLayerName not in invalidated['classNotFoundInOutput']:
            while feat:
                if not feat.geometry():
                    continue
                nullLine = True
                #Case 1: nullLine
                for i in range(fieldCount):
                    if feat.GetField(i) <> None:
                        nullLine = False
                        break
                if feat.GetFID() <> -1 or feat.geometry() <> None:
                    nullLine = False
                if not nullLine:
                    if inputLayerName not in invalidated['classNotFoundInOutput']:
                        newFeat=ogr.Feature(outputLayer.GetLayerDefn())
                        inputId = feat.GetFID()
                        #Case 2: nullPk in complex:
                        newFeat.SetFromWithMap(feat,True,layerPanMap)
                        if schema == 'complexos' and feat.GetFID() == -1:
                            newFeat.SetFID(uuid4())
                        #Case 3
                        for j in range(inputLayer.GetLayerDefn().GetFieldCount()):
                            if layerPanMap[j] <> -1:
                                if inputLayerName in invalidated['notInDomain'].keys():
                                    if inputId in invalidated['notInDomain'][inputLayerName].keys():
                                        if outputLayer.GetLayerDefn().GetFieldDefn(layerPanMap[j]).GetName() in invalidated['notInDomain'][inputLayerName][inputId].keys():
                                            newFeat.UnsetField(layerPanMap[j])
                                if inputLayerName in invalidated['nullAttribute'].keys():
                                    if inputId in invalidated['nullAttribute'][inputLayerName].keys():
                                        if outputLayer.GetLayerDefn().GetFieldDefn(layerPanMap[j]).GetName() in invalidated['nullAttribute'][inputLayerName][inputId].keys():
                                            if outputLayer.GetLayerDefn().GetFieldDefn(layerPanMap[j]).GetTypeName() == 'String':
                                                newFeat.SetField(layerPanMap[j],'-9999')
                                            if outputLayer.GetLayerDefn().GetFieldDefn(layerPanMap[j]).GetTypeName() == 'Integer':
                                                newFeat.SetField(layerPanMap[j],-9999)
                                if inputLayerName in invalidated['nullComplexFk'].keys():
                                    if inputId in invalidated['nullComplexFk'][inputLayerName].keys():
                                        if outputLayer.GetLayerDefn().GetFieldDefn(layerPanMap[j]).GetName() in invalidated['nullComplexFk'][inputLayerName][inputId].keys():
                                            newFeat.UnsetField(layerPanMap[j])
                        if newFeat.geometry().GetGeometryCount() > 1:
                            #Deaggregator
                            for geom in newFeat.geometry():
                                auxGeom = ogr.Geometry(newFeat.geometry().GetGeometryType())
                                auxGeom.AssignSpatialReference(newFeat.geometry().GetSpatialReference())
                                auxGeom.AddGeometry(geom)
                                if coordTrans <> None:
                                    auxGeom.Transform(coordTrans)
                                newFeat.SetGeometry(auxGeom)
                                out=outputLayer.CreateFeature(newFeat)
                                if out <> 0:
                                    self.utils.buildNestedDict(errorDict, [inputLayerName], [inputId])
                                else:
                                    count += 1
                        else:
                            if coordTrans <> None:
                                geom = feat.GetGeometryRef()
                                geom.Transform(coordTrans)
                                newFeat.SetGeometry(geom)
                            out=outputLayer.CreateFeature(newFeat)
                            if out <> 0:
                                self.utils.buildNestedDict(errorDict, [inputLayerName], [inputId])
                            else:
                                count += 1
                feat=inputLayer.GetNextFeature()
            return count
        else:
            return -1
    
    def buildOgrDatabase(self):
        '''
        Build a OGR database
        '''
        con = self.makeOgrConn()
        ogrDb = ogr.Open(con,update=1)
        return ogrDb
    
    def reorderTupleList(self, ls):
        '''
        Reorders a tuple list
        ls: list to be reordered
        '''
        if 'OGC_FID' in ls:
            idField = 'OGC_FID'
        else:
            idField = 'id'
        index = ls.index(idField)
        reordered = [ls[index]]
        reordered.extend(ls[0:index])
        reordered.extend(ls[index+1::])
        return reordered
    
    def getOgrLayerIndexDict(self, lyr):
        '''
        Gets ogr field definitions
        '''
        ogrDict = dict()
        layerDef = lyr.GetLayerDefn()
        for i in range(layerDef.GetFieldCount()):
            ogrDict[i] = layerDef.GetFieldDefn(i).GetName() 
        return ogrDict
    
    def writeErrorLog(self,errorDict):
        '''
        Writes conversion error log
        '''
        errorClasses = errorDict.keys()
        if len(errorClasses)>0:
            self.signals.updateLog.emit('\n'+'{:-^60}'.format(self.tr('Features not converted')))
            self.signals.updateLog.emit('\n\n'+'{:<50}'.format(self.tr('Class'))+self.tr('Feature id')+'\n\n')
            for cl in errorClasses:
                for id in errorDict[cl]:
                    self.signals.updateLog.emit('\n\n'+'{:<50}'.format(cl+str(id)))
    
    def getQmlDir(self):
        '''
        Gets the QML directory
        '''
        currentPath = os.path.dirname(__file__)
        if qgis.core.QGis.QGIS_VERSION_INT >= 20600:
            qmlVersionPath = os.path.join(currentPath, '..', '..', 'Qmls', 'qgis_26')
        else:
            qmlVersionPath = os.path.join(currentPath, '..', '..', 'Qmls', 'qgis_22')

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

    def getStyleDict(self, dbVersion):
        '''
        dbVersion: database version in the format of abstractDb.getVersion()
        The first iteration of walk lists all dirs as the second element of the list in os.walk(styleDir).next()[1]. 
        As only God and Mauricio were going to remember this, I wrote it down.
        '''
        currentPath = os.path.dirname(__file__)
        styleDir = os.path.join(currentPath, '..', '..', 'Styles')
        if dbVersion == '2.1.3':
            styleDir = os.path.join(styleDir, 'edgv_213')
        elif dbVersion == '3.0':
            styleDir = os.path.join(styleDir, 'edgv_3')
        elif dbVersion == 'FTer_2a_Ed':
            styleDir = os.path.join(styleDir, 'edgv_FTer_2a_Ed')
        else:
            styleDir = os.path.join(styleDir, 'Non_EDGV')
        styleList = os.walk(styleDir).next()[1]
        styleDict = dict()
        try:
            for s in styleList:
                styleDict['dir:'+s] = os.path.join(styleDir, s)
            #here we get the styles from db if there are any
        except:
            pass
        try:
            dbStyles = self.getStylesFromDb(dbVersion)
            if dbStyles:
                for style in dbStyles:
                    name = style.split('/')[-1]
                    styleDict['db:'+name] = 'db:'+style
        except:
            pass
        return styleDict
    
    def makeValueRelationDict(self, table, codes):
        '''
        Makes the value relation dictionary (multi valued attributes)
        '''
        self.checkAndOpenDb()
        ret = dict()
        in_clause = '(%s)' % ",".join(map(str, codes))
        sql = self.gen.makeRelationDict(table, in_clause)
        query = QSqlQuery(sql, self.db)
        while query.next():
            code = str(query.value(0))
            code_name = query.value(1)
            ret[code_name] = code
        return ret
    
    def createFrameFromInom(self, inom):
        frame = self.utmGrid.getQgsPolygonFrame(inom)
        return frame
    
    def insertFrame(self, scale, mi, inom, frame, paramDict = dict()):
        self.checkAndOpenDb()
        srid = self.findEPSG()
        geoSrid = QgsCoordinateReferenceSystem(int(srid)).geographicCRSAuthId().split(':')[-1]
        sql = self.gen.insertFrame(scale, mi, inom, frame, srid, geoSrid, paramDict = paramDict)
        self.db.transaction()
        query = QSqlQuery(self.db)
        if not query.exec_(sql):
            self.db.rollback()
            self.db.close()
            raise Exception(self.tr('Problem inserting frame: ') + query.lastError().text())
        self.db.commit()
        self.db.close()
    
    def prepareCreateFrame(self, type, scale, param):
        if type == 'mi':
            mi = str(param)
            if scale == '250k':
                inom = self.utmGrid.getINomenFromMIR(str(param))
            else:
                inom = self.utmGrid.getINomenFromMI(str(param))
        elif type == 'inom':
            inom = str(param)
            if scale == '250k':
                mi = self.utmGrid.getINomenFromMIR(inom)
            else:
                mi = self.utmGrid.getMIfromInom(inom)
        frame = self.createFrameFromInom(inom)
        return mi, inom, frame

    def getQmlDict(self, layerList):
        edgvVersion = self.getDatabaseVersion()
        if edgvVersion in ['2.1.3','FTer_2a_Ed']: #this does not have 3.0, do not change it!!!!
            qmlPath = self.getQmlDir()
            return self.utils.parseMultiQml(qmlPath, layerList)
        else:
            qmlRecordDict = self.getQmlRecordDict(layerList)
            return self.utils.parseMultiFromDb(qmlRecordDict, layerList)
    
    def getQmlRecordDict(self, inputLayer):
        self.checkAndOpenDb()
        if isinstance(inputLayer, list):
            sql = self.gen.getQmlRecords(inputLayer)
        else:
            sql = self.gen.getQmlRecords([inputLayer])
        query = QSqlQuery(sql, self.db)
        if not query.isActive():
            raise Exception(self.tr("Problem getting qmlRecordDict: ")+query.lastError().text())
        qmlDict = dict()
        while query.next():
            if isinstance(inputLayer, list): 
                qmlDict[query.value(0)] = query.value(1)
            else:
                return query.value(1)
        return qmlDict
    
    def getQml(self, layerName):
        if self.getDatabaseVersion() == '3.0':
            return (self.getQmlRecordDict(layerName), 'db')
        else:
            return (self.getQmlDir(), 'dir')
示例#42
0
class CustomTableSelector(QtGui.QWidget, FORM_CLASS):
    selectionChanged = pyqtSignal(list, str)

    def __init__(self, customNumber=None, parent=None):
        """Constructor."""
        super(self.__class__, self).__init__(parent)
        self.fromLs = []
        self.toLs = []
        self.utils = Utils()
        self.setupUi(self)

    def resizeTrees(self):
        """
        Expands headers
        """
        self.fromTreeWidget.expandAll()
        self.fromTreeWidget.header().setResizeMode(
            QtGui.QHeaderView.ResizeToContents)
        self.fromTreeWidget.header().setStretchLastSection(False)
        self.toTreeWidget.expandAll()
        self.toTreeWidget.header().setResizeMode(
            QtGui.QHeaderView.ResizeToContents)
        self.toTreeWidget.header().setStretchLastSection(False)

    def sortItems(self, treeWidget):
        """
        Sorts items from input treeWidget
        """
        rootNode = treeWidget.invisibleRootItem()
        rootNode.sortChildren(0, Qt.AscendingOrder)
        for i in range(rootNode.childCount()):
            rootNode.child(i).sortChildren(1, Qt.AscendingOrder)

    def setTitle(self, title):
        """
        Setting the title
        """
        self.groupBox.setTitle(title)

    def setFilterColumn(self, customNumber=None):
        """
        Chooses which column is going to be used in the filter
        """
        if isinstance(customNumber, int):
            self.filterColumnKey = self.headerList[customNumber]
        elif self.headerList:
            self.filterColumnKey = self.headerList[1]
        else:
            self.filterColumnKey = self.headerList[0]

    def clearAll(self):
        """
        Clears everything to return to the initial state
        """
        self.filterLineEdit.clear()

    def setHeaders(self, headerList, customNumber=None):
        """
        Sets fromTreeWidget and toTreeWidget headers
        """
        self.headerList = headerList
        self.fromTreeWidget.setHeaderLabels(headerList)
        self.toTreeWidget.setHeaderLabels(headerList)
        self.setFilterColumn(customNumber=customNumber)

    def setInitialState(self, fromDictList, unique=False):
        """
        Sets the initial state
        """
        self.fromLs = []
        self.toLs = []
        self.fromTreeWidget.clear()
        self.fromTreeWidget.clear()
        if not isinstance(fromDictList, int):
            self.addItemsToTree(self.fromTreeWidget,
                                fromDictList,
                                self.fromLs,
                                unique=unique)

    def getChildNode(self, parentNode, textList):
        """
        Returns child node with columns equals to textList items. If no node is found, return None
        """
        for i in range(parentNode.childCount()):
            nodeFound = True
            childNode = parentNode.child(i)
            for j in range(len(textList)):
                if childNode.text(j) != textList[j]:
                    nodeFound = False
                    break
            if nodeFound:
                return childNode
        return None

    def addItemsToTree(self,
                       treeWidget,
                       addItemDictList,
                       controlList,
                       unique=False):
        """
        Adds items from addItemDictList in treeWidget.
        addItemDictList = [-list of dicts with keys corresponding to header list texts-]
        unique: only adds item if it is not in already in tree
        """
        rootNode = treeWidget.invisibleRootItem()  #invisible root item
        for dictItem in addItemDictList:
            firstColumnChild = self.getChildNode(
                rootNode, [dictItem[self.headerList[0]]] + [''] *
                (len(self.headerList) - 1)
            )  #looks for a item in the format ['first column text', '','',...,'']
            if not firstColumnChild:
                firstColumnChild = self.utils.createWidgetItem(
                    rootNode, dictItem[self.headerList[0]], 0)
            textList = [
                dictItem[self.headerList[i]]
                for i in range(len(self.headerList))
            ]
            if unique:
                childNode = self.getChildNode(firstColumnChild, textList)
                if not childNode:
                    item = self.utils.createWidgetItem(firstColumnChild,
                                                       textList)
                    itemList = self.getItemList(item)
                    if itemList not in controlList:
                        controlList.append(itemList)
            else:
                item = self.utils.createWidgetItem(firstColumnChild, textList)
                itemList = self.getItemList(item)
                controlList.append(itemList)
        self.resizeTrees()
        self.sortItems(treeWidget)

    def getItemList(self, item, returnAsDict=False):
        """
        Gets item as a list
        """
        if returnAsDict:
            returnItem = dict()
        else:
            returnItem = []
        for i in range(item.columnCount()):
            if returnAsDict:
                returnItem[self.headerList[i]] = item.text(i)
            else:
                returnItem.append(item.text(i))
        return returnItem

    def getLists(self, sender):
        """
        Returns a list composed by (originTreeWidget, --list that controls previous originTreeWidget--, destinationTreeWidget, --list that controls previous destinationTreeWidget--)
        """
        text = sender.text()
        if text == '>':
            return self.fromTreeWidget, self.fromLs, self.toTreeWidget, self.toLs, False
        if text == '>>':
            return self.fromTreeWidget, self.fromLs, self.toTreeWidget, self.toLs, True
        if text == '<':
            return self.toTreeWidget, self.toLs, self.fromTreeWidget, self.fromLs, False
        if text == '<<':
            return self.toTreeWidget, self.toLs, self.fromTreeWidget, self.fromLs, True

    @pyqtSlot(bool, name='on_pushButtonSelectOne_clicked')
    @pyqtSlot(bool, name='on_pushButtonDeselectOne_clicked')
    @pyqtSlot(bool, name='on_pushButtonSelectAll_clicked')
    @pyqtSlot(bool, name='on_pushButtonDeselectAll_clicked')
    def selectItems(self, isSelected, selectedItems=[]):
        """
        Adds the selected items to the "to" list
        """
        #gets lists
        originTreeWidget, originControlLs, destinationTreeWidget, destinationControlLs, allItems = self.getLists(
            self.sender())
        #root nodes
        originRoot = originTreeWidget.invisibleRootItem()
        destinationRoot = destinationTreeWidget.invisibleRootItem()
        selectedItemList = []
        self.getSelectedItems(originRoot, selectedItemList)
        for i in range(originRoot.childCount())[::-1]:
            catChild = originRoot.child(i)
            #if son of originRootNode is selected, adds it to destinationRootNode
            moveNode = allItems or (catChild in selectedItemList)
            #get destination parent, creates one in destination if not exists
            destinationCatChild = self.getDestinationNode(
                destinationRoot, catChild)
            for j in range(catChild.childCount())[::-1]:
                nodeChild = catChild.child(j)
                moveChild = (nodeChild in selectedItemList) or moveNode
                if self.moveChild(catChild, j, destinationCatChild, moveChild):
                    itemList = self.getItemList(nodeChild)
                    destinationControlLs.append(itemList)
                    originControlLs.pop(originControlLs.index(itemList))
            destinationCatChild.sortChildren(1, Qt.AscendingOrder)
            if catChild.childCount() == 0:
                originRoot.takeChild(i)
            destinationRoot.sortChildren(0, Qt.AscendingOrder)
        for i in range(destinationRoot.childCount())[::-1]:
            if destinationRoot.child(i).childCount() == 0:
                destinationRoot.takeChild(i)
        destinationRoot.sortChildren(0, Qt.AscendingOrder)
        self.resizeTrees()

    def getSelectedItems(self, treeWidgetNode, itemList):
        """
        Recursive method to get all selected nodes of treeWidget
        """
        for i in range(treeWidgetNode.childCount()):
            childItem = treeWidgetNode.child(i)
            if childItem.isSelected() and (childItem not in itemList):
                itemList.append(childItem)
            for j in range(childItem.childCount()):
                self.getSelectedItems(childItem, itemList)

    def moveChild(self, parentNode, idx, destinationNode, isSelected):
        """
        If node is selected, removes node from parentNode and adds it to destinationNode
        """
        if isSelected:
            child = parentNode.takeChild(idx)
            destinationNode.addChild(child)
            return True
        else:
            return False

    def getDestinationNode(self, destinationRoot, catChild, returnNew=True):
        """
        Looks for node in destination and returns it. If none is found, creates one and returns it
        """
        #get destination parent, creates one in destination if not exists
        destinationCatChild = None
        if isinstance(catChild, list):
            comparisonText = catChild[0]
            if returnNew:
                itemTextList = [catChild[i] for i in range(len(catChild))]
        else:
            comparisonText = catChild.text(0)
            if returnNew:
                itemTextList = [
                    catChild.text(i) for i in range(catChild.columnCount())
                ]

        for i in range(destinationRoot.childCount()):
            candidate = destinationRoot.child(i)
            if candidate.text(0) == comparisonText:
                #if candidate is found, returns candidate
                return candidate
        #if candidate is not found, creates one and returns it
        if returnNew:
            if not destinationCatChild:
                return QTreeWidgetItem(destinationRoot, itemTextList)
        else:
            return None

    def on_filterLineEdit_textChanged(self, text):
        """
        Filters the items to make it easier to spot and select them
        """
        classes = [
            node[1].lower() for node in self.fromLs
            if text.lower() in node[1].lower()
        ]  #text list
        filteredClasses = [
            i for i in classes
            if i.lower() not in [j[1].lower() for j in self.toLs]
        ]  #text list
        self.filterTree(self.fromTreeWidget, self.fromLs, filteredClasses, 1)
        self.resizeTrees()

    def filterTree(self, treeWidget, controlList, filterList, columnIdx):
        '''
        Actual filter
        '''
        treeWidget.clear()
        rootNode = treeWidget.invisibleRootItem()
        #remove items that are not in filterList
        for item in controlList:
            if item[columnIdx].lower() in filterList:
                firstColumnChild = self.getChildNode(
                    rootNode, [item[0]] + [''] * (len(item) - 1)
                )  #looks for a item in the format ['first column text', '','',...,'']
                if not firstColumnChild:
                    firstColumnChild = self.utils.createWidgetItem(
                        rootNode, item[0], 0)
                QTreeWidgetItem(firstColumnChild, item)
        rootNode.sortChildren(0, Qt.AscendingOrder)
        for i in range(rootNode.childCount()):
            rootNode.child(i).sortChildren(1, Qt.AscendingOrder)

    def getSelectedNodes(self, concatenated=True):
        """
        Returns a list of selected nodes converted into a string separated by ','
        """
        selected = []
        rootNode = self.toTreeWidget.invisibleRootItem()
        for i in range(rootNode.childCount()):
            catNode = rootNode.child(i)
            for j in range(catNode.childCount()):
                item = catNode.child(j)
                if concatenated:
                    catList = [item.text(i) for i in range(item.columnCount())]
                    selected.append(','.join(catList))
                else:
                    selected.append(item)
        return selected

    def addItemsToWidget(self, itemList, unique=False):
        """
        Adds items to tree that is already built.
        """
        self.addItemsToTree(self.fromTreeWidget,
                            itemList,
                            self.fromLs,
                            unique=unique)

    def removeItemsFromWidget(self, removeList):
        """
        Searches both lists and removes items that are in removeList
        """
        self.removeItemsFromTree(removeList, self.fromTreeWidget, self.fromLs)
        self.removeItemsFromTree(removeList, self.toTreeWidget, self.toLs)

    def removeItemsFromTree(self, dictItemList, treeWidget, controlList):
        """
        Searches treeWidget and removes items that are in removeList and updates controlList
        """
        treeRoot = treeWidget.invisibleRootItem()
        catList = [i[self.headerList[0]] for i in dictItemList]
        returnList = []
        for i in range(treeRoot.childCount())[::-1]:
            catChild = treeRoot.child(i)
            if catChild.text(0) in catList:
                for j in range(catChild.childCount())[::-1]:
                    nodeChild = catChild.child(j)
                    nodeChildDict = self.getItemList(nodeChild,
                                                     returnAsDict=True)
                    nodeChildDict[self.headerList[0]] = catChild.text(0)
                    if nodeChildDict in dictItemList:
                        catChild.takeChild(j)
                        itemList = self.getItemList(nodeChild)
                        controlList.pop(controlList.index(itemList))
        for i in range(treeRoot.childCount())[::-1]:
            if treeRoot.child(i).childCount() == 0:
                treeRoot.takeChild(i)
        treeRoot.sortChildren(0, Qt.AscendingOrder)
        for i in range(treeRoot.childCount()):
            treeRoot.child(i).sortChildren(1, Qt.AscendingOrder)
示例#43
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
示例#44
0
class ChangeFilterWidget(QtGui.QWidget, FORM_CLASS):
    populateSingleValue = pyqtSignal()
    populateListValue = pyqtSignal()
    def __init__(self, abstractDb, uiParameterJsonDict = None, parent = None):
        """Constructor."""
        super(self.__class__, self).__init__(parent)
        self.abstractDb = abstractDb
        self.setupUi(self)
        self.jsonBuilder = CustomJSONBuilder()
        self.populateSchemaCombo()
        self.hideWidgetList([self.singleValueLabel, self.singleValueComboBox, self.actionComboBox])
        self.singleAttribute = True
        self.filterCustomSelectorWidget.setTitle(self.tr('Select filter values'))
        self.populateSingleValue.connect(self.populateWidgetWithSingleValue)
        self.populateListValue.connect(self.populateWidgetWithListValue)
        geomTypeDict = self.abstractDb.getGeomTypeDict()
        geomDict = self.abstractDb.getGeomDict(geomTypeDict)
        self.domainDict = self.abstractDb.getDbDomainDict(geomDict)
        self.inhTree = self.abstractDb.getInheritanceTreeDict()
        self.utils = Utils()
        self.actionDict = {self.tr('Add to Filter (Leave empty if filter is empty)'):'addEmpty', self.tr('Add to Filter (Add value to empty filter)'):'add',self.tr('Remove from Filter'):'remove'}
        self.populateFromUiParameterJsonDict(uiParameterJsonDict)
    
    def populateFromUiParameterJsonDict(self, uiParameterJsonDict):
        """
        {
            'schemaComboBox': --current text of schemaComboBox --
            'tableComboBox': ---current text of tableComboBox --
            'attributeComboBox': ---current text of attributeComboBox --
            'allAttributesCheckBox': --current state of allAttributesCheckBox--
            'allTablesCheckBox': --current state of allTablesCheckBox--
            'filterCustomSelectorWidgetToList': [--list of selected values on filterCustomSelectorWidget--]
            'singleValueComboBox': --current text of singleValueComboBox--
            'actionComboBoxIdx': --current index of actionComboBoxIdx--
        }
        """
        if uiParameterJsonDict:
            if uiParameterJsonDict['allTablesCheckBox']:
                self.allTablesCheckBox.setCheckState(Qt.Checked)
                singleValueIdx = self.singleValueComboBox.findText(uiParameterJsonDict['singleValueComboBox'], flags = Qt.MatchExactly)
                self.singleValueComboBox.setCurrentIndex(singleValueIdx)
                self.actionComboBox.setCurrentIndex(uiParameterJsonDict['actionComboBoxIdx'])
            else:
                schemaIdx = self.schemaComboBox.findText(uiParameterJsonDict['schemaComboBox'], flags = Qt.MatchExactly)
                self.schemaComboBox.setCurrentIndex(schemaIdx)
                tableIdx = self.tableComboBox.findText(uiParameterJsonDict['tableComboBox'], flags = Qt.MatchExactly)
                self.tableComboBox.setCurrentIndex(tableIdx)
                if uiParameterJsonDict['allAttributesCheckBox']:
                    self.allAttributesCheckBox.setCheckState(Qt.Checked)
                    singleValueIdx = self.singleValueComboBox.findText(uiParameterJsonDict['singleValueComboBox'], flags = Qt.MatchExactly)
                    self.singleValueComboBox.setCurrentIndex(singleValueIdx)
                    self.actionComboBox.setCurrentIndex(uiParameterJsonDict['actionComboBoxIdx'])
                else:
                    attributeIdx = self.attributeComboBox.findText(uiParameterJsonDict['attributeComboBox'], flags = Qt.MatchExactly)
                    self.attributeComboBox.setCurrentIndex(attributeIdx)
                    self.filterCustomSelectorWidget.selectItems(True, selectedItems=uiParameterJsonDict['filterCustomSelectorWidgetToList'])

    def populateInheritanceTree(self, nodeList):
        self.treeWidget.clear()
        rootNode = self.treeWidget.invisibleRootItem()
        for node in nodeList:
            firstNonRootNode = self.utils.find_all_paths(self.inhTree, 'root', node)[0][1]
            self.utils.createTreeWidgetFromDict(rootNode, {firstNonRootNode:self.inhTree['root'][firstNonRootNode]}, self.treeWidget, 0)
        self.treeWidget.sortItems(0, Qt.AscendingOrder)
        self.treeWidget.expandAll()

    def populateSchemaCombo(self):
        self.schemaComboBox.clear()
        self.schemaComboBox.addItem(self.tr('Select a schema'))
        schemaList = self.abstractDb.getGeometricSchemaList()
        for schema in schemaList:
            if schema not in ['views', 'validation']:
                self.schemaComboBox.addItem(schema)

    def hideWidgetList(self, widgetList):
        for widget in widgetList:
            widget.hide()

    def showWidgetList(self, widgetList):
        for widget in widgetList:
            widget.show()

    @pyqtSlot(int)
    def on_schemaComboBox_currentIndexChanged(self, idx):
        if idx == 0:
            self.tableComboBox.clear()
            self.tableComboBox.setEnabled(False)
            self.attributeComboBox.clear()
            self.attributeComboBox.setEnabled(False)
        else:
            schema = self.schemaComboBox.currentText()
            self.tableComboBox.setEnabled(True)
            self.tableComboBox.clear()
            self.tableComboBox.addItem(self.tr('Select a table'))
            tableList = self.abstractDb.getGeometricTableListFromSchema(schema)
            for table in tableList:
                self.tableComboBox.addItem(table)

    @pyqtSlot(int)
    def on_tableComboBox_currentIndexChanged(self, idx):
        if idx == 0:
            self.attributeComboBox.clear()
            self.attributeComboBox.setEnabled(False)
        else:
            schema = self.schemaComboBox.currentText()
            tableName = self.tableComboBox.currentText()
            self.attributeComboBox.setEnabled(True)
            self.attributeComboBox.clear()
            self.attributeComboBox.addItem(self.tr('Select an attribute'))
            if tableName in self.domainDict.keys():
                attributeList = self.domainDict[tableName]['columns'].keys()
                for attribute in attributeList:
                    self.attributeComboBox.addItem(attribute)

    @pyqtSlot(int, name='on_schemaComboBox_currentIndexChanged')
    @pyqtSlot(int, name='on_attributeComboBox_currentIndexChanged')
    @pyqtSlot(int, name='on_tableComboBox_currentIndexChanged')
    def populateWidgetWithSingleValue(self):
        if self.allTablesCheckBox.checkState() == 2 or (self.allAttributesCheckBox.checkState() == 2 and self.schemaComboBox.currentIndex() <> 0 and self.tableComboBox.currentIndex() <> 0):
            self.attributeComboBox.clear()
            self.attributeComboBox.setEnabled(False)
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            self.singleValueComboBox.clear()
            self.singleValueComboBox.addItem(self.tr('Select a value to alter'))
            if self.allAttributesCheckBox.checkState() == 2:
                tableList = [self.tableComboBox.currentText()]
            else:
                tableList = self.domainDict.keys()
            allValueList = []
            idxList = []
            for tableName in tableList:
                for attrName in self.domainDict[tableName]['columns'].keys():
                    for code in self.domainDict[tableName]['columns'][attrName]['values']:
                        value = self.domainDict[tableName]['columns'][attrName]['values'][code]
                        if value not in allValueList:
                            allValueList.append(value)

            for value in allValueList:
                for tableName in tableList:
                    for attrName in self.domainDict[tableName]['columns'].keys():
                        if value not in self.domainDict[tableName]['columns'][attrName]['values'].values():
                            idx = allValueList.index(value)
                            if idx not in idxList:
                                idxList.append(idx)
            idxList.sort(reverse=True)
            for idx in idxList:
                allValueList.pop(idx)
            for value in allValueList:
                self.singleValueComboBox.addItem(value)
            self.populateInheritanceTree(tableList)
            QApplication.restoreOverrideCursor()

    @pyqtSlot(int, name='on_schemaComboBox_currentIndexChanged')
    @pyqtSlot(int, name='on_attributeComboBox_currentIndexChanged')
    @pyqtSlot(int, name='on_tableComboBox_currentIndexChanged')
    def populateWidgetWithListValue(self):
        self.filterCustomSelectorWidget.clearAll()
        if self.allTablesCheckBox.checkState() == 2 or self.allAttributesCheckBox.checkState() == 2:
            return
        if self.schemaComboBox.currentIndex() == 0:
            return
        if self.tableComboBox.currentIndex() == 0:
            self.treeWidget.clear()
            return
        tableName = self.tableComboBox.currentText()
        self.populateInheritanceTree([tableName])
        if self.attributeComboBox.currentIndex() == 0:
            return
        filterList = []
        attributeName = self.attributeComboBox.currentText()
        tableFilter = []
        filterToList = []
        if tableName in self.domainDict.keys():
            if attributeName in self.domainDict[tableName]['columns'].keys():
                attrDomainDict = self.domainDict[tableName]['columns'][attributeName]['values']
                tableFilter = self.domainDict[tableName]['columns'][attributeName]['constraintList']
                filterToList = [attrDomainDict[i] for i in tableFilter]
                filterFromList = [i for i in attrDomainDict.values() if i not in filterToList]
                self.filterCustomSelectorWidget.setFromList(filterFromList, unique=True)
                self.filterCustomSelectorWidget.setToList(filterToList)

    @pyqtSlot(int)
    def on_allTablesCheckBox_stateChanged(self, state):
        self.hideOrShowWidgets()
        if state == 0:
            self.allAttributesCheckBox.setEnabled(True)
            self.schemaComboBox.setCurrentIndex(0)
            self.schemaComboBox.setEnabled(True)
        elif state == 2:
            self.allAttributesCheckBox.setEnabled(False)
            self.allAttributesCheckBox.setCheckState(0)
            self.schemaComboBox.setCurrentIndex(0)
            self.schemaComboBox.setEnabled(False)

    @pyqtSlot(int)
    def on_allAttributesCheckBox_stateChanged(self, state):
        if state == 2:
            self.allTablesCheckBox.setEnabled(False)
            self.allTablesCheckBox.setCheckState(0)
            self.attributeComboBox.setCurrentIndex(0)
            self.attributeComboBox.setEnabled(False)
        if state == 0:
            self.allTablesCheckBox.setEnabled(True)
            self.attributeComboBox.setEnabled(True)
        self.hideOrShowWidgets()

    def hideOrShowWidgets(self):
        if self.allAttributesCheckBox.checkState() == 2 or self.allTablesCheckBox.checkState() == 2:
            self.filterCustomSelectorWidget.hide()
            self.singleValueLabel.show()
            self.singleValueComboBox.show()
            self.actionComboBox.show()
            self.populateSingleValue.emit()
        else:
            self.filterCustomSelectorWidget.show()
            self.singleValueLabel.hide()
            self.singleValueComboBox.hide()
            self.actionComboBox.hide()
            self.tableComboBox.currentIndexChanged.emit(self.tableComboBox.currentIndex())
            self.populateListValue.emit()

    def getTitle(self):
        return self.title

    def setTitle(self, title):
        self.title = title

    def validate(self):
        if self.allTablesCheckBox.checkState() == 2:
             if self.singleValueComboBox.currentIndex() == 0:
                 return False
             if self.actionComboBox.currentIndex() == 0:
                 return False
        elif self.allAttributesCheckBox.checkState() == 2:
             if self.singleValueComboBox.currentIndex() == 0:
                 return False
             if self.actionComboBox.currentIndex() == 0:
                 return False
             if self.schemaComboBox.currentIndex() == 0:
                 return False
             if self.tableComboBox.currentIndex() == 0:
                 return False
        else:
             if self.schemaComboBox.currentIndex() == 0:
                 return False
             if self.tableComboBox.currentIndex() == 0:
                 return False
             if self.attributeComboBox.currentIndex() == 0:
                 return False
        return True

    def validateDiagnosis(self):
        invalidatedReason = ''
        if self.allTablesCheckBox.checkState() == 2:
             if self.singleValueComboBox.currentIndex() == 0:
                 invalidatedReason += self.tr('A value must be chosen.\n')
             if self.actionComboBox.currentIndex() == 0:
                 invalidatedReason += self.tr('An action must be chosen.\n')
        elif self.allAttributesCheckBox.checkState() == 2:
             if self.singleValueComboBox.currentIndex() == 0:
                 invalidatedReason += self.tr('A value must be chosen.\n')
             if self.actionComboBox.currentIndex() == 0:
                 invalidatedReason += self.tr('An action must be chosen.\n')
             if self.schemaComboBox.currentIndex() == 0:
                 invalidatedReason += self.tr('A schema must be chosen.\n')
             if self.tableComboBox.currentIndex() == 0:
                 invalidatedReason += self.tr('A table must be chosen.\n')
        else:
             if self.schemaComboBox.currentIndex() == 0:
                 invalidatedReason += self.tr('A schema must be chosen.\n')
             if self.tableComboBox.currentIndex() == 0:
                 invalidatedReason += self.tr('A table must be chosen.\n')
             if self.attributeComboBox.currentIndex() == 0:
                 invalidatedReason += self.tr('An attribute must be chosen.\n')
        return invalidatedReason

    def getJSONTag(self):
        if not self.validate():
            raise Exception(self.tr('Error in change filter customization ')+ self.title + ' : ' + self.validateDiagnosis())
        jsonList = []
        inhConstrDict = self.abstractDb.getInheritanceConstraintDict()
        if self.allAttributesCheckBox.checkState() == 2:
            tableName = self.tableComboBox.currentText()
            schema = self.schemaComboBox.currentText()
            self.batchGetJsonTag(schema, tableName, jsonList, inhConstrDict)
        elif self.allTablesCheckBox.checkState() == 2:
            tableList = self.inhTree['root'].keys()
            for tableName in tableList:
                schema = self.abstractDb.getTableSchemaFromDb(tableName)
                self.batchGetJsonTag(schema, tableName, jsonList, inhConstrDict)
        else:
            tableName = self.tableComboBox.currentText()
            schema = self.schemaComboBox.currentText()
            attrName = self.attributeComboBox.currentText()
            if tableName in self.domainDict.keys():
                if attrName in self.domainDict[tableName]['columns'].keys():
                    attrDomainDict = self.domainDict[tableName]['columns'][attrName]['values']
                    isMulti = self.domainDict[tableName]['columns'][attrName]['isMulti']
            newFilter = [i for i in attrDomainDict.keys() if attrDomainDict[i] in self.filterCustomSelectorWidget.toLs]
            self.getJsonTagFromOneTable(schema, tableName, attrName, jsonList, inhConstrDict, newFilter, isMulti)
        return jsonList

    def batchGetJsonTag(self, schema, tableName, jsonList, inhConstrDict):
        if tableName in self.domainDict.keys():
            for attrName in self.domainDict[tableName]['columns'].keys():
                attrDomainDict = self.domainDict[tableName]['columns'][attrName]['values']
                isMulti = self.domainDict[tableName]['columns'][attrName]['isMulti']
                newFilter = self.domainDict[tableName]['columns'][attrName]['constraintList']
                valueText = self.singleValueComboBox.currentText()
                code = [i for i in attrDomainDict.keys() if attrDomainDict[i] == valueText][0]
                if self.actionDict[self.actionComboBox.currentText()] == 'add':
                    if code not in newFilter: newFilter.append(code)
                elif self.actionDict[self.actionComboBox.currentText()] == 'addEmpty':
                    if newFilter == []:
                        continue
                else:
                    if code in newFilter: newFilter.pop(code)
                self.getJsonTagFromOneTable(schema, tableName, attrName, jsonList, inhConstrDict, newFilter, isMulti)

    def getJsonTagFromOneTable(self, schema, tableName, attrName, jsonList, inhConstrDict, newFilter, isMulti):
        originalFilterList = []
        if tableName in inhConstrDict.keys():
            if attrName in inhConstrDict[tableName].keys():
                originalFilterList = inhConstrDict[tableName][attrName]
        if originalFilterList == newFilter: return
        elif originalFilterList <> []:
            for item in originalFilterList:
                newElement = self.jsonBuilder.alterFilterElement(item['schema'], item['tableName'], attrName, item['constraintName'], item['filter'], newFilter, isMulti)
                if newElement not in jsonList:
                    jsonList.append(newElement)
        else:
            nodeLineage = self.utils.getNodeLineage(tableName, self.inhTree)
            firstInLineage = None
            for node in nodeLineage:
                if node in self.domainDict.keys():
                    if attrName in self.domainDict[node]['columns'].keys():
                        firstInLineage = node
                        break
                else:
                    schema = self.abstractDb.getTableSchemaFromDb(node)
                    if node in self.abstractDb.getAttributeListFromTable(schema, node):
                        firstInLineage = node
                        break
            newElement = self.jsonBuilder.alterFilterElement(schema, firstInLineage, attrName, '_'.join([firstInLineage,attrName,'ks']), [], newFilter, isMulti)
            if newElement not in jsonList:
                jsonList.append(newElement)

    def getUiParameterJsonDict(self):
        """
        builds a dict with the following format:
        {
            'schemaComboBox': --current text of schemaComboBox --
            'tableComboBox': ---current text of tableComboBox --
            'attributeComboBox': ---current text of attributeComboBox --
            'allAttributesCheckBox': --current state of allAttributesCheckBox--
            'allTablesCheckBox': --current state of allTablesCheckBox--
            'filterCustomSelectorWidgetToList': [--list of selected values on filterCustomSelectorWidget--]
            'singleValueComboBox': --current text of singleValueComboBox--
            'actionComboBoxIdx': --current index of actionComboBox--
        }
        """
        uiParameterJsonDict = dict()
        uiParameterJsonDict['schemaComboBox'] = self.schemaComboBox.currentText()
        uiParameterJsonDict['tableComboBox'] = self.tableComboBox.currentText()
        uiParameterJsonDict['attributeComboBox'] = self.attributeComboBox.currentText()
        uiParameterJsonDict['allAttributesCheckBox'] = self.allAttributesCheckBox.isChecked()
        uiParameterJsonDict['allTablesCheckBox'] = self.allTablesCheckBox.isChecked()
        uiParameterJsonDict['filterCustomSelectorWidgetToList'] = self.filterCustomSelectorWidget.toLs
        uiParameterJsonDict['singleValueComboBox'] = self.singleValueComboBox.currentText()
        uiParameterJsonDict['actionComboBoxIdx'] = self.actionComboBox.currentIndex()
        return uiParameterJsonDict
            
示例#45
0
class GenericDbManager(QObject):
    """
    This class manages the permissions on dsgtools databases.
    """
    def __init__(self,
                 serverAbstractDb,
                 dbDict,
                 edgvVersion,
                 parentWidget=None):
        super(GenericDbManager, self).__init__()
        self.parentWidget = parentWidget
        self.dbDict = dbDict
        self.serverAbstractDb = serverAbstractDb
        self.adminDb = self.instantiateAdminDb(serverAbstractDb)
        self.utils = Utils()
        self.extensionDict = {
            'EarthCoverage': '.dsgearthcov',
            'Customization': '.dsgcustom',
            'Style': '.dsgstyle',
            'ValidationConfig': '.dsgvalidcfg',
            'FieldToolBoxConfig': '.reclas',
            'Permission': '.dsgperm'
        }
        self.edgvVersion = edgvVersion

    def getManagerType(self):
        return str(self.__class__).split('.')[-1].replace('\'>', '').replace(
            'Manager', '')

    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

    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

    def instantiateTemplateDb(self, edgvVersion):
        """
        Instantiates a templateDb in the same server as serverAbstractDb. 
        If template does not exists, instantiateAdminDb calls createTemplate
        """
        templateName = self.serverAbstractDb.getTemplateName(edgvVersion)
        hasTemplate = self.serverAbstractDb.checkTemplate(edgvVersion)
        if not hasTemplate:
            self.serverAbstractDb.createTemplateDatabase(edgvVersion)
            templateDb = self.instantiateAbstractDb(templateName)
            templateDb.setStructureFromSql(edgvVersion, 4674)
            templateDb.setDbAsTemplate(version=edgvVersion)
        else:
            templateDb = self.instantiateAbstractDb(templateName)
        return templateDb

    def createAdminDb(self, serverAbstractDb, adminDb, host, port, user,
                      password):
        """
        Creates dsgtools_admindb
        """
        serverAbstractDb.createAdminDb()
        adminDb.connectDatabaseWithParameters(host, port, 'dsgtools_admindb',
                                              user, password)
        sqlPath = adminDb.getCreationSqlPath('admin')
        adminDb.runSqlFromFile(sqlPath)
        return adminDb

    def getSettings(self):
        """
        Gets all profiles from public.permission_profile
        """
        settingType = self.getManagerType()
        return self.adminDb.getAllSettingsFromAdminDb(settingType)

    def getSetting(self, name, edgvVersion):
        """
        Get setting from corresponding table on dsgtools_admindb
        """
        settingType = self.getManagerType()
        settingDict = json.loads(
            self.adminDb.getSettingFromAdminDb(settingType, name, edgvVersion))
        if not settingDict:
            raise Exception(
                self.tr("Setting ") + settingType +
                self.tr(" not found on dsgtools_admindb!"))
        return settingDict

    def createSetting(self, settingName, edgvVersion, jsonDict):
        """
        Creates setting on dsgtools_admindb.
        """
        settingType = self.getManagerType()
        if isinstance(jsonDict, dict):
            jsonDict = json.dumps(jsonDict, sort_keys=True, indent=4)
        self.adminDb.insertSettingIntoAdminDb(settingType, settingName,
                                              jsonDict, edgvVersion)

    def updateSetting(self, settingName, newJsonDict, edgvVersion=None):
        """
        Generic update. Can be reimplenented in child methods.
        1. Get property dict from adminDb 
        """
        if not edgvVersion:
            edgvVersion = self.edgvVersion
        errorDict = dict()
        successList = []
        settingType = self.getManagerType()
        propertyDict = self.adminDb.getPropertyPerspectiveDict(
            settingType, DsgEnums.Property, versionFilter=edgvVersion)
        if settingName in propertyDict.keys():
            rollbackList = []
            self.adminDb.db.transaction()
            try:
                for dbName in propertyDict[settingName]:
                    abstractDb = self.instantiateAbstractDb(dbName)
                    abstractDb.db.transaction()
                    rollbackList.append(abstractDb)
                    self.updateMaterializationFromDatabase(
                        abstractDb, propertyDict)
                    abstractDb.updateRecordFromPropertyTable(
                        settingType, settingName, edgvVersion, newJsonDict)
                self.adminDb.updateRecordFromPropertyTable(
                    settingType, settingName, edgvVersion, newJsonDict)
                for abstractDb in rollbackList:
                    abstractDb.db.commit()
                self.adminDb.db.commit()
                successList = [i for i in propertyDict[settingName]]
            except Exception as e:
                for abstractDb in rollbackList:
                    abstractDb.db.rollback()
                self.adminDb.db.rollback()
                errorDict[dbName] = ':'.join(e.args)
        return (successList, errorDict)

    def importSetting(self, fullFilePath):
        """
        Function to import profile into dsgtools_admindb. It has the following steps:
        1. Reads inputJsonFilePath and parses it into a python dict;
        2. Validates inputPermissionDict;
        3. Tries to insert into database, if there is an error, abstractDb raises an error which is also raised by importProfile
        """
        #getting profile name
        settingName = os.path.basename(fullFilePath).split('.')[0]
        #getting json
        inputJsonDict, inputJson = self.utils.readJsonFile(
            fullFilePath, returnFileAndDict=True)
        #error handling and json validation
        if inputJsonDict == dict():
            raise Exception(self.tr("Not valid DsgTools property file!"))
        if not self.validateJsonSetting(inputJsonDict):
            raise Exception(self.tr("Not valid DsgTools property file!"))
        if 'version' in inputJsonDict.keys():
            edgvVersion = inputJsonDict['version']
        else:
            edgvVersion = inputJsonDict.keys()[0].split('_')[-1]
        try:
            self.createSetting(settingName, edgvVersion, inputJson)
        except Exception as e:
            raise Exception(
                self.tr("Error importing setting ") + settingName + ': ' +
                ':'.join(e.args))

    def batchImportSettings(self, profilesDir):
        """
        1. Get all properties in profilesDir;
        2. Import each using importSetting;
        """
        importList = []
        for profile in os.walk(profilesDir).next()[2]:
            if self.extensionDict[self.getManagerType()] in os.path.basename(
                    profile):
                importList.append(os.path.join(profilesDir, profile))
        for profileFile in importList:
            self.importSetting(profileFile)

    def exportSetting(self, profileName, edgvVersion, outputPath):
        """
        1. Get setting from dsgtools_admindb;
        2. Export it to outputPath.
        """
        jsonDict = self.getSetting(profileName, edgvVersion)
        outputFile = os.path.join(
            outputPath,
            profileName + self.extensionDict[self.getManagerType()])
        with open(outputFile, 'w') as outfile:
            json.dump(jsonDict, outfile, sort_keys=True, indent=4)

    def batchExportSettings(self, outputDir):
        """
        1. Get all settings from corresponding table in dsgtools_admindb;
        2. Export each using exportSetting.
        """
        settingDict = self.getSettings()
        for edgvVersion in settingDict.keys():
            outputPath = os.path.join(outputDir, edgvVersion)
            if not os.path.exists(outputPath):
                os.makedirs(outputPath)
            for profileName in settingDict[edgvVersion]:
                self.exportSetting(profileName, edgvVersion, outputPath)

    def getPropertyPerspectiveDict(self,
                                   viewType=DsgEnums.Property,
                                   versionFilter=None):
        """
        Gets a dict in the format:
        if viewType == 'customization': {customizationName: ['-list of databases with customization']}
        if viewType == 'database': {databaseName: ['-list of customizations with customization']}
        """
        settingType = self.getManagerType()
        return self.adminDb.getPropertyPerspectiveDict(
            settingType, viewType, versionFilter=versionFilter)

    def getSettingVersion(self, settingName):
        settingType = self.getManagerType()
        return self.adminDb.getSettingVersion(settingType, settingName)

    def validateJsonSetting(self, inputJsonDict):
        """
        reimplemented in each child
        """
        return True

    def getRecordFromAdminDb(self, propertyName, edgvVersion):
        settingType = self.getManagerType()
        return self.adminDb.getRecordFromAdminDb(settingType, propertyName,
                                                 edgvVersion)

    def createAndInstall(self,
                         configName,
                         newJsonDict,
                         edgvVersion,
                         dbList=[]):
        self.createSetting(configName, edgvVersion, newJsonDict)
        return self.installSetting(configName, dbNameList=dbList)

    def installSetting(self, configName, dbNameList=[]):
        """
        Generic install. Can be reimplenented in child methods.
        """
        errorDict = dict()
        settingType = self.getManagerType()
        if dbNameList == []:
            dbNameList = self.dbDict.keys()
        successList = []
        configEdgvVersion = self.getSettingVersion(configName)
        for dbName in dbNameList:
            abstractDb = self.instantiateAbstractDb(dbName)
            edgvVersion = abstractDb.getDatabaseVersion()
            if edgvVersion != configEdgvVersion:
                errorDict[dbName] = self.tr('Database version missmatch.')
                continue
            recDict = self.adminDb.getRecordFromAdminDb(
                settingType, configName, edgvVersion)
            try:
                if not abstractDb.checkIfExistsConfigTable(settingType):
                    abstractDb.createPropertyTable(settingType,
                                                   useTransaction=True)
            except Exception as e:
                errorDict[dbName] = ':'.join(e.args)
                continue
            try:
                abstractDb.db.transaction()
                self.adminDb.db.transaction()
                self.materializeIntoDatabase(
                    abstractDb, recDict
                )  #step done when property management involves changing database structure
                abstractDb.insertRecordInsidePropertyTable(
                    settingType, recDict, edgvVersion)
                dbOid = abstractDb.getDbOID()
                self.adminDb.insertInstalledRecordIntoAdminDb(
                    settingType, recDict, dbOid)
                abstractDb.db.commit()
                self.adminDb.db.commit()
            except Exception as e:
                abstractDb.db.rollback()
                self.adminDb.db.rollback()
                errorDict[dbName] = ':'.join(e.args)
            successList.append(dbName)
        return (successList, errorDict)

    def deleteSetting(self, configName, dbNameList=[]):
        """
        Generic remove. Can be reimplenented in child methods.
        1. Get property dict from adminDb 
        """
        errorDict = dict()
        successList = []
        settingType = self.getManagerType()
        propertyDict = self.adminDb.getPropertyPerspectiveDict(
            settingType, DsgEnums.Property)
        if configName in propertyDict.keys():
            for dbName in propertyDict[configName]:
                abstractDb = self.instantiateAbstractDb(dbName)
                edgvVersion = abstractDb.getDatabaseVersion()
                try:
                    abstractDb.db.transaction()
                    self.adminDb.db.transaction()
                    self.undoMaterializationFromDatabase(
                        abstractDb, configName, settingType, edgvVersion
                    )  #step done when property management involves changing database structure
                    abstractDb.removeRecordFromPropertyTable(
                        settingType, configName, edgvVersion)
                    self.adminDb.removeRecordFromPropertyTable(
                        settingType, configName, edgvVersion)
                    abstractDb.db.commit()
                    self.adminDb.db.commit()
                except Exception as e:
                    abstractDb.db.rollback()
                    self.adminDb.db.rollback()
                    errorDict[dbName] = ':'.join(e.args)
                successList.append(dbName)
        return (successList, errorDict)

    def uninstallSetting(self, configName, dbNameList=[]):
        """
        Generic uninstall. Can be reimplenented in child methods.
        This can uninstall setting on a list of databases or in all databases (if dbNameList == [])
        """
        errorDict = dict()
        successList = []
        settingType = self.getManagerType()
        propertyDict = self.adminDb.getPropertyPerspectiveDict(
            settingType, DsgEnums.Property)
        if configName in propertyDict.keys():
            if dbNameList == []:  #builds filter dbList to uninstall in all installed databases
                dbList = propertyDict[configName]
            else:  #builds filter dbList to uninstall in databases in dbNameList
                dbList = [
                    i for i in propertyDict[configName] if i in dbNameList
                ]
            for dbName in dbList:
                abstractDb = self.instantiateAbstractDb(dbName)
                edgvVersion = abstractDb.getDatabaseVersion()
                try:
                    abstractDb.db.transaction()
                    self.adminDb.db.transaction()
                    self.undoMaterializationFromDatabase(
                        abstractDb, configName, settingType, edgvVersion
                    )  #step done when property management involves changing database structure
                    abstractDb.removeRecordFromPropertyTable(
                        settingType, configName, edgvVersion)
                    self.adminDb.uninstallPropertyOnAdminDb(settingType,
                                                            configName,
                                                            edgvVersion,
                                                            dbName=dbName)
                    abstractDb.db.commit()
                    self.adminDb.db.commit()
                except Exception as e:
                    abstractDb.db.rollback()
                    self.adminDb.db.rollback()
                    errorDict[dbName] = ':'.join(e.args)
                successList.append(dbName)
        return (successList, errorDict)

    def materializeIntoDatabase(self, abstractDb, propertyDict):
        """
        Method that is reimplemented in each child when installing a property involves changing any sort of database structure
        """
        pass

    def undoMaterializationFromDatabase(self, abstractDb, configName,
                                        settingType, edgvVersion):
        """
        Method that is reimplemented in each child when uninstalling a property involves changing any sort of database structure
        """
        pass

    def hasStructuralChanges(self, dbNameList):
        """
        Method that is reimplemented in each child
        """
        return []
示例#46
0
class LoadByCategory(QtGui.QDialog, load_by_category_dialog.Ui_LoadByCategory):
    def __init__(self, parent=None):
        """Constructor."""
        super(LoadByCategory, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.filename = ""
        self.dbLoaded = False
        self.epsg = 0
        self.crs = None
        self.categories = []
        self.selectedClasses = []

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

        #Sql factory generator
        self.isSpatialite = True

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

        self.parentTreeNode = None

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

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

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

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

    def __del__(self):
        self.closeDatabase()

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

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

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

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

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

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

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

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

        self.getDatabaseVersion()

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

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

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

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

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

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

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

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

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


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

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

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

    def loadDatabase(self):
        self.closeDatabase()

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

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

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

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

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

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

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

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

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

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

            self.loadPostGISLayers(type, categories, layer_names)

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

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

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

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

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

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

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

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

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

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

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

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

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

    def loadEDGVLayer(self, uri, layer_name, provider, idSubgrupo):
        vlayer = QgsVectorLayer(uri.uri(), layer_name, provider)
        vlayer.setCrs(self.crs)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer) #added due to api changes
        if self.isSpatialite and (self.dbVersion == '3.0' or self.dbVersion == '2.1.3'):
            lyr = '_'.join(layer_name.replace('\r', '').split('_')[1::])
        else:
            lyr = layer_name.replace('\r','')
        vlayerQml = os.path.join(self.qmlPath, lyr+'.qml')
        vlayer.loadNamedStyle(vlayerQml, False)
        QgsMapLayerRegistry.instance().addMapLayer(vlayer)
        qgis.utils.iface.legendInterface().moveLayer(vlayer, idSubgrupo)
        if not vlayer.isValid():
            QgsMessageLog.logMessage(vlayer.error().summary(), "DSG Tools Plugin", QgsMessageLog.CRITICAL)
示例#47
0
class ManageComplexDialog(QDialog, Ui_Dialog):
    def __init__(self, iface, db, table):
        """Constructor.
        """
        QDialog.__init__( self )
        self.setupUi( self )

        #qgis interface
        self.iface = iface

        #database conenction
        self.db = db
        #table name
        self.table = table
        #rows that are marked for removal
        self.toBeRemoved = []

        #adjusting the table name to match the correspondent qml file
        fileName = table.replace('complexos_', '')
        fileName = fileName.split('.')[-1]+'.qml'

        #obtaining the qml file path
        self.utils = Utils()
        qmlDirPath = self.utils.getQmlDir(db)
        qmlPath = os.path.join(qmlDirPath, fileName)

        #getting the domain dictionary that will be used to generate the comboboxes
        try:
            parser = QmlParser(qmlPath)
            self.domainDict = parser.getDomainDict()
        except:
            self.domainDict = dict()
            pass

        QObject.connect(self.addRow, SIGNAL(("clicked()")), self.addComplex)
        QObject.connect(self.removeRow, SIGNAL(("clicked()")), self.removeComplex)
        QObject.connect(self.updateButton, SIGNAL(("clicked()")), self.updateTable)
        QObject.connect(self.cancelButton, SIGNAL(("clicked()")), self.cancel)

        self.updateTableView()

    def generateCombos(self):
        self.combos = []
        for key in self.domainDict:
            self.generateCombo(key, self.domainDict[key])

    def generateCombo(self, column, domainValues):
        combo = ComboBoxDelegate(self,domainValues, self.projectModel.fieldIndex(column))
        self.tableView.setItemDelegateForColumn(self.projectModel.fieldIndex(column), combo)

    def updateTableView(self):
        #setting the model in the view
        self.projectModel = CustomTableModel(self.domainDict, None, self.db)
        #adjusting the table
        self.projectModel.setTable(self.table)
        #manual commit rule
        self.projectModel.setEditStrategy(QSqlTableModel.OnManualSubmit)
        #selecting all item from the table
        self.projectModel.select()
        #creating the comboboxes to map the domain values
        self.generateCombos()

        #case the first record is null we make some adjustments
        #this is not supposed to happen
        record = self.projectModel.record(0)
        if not record.value("id"):
            adjustedRecord = self.adjustRecord(record)
            self.projectModel.setRecord(0, adjustedRecord)

        self.tableView.setModel(self.projectModel)

        #Hiding columns that point to other complexes so that the user can't change them
        for i in range(self.projectModel.columnCount()):
            columnName = self.projectModel.headerData(i, Qt.Horizontal)
            if 'id_' in columnName:
                self.tableView.hideColumn(i)

        self.tableView.show()

    def addComplex(self):
        record = self.projectModel.record()
        adjustedRecord = self.adjustRecord(record)
        self.projectModel.insertRecord(self.projectModel.rowCount(), adjustedRecord)

    def adjustRecord(self,record):
        #insert a new record with an already determined uuid value
        record.setValue("id",str(uuid4()))
        record.setValue("nome", self.tr("edit this field"))
        for i in range(self.projectModel.columnCount()):
            columnName = self.projectModel.headerData(i, Qt.Horizontal)
            if self.domainDict.has_key(columnName):
                record.setValue(columnName, self.tr("edit this field"))
        return record

    def removeComplex(self):
        #getting the selected rows
        selectionModel = self.tableView.selectionModel()
        selectedRows = selectionModel.selectedRows()
        for row in selectedRows:
            #storing the complex to be removed
            record = self.projectModel.record(row.row())
            uuid = str(record.value("id"))
            if uuid not in self.toBeRemoved:
                self.toBeRemoved.append(uuid)
            self.projectModel.removeRow(row.row())

    def cancel(self):
        self.done(0)

    def checkComplexNameField(self):
        count = self.projectModel.rowCount()
        for i in range(count):
            record = self.projectModel.record(i)
            if record.isNull('nome'):
                QMessageBox.warning(self.iface.mainWindow(), self.tr("Warning!"), self.tr('The field: \'nome\' must be filled in all rows. Please, check and try again.'))
                return False
        return True

    def updateTable(self):
        #checking if the name field is filled
        #Now the database checks the field "nome", therefore the method checkComplexNameField() is no longer needed
#         if not self.checkComplexNameField():
#             return

        #emit the signal to disassocite all features from the complexes marked for removal
        self.emit(SIGNAL("markedToRemove( PyQt_PyObject )"), self.toBeRemoved)
        #commmiting all pending changes
        if not self.projectModel.submitAll():
            #In case something went wrong we show the message to the user
            QMessageBox.warning(self.iface.mainWindow(), self.tr("Error!"), self.projectModel.lastError().text())

        #Emit the signal to update the complex tree
        self.emit( SIGNAL( "tableUpdated()" ))
示例#48
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)
示例#49
0
class EDGVLayerLoader(QObject):
    def __init__(self, iface, abstractDb, loadCentroids):
        """Constructor."""
        super(EDGVLayerLoader, self).__init__()

        self.abstractDb = abstractDb
        self.uri = QgsDataSourceURI()
        self.iface = iface
        self.utils = Utils()
        self.logErrorDict = dict()
        self.errorLog = ''
        self.geomTypeDict = self.abstractDb.getGeomTypeDict(loadCentroids)
        self.geomDict = self.abstractDb.getGeomDict(self.geomTypeDict)
        self.correspondenceDict = {
            'POINT': 'Point',
            'MULTIPOINT': 'Point',
            'LINESTRING': 'Line',
            'MULTILINESTRING': 'Line',
            'POLYGON': 'Area',
            'MULTIPOLYGON': 'Area'
        }

    def preLoadStep(self, inputList):
        if len(inputList) == 0:
            return [], False
        else:
            if isinstance(inputList[0], dict):
                lyrList = [i['tableName'] for i in inputList]
                return lyrList, True
            else:
                return inputList, False

    def load(self,
             layerList,
             useQml=False,
             uniqueLoad=False,
             useInheritance=False,
             stylePath=None,
             onlyWithElements=False):
        return None

    def getStyle(self, stylePath, className):
        if 'db:' in stylePath['style']:
            return self.abstractDb.getStyle(stylePath['style'].split(':')[-1],
                                            className)
        else:
            return self.getStyleFromFile(stylePath['style'], 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

    def prepareLoad(self):
        dbName = self.abstractDb.getDatabaseName()
        groupList = iface.legendInterface().groups()
        if dbName in groupList:
            return groupList.index(dbName)
        else:
            parentTreeNode = iface.legendInterface().addGroup(
                self.abstractDb.getDatabaseName(), -1)
            return parentTreeNode

    def createMeasureColumn(self, layer):
        if layer.geometryType() == QGis.Polygon:
            layer.addExpressionField(
                '$area', QgsField(self.tr('area_otf'), QVariant.Double))
        elif layer.geometryType() == QGis.Line:
            layer.addExpressionField(
                '$length', QgsField(self.tr('lenght_otf'), QVariant.Double))
        return layer

    def getDatabaseGroup(self, groupList):
        dbName = self.abstractDb.getDatabaseName()
        if dbName in groupList:
            return groupList.index(dbName)
        else:
            return self.iface.legendInterface().addGroup(dbName, True, -1)

    def getLyrDict(self, inputList, isEdgv=True):
        """
        Builds lyrDict in order to build loading tree
        lyrList: list of layers to be loaded
        isEdgv: optional parameter to indicate when db is not edgv. If db is not edgv, layers will be grouped by schema.
        """
        lyrDict = dict()
        if isinstance(inputList, list):
            if len(inputList) > 0:
                if isinstance(inputList[0], dict):
                    for elem in inputList:
                        if elem['geomType'] == 'GEOMETRY':
                            continue
                        if self.correspondenceDict[
                                elem['geomType']] not in lyrDict.keys():
                            lyrDict[self.correspondenceDict[
                                elem['geomType']]] = dict()
                        if elem['cat'] not in lyrDict[self.correspondenceDict[
                                elem['geomType']]].keys():
                            lyrDict[self.correspondenceDict[elem['geomType']]][
                                elem['cat']] = []
                        lyrDict[self.correspondenceDict[elem['geomType']]][
                            elem['cat']].append(elem)
                else:
                    for type in self.geomTypeDict.keys():
                        # some tables are only registered as GEOMETRY and should not be considered
                        if type == 'GEOMETRY':
                            continue
                        if self.correspondenceDict[type] not in lyrDict.keys():
                            lyrDict[self.correspondenceDict[type]] = dict()
                        for lyr in self.geomTypeDict[type]:
                            if lyr in inputList:
                                if isEdgv:
                                    cat = lyr.split('_')[0]
                                else:
                                    cat = self.abstractDb.getTableSchemaFromDb(
                                        lyr)
                                if cat not in lyrDict[
                                        self.correspondenceDict[type]].keys():
                                    lyrDict[self.correspondenceDict[type]][
                                        cat] = []
                                lyrDict[self.correspondenceDict[type]][
                                    cat].append(lyr)
                    for type in lyrDict.keys():
                        if lyrDict[type] == dict():
                            lyrDict.pop(type)
        return lyrDict

    def prepareGroups(self, groupList, parent, lyrDict):
        aux = dict()
        groupDict = dict()
        groupNodeList = lyrDict.keys()
        groupNodeList.sort(reverse=True)
        for geomNode in groupNodeList:
            groupDict[geomNode] = dict()
            aux = self.createGroup(groupList, geomNode, parent)
            catList = lyrDict[geomNode].keys()
            catList.sort()
            for catNode in catList:
                groupDict[geomNode][catNode] = self.createGroup(
                    groupList, catNode, aux)
        return groupDict

    def createGroup(self, groupList, groupName, parent):
        subgroup = groupList[parent::]
        if groupName in subgroup:
            return parent + subgroup.index(groupName)  #verificar
        else:
            return self.iface.legendInterface().addGroup(
                groupName, True, parent)

    def loadDomains(self, layerList, loadedLayers, domainGroup):
        domLayerDict = dict()
        qmlDict = self.abstractDb.getQmlDict(layerList)
        for lyr in layerList:
            if lyr in qmlDict.keys():
                for attr in qmlDict[lyr].keys():
                    domain = qmlDict[lyr][attr]
                    domLyr = self.checkLoaded(domain, loadedLayers)
                    if not domLyr:
                        domLyr = self.loadDomain(domain, domainGroup)
                        loadedLayers.append(domLyr)
                        domLyrName = domLyr.name()
                    if lyr not in domLayerDict.keys():
                        domLayerDict[lyr] = dict()
                    if attr not in domLayerDict[lyr].keys():
                        domLayerDict[lyr][attr] = domLyr
        return domLayerDict

    def logError(self):
        msg = ''
        for lyr in self.logErrorDict:
            msg += self.tr(
                'Error for lyr ') + lyr + ': ' + self.logErrorDict[lyr] + '\n'
        self.errorLog += msg

    def setDataSource(self, schema, layer, geomColumn, sql, pkColumn='id'):
        self.uri.setDataSource(schema, layer, geomColumn, sql, pkColumn)
        if sql == '':
            self.uri.disableSelectAtId(False)
        else:
            self.uri.disableSelectAtId(True)

    def setDomainsAndRestrictionsWithQml(self, vlayer):
        qmldir = ''
        try:
            qmldir, qmlType = self.abstractDb.getQml(vlayer.name())
        except Exception as e:
            QgsMessageLog.logMessage(':'.join(e.args), "DSG Tools Plugin",
                                     QgsMessageLog.CRITICAL)
            return None
        if qmlType == 'db':
            vlayer.applyNamedStyle(qmldir)
        else:
            vlayerQml = os.path.join(qmldir, vlayer.name() + '.qml')
            #treat case of qml with multi
            vlayer.loadNamedStyle(vlayerQml, False)
        return vlayer
示例#50
0
class CustomTableSelector(QtGui.QWidget, FORM_CLASS):
    selectionChanged = pyqtSignal(list,str)

    def __init__(self, customNumber = None, parent = None):
        """Constructor."""
        super(self.__class__, self).__init__(parent)
        self.fromLs = []
        self.toLs = []
        self.utils = Utils()
        self.setupUi(self)
    
    def resizeTrees(self):
        """
        Expands headers
        """
        self.fromTreeWidget.expandAll()
        self.fromTreeWidget.header().setResizeMode(QtGui.QHeaderView.ResizeToContents)
        self.fromTreeWidget.header().setStretchLastSection(False)
        self.toTreeWidget.expandAll()
        self.toTreeWidget.header().setResizeMode(QtGui.QHeaderView.ResizeToContents)
        self.toTreeWidget.header().setStretchLastSection(False)
    
    def sortItems(self, treeWidget):
        """
        Sorts items from input treeWidget
        """
        rootNode = treeWidget.invisibleRootItem()
        rootNode.sortChildren(0, Qt.AscendingOrder)
        for i in range(rootNode.childCount()):
            rootNode.child(i).sortChildren(1, Qt.AscendingOrder)
    
    def setTitle(self,title):
        """
        Setting the title
        """
        self.groupBox.setTitle(title)
    
    def setFilterColumn(self, customNumber = None):
        """
        Chooses which column is going to be used in the filter
        """
        if isinstance(customNumber, int):
            self.filterColumnKey = self.headerList[customNumber]
        elif self.headerList:
            self.filterColumnKey = self.headerList[1]
        else:
            self.filterColumnKey = self.headerList[0]
    
    def clearAll(self):
        """
        Clears everything to return to the initial state
        """
        self.filterLineEdit.clear()
    
    def setHeaders(self, headerList, customNumber = None):
        """
        Sets fromTreeWidget and toTreeWidget headers
        """
        self.headerList = headerList
        self.fromTreeWidget.setHeaderLabels(headerList)
        self.toTreeWidget.setHeaderLabels(headerList)
        self.setFilterColumn(customNumber = customNumber)
    
    def setInitialState(self, fromDictList, unique=False):
        """
        Sets the initial state
        """
        self.fromLs = []
        self.toLs = []
        self.fromTreeWidget.clear()
        self.fromTreeWidget.clear()
        if not isinstance(fromDictList, int):
            self.addItemsToTree(self.fromTreeWidget, fromDictList, self.fromLs, unique = unique)
    
    def getChildNode(self, parentNode, textList):
        """
        Returns child node with columns equals to textList items. If no node is found, return None
        """
        for i in range(parentNode.childCount()):
            nodeFound = True
            childNode = parentNode.child(i)
            for j in range(len(textList)):
                if childNode.text(j) != textList[j]:
                    nodeFound = False
                    break
            if nodeFound:
                return childNode
        return None

    def addItemsToTree(self, treeWidget, addItemDictList, controlList, unique = False):
        """
        Adds items from addItemDictList in treeWidget.
        addItemDictList = [-list of dicts with keys corresponding to header list texts-]
        unique: only adds item if it is not in already in tree
        """
        rootNode = treeWidget.invisibleRootItem() #invisible root item
        for dictItem in addItemDictList:
            firstColumnChild = self.getChildNode(rootNode, [dictItem[self.headerList[0]]]+['']*(len(self.headerList)-1)) #looks for a item in the format ['first column text', '','',...,'']
            if not firstColumnChild:
                firstColumnChild = self.utils.createWidgetItem(rootNode,dictItem[self.headerList[0]],0)
            textList = [dictItem[self.headerList[i]] for i in range(len(self.headerList))]
            if unique:
                childNode = self.getChildNode(firstColumnChild, textList)
                if not childNode:
                    item = self.utils.createWidgetItem(firstColumnChild,textList)
                    itemList = self.getItemList(item)
                    if itemList not in controlList:
                        controlList.append(itemList)
            else:
                item = self.utils.createWidgetItem(firstColumnChild,textList)
                itemList = self.getItemList(item)
                controlList.append(itemList)
        self.resizeTrees()
        self.sortItems(treeWidget)
    
    def getItemList(self, item, returnAsDict = False):
        """
        Gets item as a list
        """
        if returnAsDict:
            returnItem = dict()
        else:
            returnItem = []
        for i in range(item.columnCount()):
            if returnAsDict:
                returnItem[self.headerList[i]] = item.text(i)
            else:
                returnItem.append(item.text(i))
        return returnItem

    def getLists(self, sender):
        """
        Returns a list composed by (originTreeWidget, --list that controls previous originTreeWidget--, destinationTreeWidget, --list that controls previous destinationTreeWidget--)
        """
        text = sender.text()
        if text == '>':
            return self.fromTreeWidget, self.fromLs, self.toTreeWidget, self.toLs, False
        if text == '>>':
            return self.fromTreeWidget, self.fromLs, self.toTreeWidget, self.toLs, True
        if text == '<':
            return self.toTreeWidget, self.toLs, self.fromTreeWidget, self.fromLs, False
        if text == '<<':
            return self.toTreeWidget, self.toLs, self.fromTreeWidget, self.fromLs, True

    @pyqtSlot(bool, name='on_pushButtonSelectOne_clicked')
    @pyqtSlot(bool, name='on_pushButtonDeselectOne_clicked')
    @pyqtSlot(bool, name='on_pushButtonSelectAll_clicked')
    @pyqtSlot(bool, name='on_pushButtonDeselectAll_clicked')
    def selectItems(self, isSelected, selectedItems=[]):
        """
        Adds the selected items to the "to" list
        """
        #gets lists
        originTreeWidget, originControlLs, destinationTreeWidget, destinationControlLs, allItems = self.getLists(self.sender())
        #root nodes
        originRoot = originTreeWidget.invisibleRootItem()
        destinationRoot = destinationTreeWidget.invisibleRootItem()
        selectedItemList = []
        self.getSelectedItems(originRoot, selectedItemList)
        for i in range(originRoot.childCount())[::-1]:
            catChild = originRoot.child(i)
            #if son of originRootNode is selected, adds it to destinationRootNode
            moveNode = allItems or (catChild in selectedItemList)
            #get destination parent, creates one in destination if not exists
            destinationCatChild = self.getDestinationNode(destinationRoot, catChild)
            for j in range(catChild.childCount())[::-1]:
                nodeChild = catChild.child(j)
                moveChild = (nodeChild in selectedItemList) or moveNode
                if self.moveChild(catChild, j, destinationCatChild, moveChild):
                    itemList = self.getItemList(nodeChild)
                    destinationControlLs.append(itemList)
                    originControlLs.pop(originControlLs.index(itemList))
            destinationCatChild.sortChildren(1, Qt.AscendingOrder)
            if catChild.childCount() == 0:
                originRoot.takeChild(i)
            destinationRoot.sortChildren(0, Qt.AscendingOrder)
        for i in range(destinationRoot.childCount())[::-1]:
            if destinationRoot.child(i).childCount() == 0:
                destinationRoot.takeChild(i)
        destinationRoot.sortChildren(0, Qt.AscendingOrder)
        self.resizeTrees()

    def getSelectedItems(self, treeWidgetNode, itemList):
        """
        Recursive method to get all selected nodes of treeWidget
        """
        for i in range(treeWidgetNode.childCount()):
            childItem = treeWidgetNode.child(i)
            if childItem.isSelected() and (childItem not in itemList):
                itemList.append(childItem)
            for j in range(childItem.childCount()):
                self.getSelectedItems(childItem, itemList)
    
    def moveChild(self, parentNode, idx, destinationNode, isSelected):
        """
        If node is selected, removes node from parentNode and adds it to destinationNode
        """
        if isSelected:
            child = parentNode.takeChild(idx)
            destinationNode.addChild(child)
            return True
        else:
            return False

    def getDestinationNode(self, destinationRoot, catChild, returnNew = True):
        """
        Looks for node in destination and returns it. If none is found, creates one and returns it
        """
        #get destination parent, creates one in destination if not exists
        destinationCatChild = None
        if isinstance(catChild,list):
            comparisonText = catChild[0]
            if returnNew:
                itemTextList = [catChild[i] for i in range(len(catChild))]
        else:
            comparisonText = catChild.text(0)
            if returnNew:
                itemTextList = [catChild.text(i) for i in range(catChild.columnCount())]

        for i in range(destinationRoot.childCount()):
            candidate = destinationRoot.child(i)
            if candidate.text(0) == comparisonText:
                #if candidate is found, returns candidate
                return candidate
        #if candidate is not found, creates one and returns it
        if returnNew:
            if not destinationCatChild:
                return QTreeWidgetItem(destinationRoot,itemTextList)
        else:
            return None
    
    def on_filterLineEdit_textChanged(self, text):
        """
        Filters the items to make it easier to spot and select them
        """
        classes = [node[1].lower() for node in self.fromLs if text.lower() in node[1].lower()] #text list
        filteredClasses = [i for i in classes if i.lower() not in [j[1].lower() for j in self.toLs]] #text list
        self.filterTree(self.fromTreeWidget, self.fromLs, filteredClasses, 1)
        self.resizeTrees()
    
    def filterTree(self, treeWidget, controlList, filterList, columnIdx):
        '''
        Actual filter
        '''
        treeWidget.clear()
        rootNode = treeWidget.invisibleRootItem()
        #remove items that are not in filterList
        for item in controlList:
            if item[columnIdx].lower() in filterList:
                firstColumnChild = self.getChildNode(rootNode, [item[0]]+['']*(len(item)-1)) #looks for a item in the format ['first column text', '','',...,'']
                if not firstColumnChild:
                    firstColumnChild = self.utils.createWidgetItem(rootNode, item[0], 0)
                QTreeWidgetItem(firstColumnChild, item)
        rootNode.sortChildren(0, Qt.AscendingOrder)
        for i in range(rootNode.childCount()):
            rootNode.child(i).sortChildren(1, Qt.AscendingOrder)
    
    def getSelectedNodes(self, concatenated = True):
        """
        Returns a list of selected nodes converted into a string separated by ','
        """
        selected = []
        rootNode = self.toTreeWidget.invisibleRootItem()
        for i in range(rootNode.childCount()):
            catNode = rootNode.child(i)
            for j in range(catNode.childCount()):
                item = catNode.child(j)
                if concatenated:
                    catList = [item.text(i) for i in range(item.columnCount())]
                    selected.append(','.join(catList))
                else:
                    selected.append(item)
        return selected

    def addItemsToWidget(self, itemList, unique = False):
        """
        Adds items to tree that is already built.
        """
        self.addItemsToTree(self.fromTreeWidget, itemList, self.fromLs, unique = unique)
    
    def removeItemsFromWidget(self, removeList):
        """
        Searches both lists and removes items that are in removeList
        """
        self.removeItemsFromTree(removeList, self.fromTreeWidget, self.fromLs)
        self.removeItemsFromTree(removeList, self.toTreeWidget, self.toLs)
    
    def removeItemsFromTree(self, dictItemList, treeWidget, controlList):
        """
        Searches treeWidget and removes items that are in removeList and updates controlList
        """        
        treeRoot = treeWidget.invisibleRootItem()
        catList = [i[self.headerList[0]] for i in dictItemList]
        returnList = []
        for i in range(treeRoot.childCount())[::-1]:
            catChild = treeRoot.child(i)
            if catChild.text(0) in catList:
                for j in range(catChild.childCount())[::-1]:
                    nodeChild = catChild.child(j)
                    nodeChildDict = self.getItemList(nodeChild, returnAsDict = True)
                    nodeChildDict[self.headerList[0]] = catChild.text(0)
                    if nodeChildDict in dictItemList:
                        catChild.takeChild(j)
                        itemList = self.getItemList(nodeChild)
                        controlList.pop(controlList.index(itemList))
        for i in range(treeRoot.childCount())[::-1]:
            if treeRoot.child(i).childCount() == 0:
                treeRoot.takeChild(i)
        treeRoot.sortChildren(0, Qt.AscendingOrder)
        for i in range(treeRoot.childCount()):
            treeRoot.child(i).sortChildren(1, Qt.AscendingOrder)
class GenericManagerWidget(QtGui.QWidget, FORM_CLASS):
    Install, Delete, Uninstall, Update, Create = range(5)
    def __init__(self, genericDbManager = None, parent = None):
        """
        Constructor
        """
        super(GenericManagerWidget, self).__init__(parent)
        self.setupUi(self)
        self.genericDbManager = genericDbManager
        self.versionDict = {'2.1.3':1, 'FTer_2a_Ed':2, 'Non_Edgv':3}
        self.textDict = {'EarthCoverage':self.tr('Earth Coverage'), 
                            'Customization':self.tr('Customization'), 
                            'Style':self.tr('Style'), 
                            'ValidationConfig':self.tr('Validation'), 
                            'FieldToolBoxConfig':self.tr('Field Toolbox Configuration'),
                            'Permission':self.tr('Permissions')}
        self.captionDict = {'EarthCoverage':self.tr('Earth Coverage'), 
                            'Customization':self.tr('Customization'), 
                            'Style':self.tr('Style'), 
                            'ValidationConfig':self.tr('Validation'), 
                            'FieldToolBoxConfig':self.tr('Reclassification Setup Files'),
                            'Permission':self.tr('Select a dsgtools permission profile')}
        self.filterDict = {'EarthCoverage':self.tr('Earth Coverage Setup File (*.dsgearthcov)'), 
                            'Customization':self.tr('DsgTools Customization File (*.dsgcustom)'), 
                            'Style':self.tr('DsgTools Styles File (*.dsgstyle)'), 
                            'ValidationConfig':self.tr('DsgTools Validation Configuration File (*.dsgvalidcfg)'), 
                            'FieldToolBoxConfig':self.tr('Reclassification Setup Files (*.reclas)'),
                            'Permission':self.tr('DsgTools Permission Profile File (*.dsgperm)')}
        self.widgetName = self.textDict[self.getWhoAmI()]
        self.genericDict = None
        self.setComponentsEnabled(False)
        self.utils = Utils()
        self.setHeaders()
        self.setButtons()
        self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeWidget.customContextMenuRequested.connect(self.createMenuAssigned)
       
    def setButtons(self):
        createText = self.createPushButton.text()
        self.createPushButton.setText(createText.replace(self.tr('Setting'),self.widgetName))
        deleteText = self.deletePushButton.text()
        self.deletePushButton.setText(deleteText.replace(self.tr('Setting'),self.widgetName))
    
    def setHeaders(self):
        viewType = self.getViewType()
        if viewType == DsgEnums.Database:
            self.treeWidget.setHeaderLabels([self.tr('Database'), self.widgetName])
        else:
            self.treeWidget.setHeaderLabels([self.widgetName, self.tr('Database')])
        return viewType
    
    def getWhoAmI(self):
        return str(self.__class__).split('.')[-1].replace('\'>', '').replace('ManagerWidget','')
    
    def setChildParameter(self):
        """
        Reimplement in each child
        """
        pass
    
    def setComponentsEnabled(self, enabled):
        """
        Changes states of all components of the widget, according to the boolean parameter enabled.
        """
        self.treeWidget.setEnabled(enabled)
        self.importPushButton.setEnabled(enabled)
        self.batchImportPushButton.setEnabled(enabled)
        self.exportPushButton.setEnabled(enabled)
        self.batchExportPushButton.setEnabled(enabled)
        self.databasePerspectivePushButton.setEnabled(enabled)
        self.propertyPerspectivePushButton.setEnabled(enabled)

    def populateConfigInterface(self, templateDb, jsonDict = None):
        """
        Must be reimplemented in each child
        """
        pass    

    def readJsonFromDatabase(self, propertyName, edgvVersion):
        """
        Reads the profile file, gets a dictionary of it and builds the tree widget
        """
        self.genericDict = self.genericDbManager.getCustomization(propertyName, edgvVersion)

    @pyqtSlot(bool)
    def on_importPushButton_clicked(self):
        """
        Imports a property file into dsgtools_admindb
        """
        fd = QFileDialog()
        widgetType = self.getWhoAmI()
        filename = fd.getOpenFileName(caption=self.captionDict[widgetType],filter=self.filterDict[widgetType])
        if filename == '':
            QMessageBox.warning(self, self.tr('Warning!'), self.tr('Warning! Select a file to import!'))
            return
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            self.genericDbManager.importSetting(filename)
            QApplication.restoreOverrideCursor()
            QMessageBox.information(self, self.tr('Success!'), self.widgetName + self.tr(' successfully imported.'))
        except Exception as e:
            QApplication.restoreOverrideCursor()
            QMessageBox.critical(self, self.tr('Error!'), self.tr('Error! Problem importing ') +self.widgetName + ': '  + ':'.join(e.args))
        self.refresh()
    
    @pyqtSlot(bool)
    def on_exportPushButton_clicked(self):
        """
        Export selected properties.
        """
        exportPropertyList = self.selectConfig()
        if exportPropertyList == []:
            QMessageBox.warning(self, self.tr('Warning!'), self.tr('Warning! Select a profile to export!'))
            return
        fd = QFileDialog()
        folder = fd.getExistingDirectory(caption = self.tr('Select a folder to output'))
        if folder == '':
            QMessageBox.warning(self, self.tr('Warning!'), self.tr('Warning! Select a output!'))
            return
        edgvVersion = self.genericDbManager.edgvVersion
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            for exportProperty in exportPropertyList:
                self.genericDbManager.exportSetting(exportProperty, edgvVersion, folder)
            QApplication.restoreOverrideCursor()
            QMessageBox.information(self, self.tr('Success!'), self.widgetName + self.tr(' successfully exported.'))
        except Exception as e:
            QApplication.restoreOverrideCursor()
            QMessageBox.critical(self, self.tr('Error!'), self.tr('Error! Problem exporting ') + self.widgetName + ': ' + ':'.join(e.args))
        
    @pyqtSlot(bool)
    def on_batchExportPushButton_clicked(self):
        """
        Exports all configs from dsgtools_admindb.
        """
        fd = QFileDialog()
        folder = fd.getExistingDirectory(caption = self.tr('Select a folder to output'))
        if folder == '':
            QMessageBox.warning(self, self.tr('Warning!'), self.tr('Warning! Select a output!'))
            return
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            self.genericDbManager.batchExportSettings(folder)
            QApplication.restoreOverrideCursor()
            QMessageBox.information(self, self.tr('Success!'), self.widgetName + self.tr(' successfully exported.'))
        except Exception as e:
            QApplication.restoreOverrideCursor()
            QMessageBox.critical(self, self.tr('Error!'), self.tr('Error! Problem exporting ') + self.widgetName + ': ' + ':'.join(e.args))
    
    @pyqtSlot(bool)
    def on_batchImportPushButton_clicked(self):
        """
        Imports all config files from a folder into dsgtools_admindb. It only works for a single type of config per time.
        """
        fd = QFileDialog()
        folder = fd.getExistingDirectory(caption = self.tr('Select a folder with json files: '))
        if folder == '':
            QMessageBox.warning(self, self.tr('Warning!'), self.tr('Warning! Select a input folder!'))
            return
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            self.genericDbManager.batchImportSettings(folder)
            QApplication.restoreOverrideCursor()
            QMessageBox.information(self, self.tr('Success!'), self.widgetName + self.tr(' successfully imported.'))
        except Exception as e:
            QApplication.restoreOverrideCursor()
            QMessageBox.critical(self, self.tr('Error!'), self.tr('Error! Problem importing ') + self.widgetName + ': ' + ':'.join(e.args))

    @pyqtSlot(bool)
    def on_applyPushButton_clicked(self):
        dbList = self.genericDbManager.dbDict.keys()
        successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Install, dbList = dbList)
        header, operation = self.getApplyHeader()
        self.outputMessage(operation, header, successDict, exceptionDict)

    @pyqtSlot(bool)
    def on_deletePushButton_clicked(self):
        successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Delete)
        header, operation = self.getDeleteHeader()
        self.outputMessage(operation, header, successDict, exceptionDict)

    @pyqtSlot(bool)
    def on_uninstallFromSelectedPushButton_clicked(self):
        dbList = []
        successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Uninstall, dbList)
        header, operation = self.getUninstallFromSelected()
        self.outputMessage(operation, header, successDict, exceptionDict)

    def getViewType(self):
        if self.databasePerspectivePushButton.isChecked():
            return DsgEnums.Database
        else:
            return DsgEnums.Property

    @pyqtSlot(bool, name='on_databasePerspectivePushButton_clicked')
    @pyqtSlot(bool, name='on_propertyPerspectivePushButton_clicked')
    def refresh(self):
        viewType = self.setHeaders()
        propertyPerspectiveDict = self.genericDbManager.getPropertyPerspectiveDict(viewType)
        self.treeWidget.clear()
        rootNode = self.treeWidget.invisibleRootItem()
        if viewType == DsgEnums.Database:
            propertyList = self.genericDbManager.dbDict.keys()
        else:
            propertyList = propertyPerspectiveDict.keys()
        for key in propertyList:
            parentCustomItem = self.utils.createWidgetItem(rootNode, key, 0)
            if key in propertyPerspectiveDict.keys():
                for item in propertyPerspectiveDict[key]:
                    if item and item <> '':
                        dbItem = self.utils.createWidgetItem(parentCustomItem, item, 1)
        self.treeWidget.sortItems(0, Qt.AscendingOrder)
        self.treeWidget.expandAll()
        self.treeWidget.header().setResizeMode(QtGui.QHeaderView.ResizeToContents)
        self.treeWidget.header().setStretchLastSection(False)
    
    def outputMessage(self, operation, header, successDict, exceptionDict):
        """
        successDict = {configName: [--list of successful databases--]}
        exceptionDict = {configName: {dbName: errorText}}
        """
        viewType = self.getViewType()
        msg = header
        for setting in successDict.keys():
            successList = successDict[setting]
            if len(successDict[setting]) > 0:
                msg += self.tr('\nSuccessful ')
                msg += operation + ' : '
                msg += setting
                if successList:
                    if len(successList) > 0:
                        try:
                            msg += self.tr(' on databases ') + ', '.join(successList)
                        except: #none type case, just add .
                            msg += '.'
        msg += self.logInternalError(exceptionDict)
        QMessageBox.warning(self, self.tr('Operation Complete!'), msg)
    
    def logInternalError(self, exceptionDict):
        """
        exceptionDict = {configName: {dbName: errorText}}
        """
        msg = ''
        configList = exceptionDict.keys()
        if len(configList) > 0:
            msg += self.tr('\nConfig with error:') + ','.join(configList)
            msg+= self.tr('\nError messages for each config and database were output in qgis log.')
            for config in configList:
                for dbName in exceptionDict[config].keys():
                    if exceptionDict[config][dbName] != dict():
                        QgsMessageLog.logMessage(self.tr('Error for config ')+ config + ' in database ' +dbName+' : '+exceptionDict[config][dbName], "DSG Tools Plugin", QgsMessageLog.CRITICAL)
        return msg 

    def manageSetting(self, config, manageType, dbList = [], parameterDict = dict()):
        if manageType == GenericManagerWidget.Install:
            return self.genericDbManager.installSetting(config, dbNameList = dbList)
        elif manageType == GenericManagerWidget.Delete:
            return self.genericDbManager.deleteSetting(config)
        elif manageType == GenericManagerWidget.Uninstall:
            return self.genericDbManager.uninstallSetting(config, dbNameList = dbList)
        elif manageType == GenericManagerWidget.Update:
            return self.genericDbManager.updateSetting(config, parameterDict['newJsonDict'])
        elif manageType == GenericManagerWidget.Create:
            return self.genericDbManager.createSetting(config, parameterDict['newJsonDict'])
    
    def selectConfig(self):
        availableConfig = self.genericDbManager.getPropertyPerspectiveDict().keys()
        dlg = ListSelector(availableConfig,[])
        dlg.exec_()
        selectedConfig = dlg.getSelected()
        return selectedConfig

    def manageSettings(self, manageType, dbList = [], selectedConfig = [], parameterDict = dict()):
        """
        Executes the setting work according to manageType
        successDict = {configName: [--list of successful databases--]}
        exceptionDict = {configName: {dbName: errorText}}
        """
        if selectedConfig == []:
            selectedConfig = self.selectConfig()
            if selectedConfig == []:
                QMessageBox.warning(self, self.tr('Warning!'), self.tr('Select at least one configuration!'))
                return (dict(),dict())
        successDict = dict()
        exceptionDict = dict()
        if self.lookAndPromptForStructuralChanges(dbList = dbList):
            for config in selectedConfig:
                QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
                sucessList, errorDict = self.manageSetting(config, manageType, dbList = dbList, parameterDict = parameterDict)
                QApplication.restoreOverrideCursor()
                successDict[config] = sucessList
                if errorDict != dict():
                    exceptionDict[config] = errorDict
            self.refresh()
            return successDict, exceptionDict
        else:
            QMessageBox.warning(self, self.tr('Warning!'), self.tr('Operation canceled by user!'))
            return (dict(),dict())
    
    def createMenuAssigned(self, position):
        """
        Creates a pop up menu
        """
        viewType = self.getViewType()
        if viewType == DsgEnums.Database:
            self.createDbPerspectiveContextMenu(position)
        if viewType == DsgEnums.Property:
            self.createPropertyPerspectiveContextMenu(position)

    def createDbPerspectiveContextMenu(self, position):
        menu = QMenu()
        item = self.treeWidget.itemAt(position)
        if item:
            if item.text(0) != '':
                menu.addAction(self.tr('Uninstall all settings from selected database'), self.uninstallSettings)
                menu.addAction(self.tr('Manage settings from selected database'), self.manageDbSettings)
            elif item.text(1) != '':
                menu.addAction(self.tr('Update selected setting'), self.updateSelectedSetting)
                menu.addAction(self.tr('Clone selected setting'), self.cloneSelectedSetting)
                menu.addAction(self.tr('Uninstall selected setting'), self.uninstallSettings)
                menu.addAction(self.tr('Delete selected setting'), self.deleteSelectedSetting)
        menu.exec_(self.treeWidget.viewport().mapToGlobal(position))
    
    def createPropertyPerspectiveContextMenu(self, position):
        menu = QMenu()
        item = self.treeWidget.itemAt(position)
        if item:
            if item.text(0) != '':
                menu.addAction(self.tr('Update selected setting'), self.updateSelectedSetting)
                menu.addAction(self.tr('Clone selected setting'), self.cloneSelectedSetting)
                menu.addAction(self.tr('Manage selected setting'), self.manageSelectedSetting)
                menu.addAction(self.tr('Uninstall selected setting on all databases'), self.uninstallSettings)
                menu.addAction(self.tr('Delete selected setting'), self.deleteSelectedSetting)                
            elif item.text(1) != '':
                menu.addAction(self.tr('Manage Settings on database'), self.manageDbSettings)
                menu.addAction(self.tr('Uninstall selected setting on selected database'), self.uninstallSettings)
        menu.exec_(self.treeWidget.viewport().mapToGlobal(position))
    
    def manageDbSettings(self):
        """
        1. get installed profiles and available profiles
        2. populate selection with items from #1
        3. get final lists and uninstall items and them install items
        """
        uiParameterDict = self.getParametersFromInterface()
        propertyPerspectiveDict = self.genericDbManager.getPropertyPerspectiveDict()
        availableConfig = [i for i in propertyPerspectiveDict.keys() if i not in uiParameterDict['parameterList']]
        dlg = ListSelector(availableConfig,uiParameterDict['parameterList'])
        dlg.exec_()
        fromLs, toLs = dlg.getInputAndOutputLists()
        #build install list: elements from toLs that were not in uiParameterDict['parameterList']
        installList = [i for i in toLs if i not in uiParameterDict['parameterList']]
        #build uninstall list: : elements from fromLs that were not in availableConfig
        uninstallList = [i for i in fromLs if i in uiParameterDict['parameterList']]
        if (installList == [] and uninstallList == []):
            QMessageBox.warning(self, self.tr('Error!'), self.tr('Select at least one configuration to manage!'))
            return
        if installList <> []:
            #install:
            successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Install, selectedConfig = installList, dbList = uiParameterDict['databaseList'])
            header, operation = self.getApplyHeader()
            self.outputMessage(operation, header, successDict, exceptionDict)
        if uninstallList <> []:
            #uninstall:
            successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Uninstall, selectedConfig = uninstallList, dbList = uiParameterDict['databaseList'])
            header, operation = self.getUninstallSelectedSettingHeader()
            self.outputMessage(operation, header, successDict, exceptionDict)

    def manageSelectedSetting(self):
        """
        1. get installed profiles and available profiles
        2. populate selection with items from #1
        3. get final lists and uninstall items and them install items
        """
        uiParameterDict = self.getParametersFromInterface()
        propertyPerspectiveDict = self.genericDbManager.getPropertyPerspectiveDict(viewType = DsgEnums.Database)
        availableDb = [i for i in propertyPerspectiveDict.keys() if i not in uiParameterDict['databaseList']]
        dlg = ListSelector(availableDb,uiParameterDict['databaseList'])
        dlg.exec_()
        fromLs, toLs = dlg.getInputAndOutputLists()
        #build install list: elements from toLs that were not in uiParameterDict['parameterList']
        installList = [i for i in toLs if i not in uiParameterDict['databaseList']]
        #build uninstall list: : elements from fromLs that were not in availableConfig
        uninstallList = [i for i in fromLs if i in uiParameterDict['databaseList']]
        if (installList == [] and uninstallList == []):
            QMessageBox.warning(self, self.tr('Error!'), self.tr('Select at least one configuration database to manage!'))
            return
        if installList <> []:
            #install:
            successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Install, selectedConfig = uiParameterDict['parameterList'], dbList = installList)
            header, operation = self.getApplyHeader()
            self.outputMessage(operation, header, successDict, exceptionDict)
        if uninstallList <> []:
            #uninstall:
            successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Uninstall, selectedConfig = uiParameterDict['parameterList'], dbList = uninstallList)
            header, operation = self.getUninstallSelectedSettingHeader()
            self.outputMessage(operation, header, successDict, exceptionDict)

    def updateSelectedSetting(self):
        """
        1. get setting dict
        2. populate setting interface
        3. from new dict, update setting
        """
        currItem = self.treeWidget.currentItem()
        if self.getViewType() == DsgEnums.Database:
            settingName = currItem.text(1)
        else:
            settingName = currItem.text(0)
        edgvVersion = self.genericDbManager.edgvVersion
        templateDb = self.genericDbManager.instantiateTemplateDb(edgvVersion)
        originalDict = self.genericDbManager.getSetting(settingName, edgvVersion)
        newDict = self.populateConfigInterface(templateDb, jsonDict = originalDict)
        if newDict:
            successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Update, selectedConfig = [settingName], parameterDict = {'newJsonDict':newDict})
            header, operation = self.getUpdateSelectedSettingHeader()
            self.outputMessage(operation, header, successDict, exceptionDict)
    
    def cloneSelectedSetting(self):
        currItem = self.treeWidget.currentItem()
        if self.getViewType() == DsgEnums.Database:
            settingName = currItem.text(1)
        else:
            settingName = currItem.text(0)
        edgvVersion = self.genericDbManager.edgvVersion
        templateDb = self.genericDbManager.instantiateTemplateDb(edgvVersion)
        originalDict = self.genericDbManager.getSetting(settingName, edgvVersion)
        newDict = self.populateConfigInterface(templateDb, jsonDict = originalDict)
        if newDict:
            successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Create, selectedConfig = [settingName], parameterDict = {'newJsonDict':newDict})
            header, operation = self.getUpdateSelectedSettingHeader()
            self.outputMessage(operation, header, successDict, exceptionDict)

    def getParametersFromInterface(self):
        """
        Gets selected database and selected property. 
        Returns {'databaseList':dbList, 'parameterList':parameterList}
        """
        currItem = self.treeWidget.currentItem()
        if self.getViewType() == DsgEnums.Database:
            #2 possibilities: leaf (if first column is '') or parent (if first column != '')
            if currItem.text(0) == '':
                #leaf -> must get 
                parentNode = currItem.parent()
                dbName = parentNode.text(0)
                parameter = currItem.text(1)
                return {'databaseList':[dbName], 'parameterList':[parameter]}
            else:
                #parent
                dbName = currItem.text(0)
                childCount = currItem.childCount()
                parameterList = []
                for i in range(childCount):
                    childNode = currItem.child(i)
                    parameterName = childNode.text(1)
                    if parameterName not in parameterList:
                        parameterList.append(parameterName)
                return {'databaseList':[dbName], 'parameterList':parameterList}
        else:
            if currItem.text(0) == '':
                #leaf
                parentNode = currItem.parent()
                parameter = parentNode.text(0)
                dbName = currItem.text(1)
                return {'databaseList':[dbName], 'parameterList':[parameter]}
            else:
                #parent
                parameter = currItem.text(0)
                childCount = currItem.childCount()
                dbList = []
                for i in range(childCount):
                    childNode = currItem.child(i)
                    dbName = childNode.text(1)
                    if dbName not in dbList:
                        dbList.append(dbName)
                return {'databaseList':dbList, 'parameterList':[parameter]}

    def uninstallSettings(self):
        edgvVersion = self.genericDbManager.edgvVersion
        uiParameterDict = self.getParametersFromInterface()
        successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Uninstall, dbList = uiParameterDict['databaseList'], selectedConfig = uiParameterDict['parameterList'])
        header, operation = self.getUninstallSelectedSettingHeader()
        self.outputMessage(operation, header, successDict, exceptionDict)
    
    def deleteSelectedSetting(self):
        edgvVersion = self.genericDbManager.edgvVersion
        uiParameterDict = self.getParametersFromInterface()
        settingTextList = ', '.join(uiParameterDict['parameterList'])
        if QtGui.QMessageBox.question(self, self.tr('Question'), self.tr('Do you really want to delete ')+settingTextList+'?', QtGui.QMessageBox.Ok|QtGui.QMessageBox.Cancel) == QtGui.QMessageBox.Cancel:
            return
        successDict, exceptionDict = self.manageSettings(GenericManagerWidget.Delete, selectedConfig = uiParameterDict['parameterList'])
        header, operation = self.getDeleteHeader()
        self.outputMessage(operation, header, successDict, exceptionDict)
    
    def lookAndPromptForStructuralChanges(self, dbList = []):
        '''
        Returns True if user accepts the process
        '''
        structuralChanges = self.genericDbManager.hasStructuralChanges(dbList)
        if structuralChanges != []:
            dbChangeList = ', '.join(structuralChanges)
            if QtGui.QMessageBox.question(self, self.tr('Question'), self.tr('Do you really want to apply selected operation on ')+dbChangeList+'?'+self.tr(' (Data may be lost in the process)'), QtGui.QMessageBox.Ok|QtGui.QMessageBox.Cancel) == QtGui.QMessageBox.Cancel:
                return False
            else:
                return True
        else:
            return True