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 __init__(self): super(AbstractDb,self).__init__() self.conversionTypeDict = dict({'QPSQL':'postgis','QSQLITE':'spatialite'}) self.utils = Utils() self.signals = DbSignals() self.slotConnected = False pass
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)
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 __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 __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()
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 __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()
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()
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 __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 __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 __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)
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()
def __init__(self, parent = None): """Constructor.""" super(self.__class__, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.utils = Utils() self.factory = SqlGeneratorFactory() #setting the sql generator self.gen = self.factory.createSqlGenerator(False) self.serverWidget.populateServersCombo() self.serverWidget.abstractDbLoaded.connect(self.populateListWithDatabasesFromServer)
def __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 __init__(self, parent = None): """Constructor.""" super(self.__class__, self).__init__(parent) self.setupUi(self) self.utils = Utils() self.dbFactory = DbFactory() self.factory = SqlGeneratorFactory() self.showTabs(show = False) #setting the sql generator self.serverWidget.populateServersCombo() self.serverWidget.abstractDbLoaded.connect(self.checkSuperUser) self.serverWidget.abstractDbLoaded.connect(self.populateOtherInterfaces) self.dbsCustomSelector.setTitle(self.tr('Server Databases')) self.dbsCustomSelector.selectionChanged.connect(self.showTabs) self.dbsCustomSelector.selectionChanged.connect(self.populateStylesInterface) self.dbsCustomSelector.selectionChanged.connect(self.populateOtherInterfaces) self.previousTab = 0 self.dbDict = {'2.1.3':[], 'FTer_2a_Ed':[],'Non_EDGV':[], '3.0':[]} self.correspondenceDict = {self.tr('Load Database Model EDGV Version 2.1.3'):'2.1.3', self.tr('Load Database Model EDGV Version 3.0'):'3.0', self.tr('Load Database Model EDGV Version FTer_2a_Ed'):'FTer_2a_Ed',self.tr('Load Other Database Models'):'Non_EDGV'}
def __init__(self, parent=None): """Constructor.""" super(self.__class__, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.utils = Utils() self.dbFactory = DbFactory() self.localDb = None self.serverWidget.populateServersCombo() #signal connections self.serverWidget.abstractDbLoaded.connect(self.checkSuperUser) self.serverWidget.clearWidgets.connect(self.clearAll) self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.treeWidget.customContextMenuRequested.connect( self.createMenuAssigned)
def __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 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)
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
def clearAll(self): """ Resets the initial state """ self.filename = '' self.dbLoaded = False self.epsg = 0 self.crs = None self.abstractDb = None self.isSpatialite = False self.abstractDbFactory = DbFactory() self.utils = Utils() #populating the postgis combobox self.comboBoxPostgis.clear() self.spatialiteFileEdit.setReadOnly(True) self.postGISCrsEdit.setReadOnly(True) self.spatialiteCrsEdit.setReadOnly(True) self.edgvSpatialiteVersionEdit.setReadOnly(True) self.edgvPostgisVersionEdit.setReadOnly(True)
def __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 __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)
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
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)
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
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)
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))
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
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)
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
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
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')
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 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
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 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 []
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)
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()" ))
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)
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
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