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() self.algRunner = AlgRunner()
def runGrassDissolve(self, inputLyr, context, feedback=None, column=None, outputLyr=None, onFinish=None): """ Runs dissolve from GRASS algorithm provider. :param inputLyr: (QgsVectorLayer) layer to be dissolved. :param context: (QgsProcessingContext) processing context. :param feedback: (QgsProcessingFeedback) QGIS object to keep track of progress/cancelling option. :param column: () :param outputLyr: (str) URI to output layer. :param onFinish: (list-of-str) sequence of algs to be run after dissolve is executed, in execution order. :return: (QgsVectorLayer) dissolved (output) layer. """ return AlgRunner().runGrassDissolve(inputLyr, context, feedback=None, column=None, outputLyr=None, onFinish=None)
def prepareConversion(self, inputLyr, context, inputExpression=None, filterLyr=None,\ behavior=None, bufferRadius=None, conversionMap=None, feedback=None): bufferRadius = 0 if bufferRadius is None else bufferRadius algRunner = AlgRunner() if feedback is not None: count = 0 if inputExpression is not None: count += 1 if filterLyr is not None: count += 1 if behavior == 3: count += 1 elif count == 0: return inputLyr multiStepFeedback = QgsProcessingMultiStepFeedback(count, feedback) else: multiStepFeedback = None localLyr = inputLyr currentStep = 0 if inputExpression is not None and inputExpression != '': if multiStepFeedback is not None: multiStepFeedback.setCurrentStep(currentStep) localLyr = algRunner.runFilterExpression( inputLyr=localLyr, context=context, expression = inputExpression, feedback=multiStepFeedback ) currentStep+=1 if filterLyr is not None: if multiStepFeedback is not None: multiStepFeedback.setCurrentStep(currentStep) if behavior == 3: filterLyr = algRunner.runBuffer(filterLyr, bufferRadius, context, feedback=multiStepFeedback) currentStep += 1 localLyr = algRunner.runIntersection(localLyr, context, overlayLyr=filterLyr) return localLyr
def filterByExpression(self, layer, expression, context, feedback=None): """ Filters a given layer using a filtering expression. The original layer is not modified. :param layer: (QgsVectorLayer) layer to be filtered. :param expression: (str) expression to be used as filter. :param context: (QgsProcessingContext) processing context in which algorithm should be executed. :param feedback: (QgsFeedback) QGIS feedback component (progress bar). :return: (QgsVectorLayer) filtered layer. """ return AlgRunner().runFilterExpression( inputLyr=layer, context=context, expression = expression, feedback=feedback )
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ #get the network handler layerHandler = LayerHandler() networkHandler = NetworkHandler() algRunner = AlgRunner() self.nodeTypeNameDict = networkHandler.nodeTypeDict # get network layer networkLayer = self.parameterAsLayer(parameters, self.NETWORK_LAYER, context) if networkLayer is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.NETWORK_LAYER)) attributeBlackList = self.parameterAsFields(parameters, self.ATTRIBUTE_BLACK_LIST, context) ignoreVirtual = self.parameterAsBool(parameters, self.IGNORE_VIRTUAL_FIELDS, context) ignorePK = self.parameterAsBool(parameters, self.IGNORE_PK_FIELDS, context) # get network node layer (nodeSink, dest_id) = self.parameterAsSink(parameters, self.NETWORK_NODES, context, self.getFields(), QgsWkbTypes.MultiPoint, networkLayer.sourceCrs()) #prepairs flag sink for raising errors self.prepareFlagSink(parameters, networkLayer, QgsWkbTypes.MultiPoint, context) waterBodyClasses = self.parameterAsLayer(parameters, self.WATER_BODY_LAYERS, context) waterBodyClasses = waterBodyClasses if waterBodyClasses is not None else [] # get water sink layer waterSinkLayer = self.parameterAsLayer(parameters, self.SINK_LAYER, context) # get spillway layer spillwayLayer = self.parameterAsLayer(parameters, self.SPILLWAY_LAYER, context) # get frame layer frameLayer = self.parameterAsLayer(parameters, self.REF_LAYER, context) currStep = 0 if frameLayer is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.REF_LAYER)) multiStepFeedback = QgsProcessingMultiStepFeedback(3, feedback) multiStepFeedback.setCurrentStep(currStep) multiStepFeedback.pushInfo(self.tr('Preparing bounds...')) frame = layerHandler.getFrameOutterBounds(frameLayer, algRunner, context, feedback=multiStepFeedback) currStep += 1 # get search radius searchRadius = self.parameterAsDouble(parameters, self.SEARCH_RADIUS, context) # get ditch layer ditchLayer = self.parameterAsLayer(parameters, self.DITCH_LAYER, context) #new step multiStepFeedback.setCurrentStep(currStep) multiStepFeedback.pushInfo(self.tr('Performing node identification...')) self.nodeDict = networkHandler.identifyAllNodes(networkLayer=networkLayer, feedback=multiStepFeedback) #zoado, mudar lógica multiStepFeedback.pushInfo(self.tr('{node_count} node(s) identificated...').format(node_count=len(self.nodeDict))) currStep += 1 #new step multiStepFeedback.setCurrentStep(currStep) multiStepFeedback.pushInfo(self.tr('Performing node classification...')) networkHandler.nodeDict = self.nodeDict self.nodeTypeDict, nodeFlagDict = networkHandler.classifyAllNodes( networkLayer=networkLayer, frameLyrContourList=frame, waterBodiesLayers=waterBodyClasses, searchRadius=searchRadius, waterSinkLayer=waterSinkLayer, spillwayLayer=spillwayLayer, feedback=multiStepFeedback, attributeBlackList=attributeBlackList, excludePrimaryKeys=ignorePK, ignoreVirtualFields=ignoreVirtual, ditchLayer=ditchLayer ) currStep += 1 #new step multiStepFeedback.setCurrentStep(currStep) multiStepFeedback.pushInfo(self.tr('Writing nodes...')) self.fillNodeSink( nodeSink=nodeSink, networkLineLayerName=networkLayer.name(), nodeFlagDict=nodeFlagDict, feedback=multiStepFeedback) return {self.NETWORK_NODES : dest_id, self.FLAGS : self.flag_id}
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ spatialRealtionsHandler = SpatialRealtionsHandler() algRunner = AlgRunner() inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context) if inputLyr is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) onlySelected = self.parameterAsBool(parameters, self.SELECTED, context) contourFieldName = self.parameterAsField(parameters, self.CONTOUR_ATTR, context) threshold = self.parameterAsDouble(parameters, self.TOLERANCE, context) topology_radius = self.parameterAsDouble(parameters, self.TOPOLOGY_RADIUS, context) refLyr = self.parameterAsVectorLayer(parameters, self.REFERENCE_LYR, context) self.prepareFlagSink(parameters, inputLyr, QgsWkbTypes.Polygon, context) #1. Get all lines into one line lyr currentStep = 0 if refLyr is not None: multiStepFeedback = QgsProcessingMultiStepFeedback(4, feedback) multiStepFeedback.setCurrentStep(currentStep) multiStepFeedback.pushInfo(self.tr('Identifying dangles...')) dangles = algRunner.runIdentifyDangles( inputLayer=inputLayer, searchRadius=topology_radius, context=context, onlySelected=onlySelected, polygonFilter=refLyr, feedback=multiStepFeedback ) currentStep += 1 #2. Snap frame to dangles multiStepFeedback.setCurrentStep(currentStep) multiStepFeedback.pushInfo(self.tr('Adjusting frame lyr...')) snappedFrame = algRunner.runSnapGeometriesToLayer( inputLayer=inputLyr, referenceLayer=dangles, tol=topology_radius, context=context feedback=multiStepFeedback ) currentStep += 1 else: multiStepFeedback = QgsProcessingMultiStepFeedback(2, feedback) #3. Validate contour lines multiStepFeedback.setCurrentStep(currentStep) multiStepFeedback.pushInfo(self.tr('Validating contour lines...')) invalidDict = spatialRealtionsHandler.validateContourLines( contourLyr=inputLyr, contourAttrName=contourFieldName, refLyr=refLyr, feedback=multiStepFeedback ) currentStep+=1 multiStepFeedback.setCurrentStep(currentStep) multiStepFeedback.pushInfo(self.tr('Raising flags...')) nFlags = len(invalidDict) step = 100/nFlags if nFlags else 0 for current, (geom, text) in enumerate(invalidDict.items()): self.flagFeature(geom, text, fromWkb=True) multiStepFeedback.setProgress(step * current) return {self.FLAGS: self.flag_id}
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() self.algRunner = AlgRunner() @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] if 'db:' in selectedStyle: self.algRunner.runApplStylesFromDatabaseToLayers( inputList=lyrList, context=QgsProcessingContext(), styleName=selectedStyle.split(':')[-1]) else: stylePath = os.path.join( abstractDb.getStyleDirectory(dbVersion), selectedStyle) self.algRunner.runMatchAndApplyQmlStylesToLayer( inputList=lyrList, qmlFolder=stylePath, context=QgsProcessingContext()) # 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.loadNamedStyle(fullPath, True) # # remove qml temporary file # self.utils.deleteQml(fullPath) # # clear fullPath variable # del 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), "DSGTools Plugin", Qgis.Critical) QApplication.restoreOverrideCursor() def getLayers(self, dbName): lyrList = [] for lyr in self.iface.mapCanvas().layers(): if isinstance(lyr, QgsVectorLayer): candidateUri = QgsDataSourceUri( lyr.dataProvider().dataSourceUri()) if (candidateUri.database() == dbName and lyr.providerType() in ['postgres', 'spatialite']) \ or (os.path.splitext(os.path.basename(candidateUri.uri().split('|')[0]))[0] == dbName and lyr.providerType() == 'ogr'): lyrList.append(lyr) return lyrList def getDatabaseList(self): # dbList = list() dbSet = set() for lyr in self.iface.mapCanvas().layers(): if isinstance(lyr, QgsVectorLayer): candidateUri = QgsDataSourceUri( lyr.dataProvider().dataSourceUri()) dbName = candidateUri.database() # if dbName not in dbList and lyr.providerType() in ['postgres', 'spatialite']: if lyr.providerType() in ['postgres', 'spatialite']: dbSet.add(dbName) elif lyr.providerType() == 'ogr': dbName = os.path.splitext( os.path.basename( lyr.dataProvider().dataSourceUri().split( '|')[0]))[0] # if db not in dbList: dbSet.add(dbName) return dbSet def loadStylesCombo(self, abstractDb): dbVersion = abstractDb.getDatabaseVersion() styleDict = abstractDb.getStyleDict(dbVersion) self.styleComboBox.clear() styleList = list(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.mapCanvas().layers(): if isinstance(lyr, QgsVectorLayer): candidateUri = QgsDataSourceUri( lyr.dataProvider().dataSourceUri()) if candidateUri.database() == dbName or \ os.path.splitext(os.path.basename(candidateUri.uri().split('|')[0]))[0] == 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, DsgEnums.DriverPostGIS elif currLyr.providerType() == 'spatialite': dbParameters['dbPath'] = candidateUri.database() return dbParameters, DsgEnums.DriverSpatiaLite elif currLyr.providerType() == 'ogr': # geopackage provider type is ogr dbParameters['dbPath'] = candidateUri.database() return dbParameters, DsgEnums.DriverGeopackage 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 list(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): self.enableApply() if self.sender().objectName() == 'dbComboBox': 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)