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