def processAlgorithm(self, progress): ns = {} ns["progress"] = progress ns["scriptDescriptionFile"] = self.descriptionFile for param in self.parameters: ns[param.name] = param.value for out in self.outputs: ns[out.name] = out.value variables = re.findall("@[a-zA-Z0-9_]*", self.script) script = "import processing\n" script += self.script context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope()) for var in variables: varname = var[1:] if context.hasVariable(varname): script = script.replace(var, context.variable(varname)) else: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, "Cannot find variable: %s" % varname) exec((script), ns) for out in self.outputs: out.setValue(ns[out.name])
def inasafe_sub_analysis_summary_field_value( exposure_key, field, feature, parent): """Retrieve a value from field in the specified exposure analysis layer. """ _ = feature, parent # NOQA project_context_scope = QgsExpressionContextUtils.projectScope( QgsProject.instance()) project = QgsProject.instance() key = ('{provenance}__{exposure}').format( provenance=provenance_multi_exposure_analysis_summary_layers_id[ 'provenance_key'], exposure=exposure_key) if not project_context_scope.hasVariable(key): return None analysis_summary_layer = project.mapLayer( project_context_scope.variable(key)) if not analysis_summary_layer: return None index = analysis_summary_layer.fields().lookupField(field) if index < 0: return None feature = next(analysis_summary_layer.getFeatures()) return feature[index]
def processAlgorithm(self, progress): layer = layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) expression = self.getParameterValue(self.EXPRESSION) qExp = QgsExpression(expression) if qExp.hasParserError(): raise GeoAlgorithmExecutionException(qExp.parserErrorString()) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.fields(), layer.wkbType(), layer.crs()) context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope()) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) count = layer.featureCount() step = 100.0 / count if count else 1 request = QgsFeatureRequest(qExp, context) for current, f in enumerate(layer.getFeatures(request)): writer.addFeature(f) progress.setPercentage(int(current * step)) del writer
def processAlgorithm(self, feedback): ns = {} ns['feedback'] = feedback ns['scriptDescriptionFile'] = self.descriptionFile for param in self.parameters: ns[param.name] = param.value for out in self.outputs: ns[out.name] = out.value variables = re.findall('@[a-zA-Z0-9_]*', self.script) script = 'import processing\n' script += self.script context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance())) for var in variables: varname = var[1:] if context.hasVariable(varname): script = script.replace(var, context.variable(varname)) else: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'Cannot find variable: %s' % varname) exec((script), ns) for out in self.outputs: out.setValue(ns[out.name])
def processAlgorithm(self, parameters, context, feedback): ns = {} ns['feedback'] = feedback ns['scriptDescriptionFile'] = self.descriptionFile ns['context'] = context for param in self.parameterDefinitions(): ns[param.name] = parameters[param.name()] for out in self.outputs: ns[out.name] = out.value variables = re.findall('@[a-zA-Z0-9_]*', self.script) script = 'import processing\n' script += self.script context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance())) for var in variables: varname = var[1:] if context.hasVariable(varname): script = script.replace(var, context.variable(varname)) else: QgsMessageLog.logMessage(self.tr('Cannot find variable: {0}').format(varname), self.tr('Processing'), QgsMessageLog.WARNING) exec((script), ns) for out in self.outputs: out.setValue(ns[out.name])
def processAlgorithm(self, progress): ns = {} ns['progress'] = progress ns['scriptDescriptionFile'] = self.descriptionFile for param in self.parameters: ns[param.name] = param.value for out in self.outputs: ns[out.name] = out.value variables = re.findall("@[a-zA-Z0-9_]*", self.script) print variables script = 'import processing\n' script += self.script scope = QgsExpressionContextUtils.projectScope() for var in variables: varname = var[1:] if not scope.hasVariable(varname): raise GeoAlgorithmExecutionException("Wrong variable: %s" % varname) script = script.replace(var, scope.variable(varname)) exec((script), ns) for out in self.outputs: out.setValue(ns[out.name])
def inasafe_analysis_summary_field_value(field, feature, parent): """Retrieve a value from a field in the analysis summary layer. e.g. inasafe_analysis_summary_field_value('total_not_exposed') -> 3 """ _ = feature, parent # NOQA project_context_scope = QgsExpressionContextUtils.projectScope( QgsProject.instance()) registry = QgsProject.instance() key = provenance_layer_analysis_impacted_id['provenance_key'] if not project_context_scope.hasVariable(key): return None layer = registry.mapLayer(project_context_scope.variable(key)) if not layer: return None index = layer.fields().lookupField(field) if index < 0: return None feature = next(layer.getFeatures()) return feature[index]
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) geometry_type = self.getParameterValue(self.OUTPUT_GEOMETRY) wkb_type = None if geometry_type == 0: wkb_type = QgsWkbTypes.Polygon elif geometry_type == 1: wkb_type = QgsWkbTypes.LineString else: wkb_type = QgsWkbTypes.Point if self.getParameterValue(self.WITH_Z): wkb_type = QgsWkbTypes.addZ(wkb_type) if self.getParameterValue(self.WITH_M): wkb_type = QgsWkbTypes.addM(wkb_type) writer = self.getOutputFromName( self.OUTPUT_LAYER).getVectorWriter( layer.fields(), wkb_type, layer.crs()) expression = QgsExpression(self.getParameterValue(self.EXPRESSION)) if expression.hasParserError(): raise GeoAlgorithmExecutionException(expression.parserErrorString()) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) if not expression.prepare(exp_context): raise GeoAlgorithmExecutionException( self.tr('Evaluation error: %s' % expression.evalErrorString())) features = vector.features(layer) total = 100.0 / len(features) for current, input_feature in enumerate(features): output_feature = input_feature exp_context.setFeature(input_feature) value = expression.evaluate(exp_context) if expression.hasEvalError(): raise GeoAlgorithmExecutionException( self.tr('Evaluation error: %s' % expression.evalErrorString())) if not value: output_feature.setGeometry(QgsGeometry()) else: if not isinstance(value, QgsGeometry): raise GeoAlgorithmExecutionException( self.tr('{} is not a geometry').format(value)) output_feature.setGeometry(value) writer.addFeature(output_feature) progress.setPercentage(int(current * total)) del writer
def initContext(self): exp_context = self.builder.expressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(self.layer)) exp_context.lastScope().setVariable("row_number", 1) exp_context.setHighlightedVariables(["row_number"]) self.builder.setExpressionContext(exp_context)
def expressionContext(self): context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope()) processingScope = QgsExpressionContextScope() for param in self.alg.parameters: processingScope.setVariable("%s_value" % param.name, "") context.appendScope(processingScope) return context
def _expressionContext(alg): context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope()) processingScope = QgsExpressionContextScope() for param in alg.parameters: processingScope.setVariable('%s_value' % param.name, '') context.appendScope(processingScope) return context
def evaluateExpression(self, text): context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope()) exp = QgsExpression(text) if exp.hasParserError(): raise Exception(exp.parserErrorString()) result = exp.evaluate(context) if exp.hasEvalError(): raise ValueError(exp.evalErrorString()) return result
def analysis_summary_report(feature, parent): """Retrieve an HTML table report of current selected analysis. """ _ = feature, parent # NOQA project_context_scope = QgsExpressionContextUtils.projectScope( QgsProject.instance()) key = provenance_layer_analysis_impacted['provenance_key'] if not project_context_scope.hasVariable(key): return None analysis_dir = dirname(project_context_scope.variable(key)) return get_impact_report_as_string(analysis_dir)
def exposure_summary_layer(): """Helper method for retrieving exposure summary layer. If the analysis is multi-exposure, then it will return the exposure summary layer from place exposure analysis. """ project_context_scope = QgsExpressionContextUtils.projectScope( QgsProject.instance()) project = QgsProject.instance() key = provenance_layer_analysis_impacted_id['provenance_key'] analysis_summary_layer = project.mapLayer( project_context_scope.variable(key)) if not analysis_summary_layer: key = provenance_layer_analysis_impacted['provenance_key'] if project_context_scope.hasVariable(key): analysis_summary_layer = load_layer( project_context_scope.variable(key))[0] if not analysis_summary_layer: return None keywords = KeywordIO.read_keywords(analysis_summary_layer) extra_keywords = keywords.get(property_extra_keywords['key'], {}) is_multi_exposure = extra_keywords.get(extra_keyword_analysis_type['key']) key = provenance_layer_exposure_summary_id['provenance_key'] if is_multi_exposure: key = ('{provenance}__{exposure}').format( provenance=provenance_multi_exposure_summary_layers_id[ 'provenance_key'], exposure=exposure_place['key']) if not project_context_scope.hasVariable(key): return None exposure_summary_layer = project.mapLayer( project_context_scope.variable(key)) if not exposure_summary_layer: key = provenance_layer_exposure_summary['provenance_key'] if is_multi_exposure: key = ('{provenance}__{exposure}').format( provenance=provenance_multi_exposure_summary_layers[ 'provenance_key'], exposure=exposure_place['key']) if project_context_scope.hasVariable(key): exposure_summary_layer = load_layer( project_context_scope.variable(key))[0] else: return None return exposure_summary_layer
def calculate( self, layer, fieldName, expression ): if ( layer.featureCount() == 0 ): self.msg.show( "[Info] * No existing features on layer " + layer.name() + " to calculate expression.", 'info', True ) return expression = QgsExpression( expression ) if expression.hasParserError(): self.msg.show( QApplication.translate( "AutoFields-FieldCalculator", "[Error] (Parsing) " ) + \ expression.parserErrorString(), 'critical' ) return context = QgsExpressionContext() context.appendScope( QgsExpressionContextUtils.globalScope() ) context.appendScope( QgsExpressionContextUtils.projectScope() ) context.appendScope( QgsExpressionContextUtils.layerScope( layer ) ) context.setFields( layer.fields() ) if expression.needsGeometry(): if self.iface: # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py da = QgsDistanceArea() da.setSourceCrs( layer.crs().srsid() ) da.setEllipsoidalMode( self.iface.mapCanvas().mapSettings().hasCrsTransformEnabled() ) da.setEllipsoid( QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE )[0] ) expression.setGeomCalculator( da ) if QGis.QGIS_VERSION_INT >= 21400: # Methods added in QGIS 2.14 expression.setDistanceUnits( QgsProject.instance().distanceUnits() ) expression.setAreaUnits( QgsProject.instance().areaUnits() ) expression.prepare( context ) fieldIndex = layer.fieldNameIndex( fieldName ) if fieldIndex == -1: return field = layer.fields()[fieldIndex] dictResults = {} for feature in layer.getFeatures(): context.setFeature( feature ) result = expression.evaluate( context ) if expression.hasEvalError(): self.msg.show( QApplication.translate( "AutoFields-FieldCalculator", "[Error] (Evaluating) " ) + \ expression.evalErrorString(), 'critical' ) return dictResults[feature.id()] = { fieldIndex: field.convertCompatible( result ) } layer.dataProvider().changeAttributeValues( dictResults ) self.msg.show( "[Info] * An expression was calculated on existing features of layer " + layer.name() + ", field " + fieldName + ".", 'info', True )
def __init__(self, provider): super(PyFeatureSource, self).__init__() self._provider = provider self._features = provider._features self._expression_context = QgsExpressionContext() self._expression_context.appendScope(QgsExpressionContextUtils.globalScope()) self._expression_context.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance())) self._expression_context.setFields(self._provider.fields()) if self._provider.subsetString(): self._subset_expression = QgsExpression(self._provider.subsetString()) self._subset_expression.prepare(self._expression_context) else: self._subset_expression = None
def doAction(self, layer, uid, feature): if layer.actions().action(uid).name() == 'openFeatureForm': self.plugin.iface.openFeatureForm(layer, feature) else : ctxt = QgsExpressionContext() ctxt.appendScope(QgsExpressionContextUtils.globalScope()) ctxt.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance())) ctxt.appendScope(QgsExpressionContextUtils.mapSettingsScope(self.canvas.mapSettings())) # Add click_x and click_y to context p = self.toLayerCoordinates(layer, self.pos()) QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(), 'click_x', p.x()) QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(), 'click_y', p.y()) layer.actions().doAction(uid, feature, ctxt)
def updateLayer(self): self.layer = dataobjects.getObject(self.cmbInputLayer.currentText()) self.builder.setLayer(self.layer) self.builder.loadFieldNames() exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(self.layer)) exp_context.lastScope().setVariable("row_number", 1) exp_context.setHighlightedVariables(["row_number"]) self.builder.setExpressionContext(exp_context) self.populateFields()
def aggregation_result_report(feature, parent): """Retrieve the aggregation result section from InaSAFE report. """ _ = feature, parent # NOQA project_context_scope = QgsExpressionContextUtils.projectScope() key = provenance_layer_analysis_impacted['provenance_key'] if not project_context_scope.hasVariable(key): return None analysis_dir = dirname(project_context_scope.variable(key)) complete_html_report = get_impact_report_as_string(analysis_dir) requested_html_report = get_report_section( complete_html_report, component_id=aggregation_result_component['key']) return requested_html_report
def createExpressionContext(): context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance())) if iface.mapCanvas(): context.appendScope(QgsExpressionContextUtils.mapSettingsScope(iface.mapCanvas().mapSettings())) processingScope = QgsExpressionContextScope() extent = iface.mapCanvas().fullExtent() processingScope.setVariable('fullextent_minx', extent.xMinimum()) processingScope.setVariable('fullextent_miny', extent.yMinimum()) processingScope.setVariable('fullextent_maxx', extent.xMaximum()) processingScope.setVariable('fullextent_maxy', extent.yMaximum()) context.appendScope(processingScope) return context
def test_length_expression(self): # compare length using the ellipsoid in kms and the planimetric distance in meters self.lyr.fieldName = "round($length,5) || ' - ' || round(length($geometry),2)" self.lyr.isExpression = True QgsProject.instance().setCrs(QgsCoordinateReferenceSystem("EPSG:32613")) QgsProject.instance().setEllipsoid("WGS84") QgsProject.instance().setDistanceUnits(QgsUnitTypes.DistanceKilometers) ctxt = QgsExpressionContext() ctxt.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance())) ctxt.appendScope(QgsExpressionContextUtils.layerScope(self.layer)) self._TestMapSettings.setExpressionContext(ctxt) self.lyr.placement = QgsPalLayerSettings.Curved self.lyr.placementFlags = QgsPalLayerSettings.AboveLine | QgsPalLayerSettings.MapOrientation self.checkTest()
def default_inasafe_html_resources(feature, parent): """Retrieve default InaSAFE HTML resources (style and script). """ _ = feature, parent # NOQA project_context_scope = QgsExpressionContextUtils.projectScope() key = provenance_layer_analysis_impacted['provenance_key'] if not project_context_scope.hasVariable(key): return None analysis_dir = dirname(project_context_scope.variable(key)) complete_html_report = get_impact_report_as_string(analysis_dir) requested_html_report = get_report_section( complete_html_report, component_id='inasafe-html-resources', container_wrapper_format=u'{section_content}') return requested_html_report
def _layer_tooltip(self, layer, feat): try: df = layer.displayField() if df: return str(feat.attribute(df)) else: context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(QgsProject.instance())) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) context.appendScope(QgsExpressionContextUtils.mapSettingsScope( self.canvas.mapSettings() ) ) context.setFeature( feat ) x = QgsExpression(layer.displayExpression()) x.prepare(context) return x.evaluate(context).replace('\n', "<br/>") except: return ""
def pointPicked(self, event): for b in self.rubberBands: del b self.rubberBands[:] = [] fieldX = self.cmbXField.currentField() fieldY = self.cmbYField.currentField() artist = event.artist indices = event.ind for i in indices: x = self.xData[artist.name][i] y = self.yData[artist.name][i] if isinstance(x, int): expr = '"{}" = {} AND '.format(fieldX, x) elif isinstance(x, float): expr = 'abs("{}" - {}) <= 0.0000001 AND '.format(fieldX, x) elif isinstance(x, (str, unicode)): expr = """"{}" = '{}' AND """.format(fieldX, x) else: expr = """"{}" = '{}' AND """.format(fieldX, x.toString('yyyy-MM-dd')) if isinstance(y, float): expr += 'abs("{}" - {}) <= 0.0000001'.format(fieldY, y) elif isinstance(y, (str, unicode)): expr += """"{}" = '{}'""".format(fieldY, y) else: expr += '"{}" = {}'.format(fieldY, y) layer = self.cmbLayer.currentLayer() expression = QgsExpression(expr) context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope()) context.appendScope(QgsExpressionContextUtils.mapSettingsScope(self.canvas.mapSettings())) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) request = QgsFeatureRequest(expression, context) for f in layer.getFeatures(request): hl = QgsHighlight(self.canvas, f.geometry(), layer) hl.setColor(QColor(255, 0, 0)) hl.setWidth(2) self.rubberBands.append(hl)
def expressionContext(self): context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope()) processingScope = QgsExpressionContextScope() layers = dataobjects.getAllLayers() for layer in layers: name = layer.name() processingScope.setVariable('%s_minx' % name, layer.extent().xMinimum()) processingScope.setVariable('%s_miny' % name, layer.extent().yMinimum()) processingScope.setVariable('%s_maxx' % name, layer.extent().xMaximum()) processingScope.setVariable('%s_maxy' % name, layer.extent().yMaximum()) if isinstance(layer, QgsRasterLayer): cellsize = (layer.extent().xMaximum() - layer.extent().xMinimum()) / layer.width() processingScope.setVariable('%s_cellsize' % name, cellsize) layers = dataobjects.getRasterLayers() for layer in layers: for i in range(layer.bandCount()): stats = layer.dataProvider().bandStatistics(i + 1) processingScope.setVariable('%s_band%i_avg' % (name, i + 1), stats.mean) processingScope.setVariable('%s_band%i_stddev' % (name, i + 1), stats.stdDev) processingScope.setVariable('%s_band%i_min' % (name, i + 1), stats.minimumValue) processingScope.setVariable('%s_band%i_max' % (name, i + 1), stats.maximumValue) extent = iface.mapCanvas().extent() processingScope.setVariable('canvasextent_minx', extent.xMinimum()) processingScope.setVariable('canvasextent_miny', extent.yMinimum()) processingScope.setVariable('canvasextent_maxx', extent.xMaximum()) processingScope.setVariable('canvasextent_maxy', extent.yMaximum()) extent = iface.mapCanvas().fullExtent() processingScope.setVariable('fullextent_minx', extent.xMinimum()) processingScope.setVariable('fullextent_miny', extent.yMinimum()) processingScope.setVariable('fullextent_maxx', extent.xMaximum()) processingScope.setVariable('fullextent_maxy', extent.yMaximum()) context.appendScope(processingScope) return context
def createExpressionContext(): context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope( QgsExpressionContextUtils.projectScope(QgsProject.instance())) if iface and iface.mapCanvas(): context.appendScope( QgsExpressionContextUtils.mapSettingsScope( iface.mapCanvas().mapSettings())) processingScope = QgsExpressionContextScope() if iface and iface.mapCanvas(): extent = iface.mapCanvas().fullExtent() processingScope.setVariable('fullextent_minx', extent.xMinimum()) processingScope.setVariable('fullextent_miny', extent.yMinimum()) processingScope.setVariable('fullextent_maxx', extent.xMaximum()) processingScope.setVariable('fullextent_maxy', extent.yMaximum()) context.appendScope(processingScope) return context
def processAlgorithm(self, parameters, context, feedback): # Database connection parameters connection_name = QgsExpressionContextUtils.projectScope( context.project()).variable('gobs_connection_name') msg = '' status = 1 # Set SQL self.setSql(parameters, context, feedback) # Set output layer name self.setLayerName(parameters, context, feedback) # Buid QGIS uri to load layer id_field = 'id' uri = getPostgisConnectionUriFromName(connection_name) uri.setDataSource("", "(" + self.SQL + ")", self.GEOM_FIELD, "", id_field) vlayer = QgsVectorLayer(uri.uri(), "layername", "postgres") if not vlayer.isValid(): feedback.reportError('SQL = \n' + self.SQL) raise QgsProcessingException( tr("""This layer is invalid! Please check the PostGIS log for error messages.""")) # Load layer context.temporaryLayerStore().addMapLayer(vlayer) context.addLayerToLoadOnCompletion( vlayer.id(), QgsProcessingContext.LayerDetails(self.LAYER_NAME, context.project(), self.OUTPUT_LAYER)) return { self.OUTPUT_STATUS: status, self.OUTPUT_STRING: msg, self.OUTPUT_LAYER: vlayer.id(), self.OUTPUT_LAYER_RESULT_NAME: self.LAYER_NAME }
def get_project_setting(key: str, default: Optional[any] = None, typehint: type = None, internal: bool = True) -> Union[QVariant, str, None]: """ Get QGIS project setting value :param key: Key for the setting :param default: Optional default value :param typehint: Type hint :param internal: Whether to search from only plugin settings or all :return: Value if conversion is successful, else None """ proj = QgsProject.instance() if not internal: value = QgsExpressionContextUtils.projectScope(proj).variable(key) return value if value is not None else default args = [plugin_name(), key] if default is not None: args.append(default) value = None conversion_ok = False if typehint is not None and typehint is not str: try: if typehint is int: value, conversion_ok = proj.readNumEntry(*args) elif typehint is bool: value, conversion_ok = proj.readBoolEntry(*args) elif typehint is list: value, conversion_ok = proj.readListEntry(*args) except TypeError as e: raise QgsPluginInvalidProjectSetting(str(e)) else: value, conversion_ok = proj.readEntry(*args) return value if conversion_ok else default
def initAlgorithm(self, config): # INPUTS project = QgsProject.instance() connection_name = QgsExpressionContextUtils.projectScope( project).variable('gobs_connection_name') db_param = QgsProcessingParameterString( self.CONNECTION_NAME, tr('PostgreSQL connection to G-Obs database'), defaultValue=connection_name, optional=False) db_param.setMetadata({ 'widget_wrapper': { 'class': 'processing.gui.wrappers_postgis.ConnectionWidgetWrapper' } }) self.addParameter(db_param) self.addParameter( QgsProcessingParameterBoolean( self.OVERRIDE, tr('Overwrite schema gobs and all data ? ** CAUTION ** It will remove all existing data !' ), defaultValue=False, )) self.addParameter( QgsProcessingParameterBoolean( self.ADD_TEST_DATA, tr('Add test data ?'), defaultValue=False, )) # OUTPUTS # Add output for status (integer) and message (string) self.addOutput( QgsProcessingOutputNumber(self.OUTPUT_STATUS, tr('Output status'))) self.addOutput( QgsProcessingOutputString(self.OUTPUT_STRING, tr('Output message')))
def _layer_tooltip(self, layer, feat): try: df = layer.displayField() if df: return str(feat.attribute(df)) else: context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope( QgsExpressionContextUtils.projectScope( QgsProject.instance())) context.appendScope( QgsExpressionContextUtils.layerScope(layer)) context.appendScope( QgsExpressionContextUtils.mapSettingsScope( self.canvas.mapSettings())) context.setFeature(feat) x = QgsExpression(layer.displayExpression()) x.prepare(context) return x.evaluate(context).replace("\n", "<br/>") except: return ""
def setCustomExpression( self ): """ Initialize and show the expression builder dialog """ layer = None if len( self.tblLayers.selectedItems() ) / 3 == 1: # Single layer selected? for item in self.tblLayers.selectedItems(): if item.column() == 1: # It's the layer name item layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) ) if not self.expressionDlg: self.expressionDlg = ExpressionBuilderDialog( self.iface.mainWindow() ) context = QgsExpressionContext() context.appendScope( QgsExpressionContextUtils.globalScope() ) context.appendScope( QgsExpressionContextUtils.projectScope() ) # Initialize dialog with layer-based names and variables if single layer selected if len( self.tblLayers.selectedItems() ) / 3 == 1: context.appendScope( QgsExpressionContextUtils.layerScope( layer ) ) self.expressionDlg.expressionBuilderWidget.setLayer( layer ) self.expressionDlg.expressionBuilderWidget.loadFieldNames() # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py da = QgsDistanceArea() da.setSourceCrs( layer.crs().srsid() ) da.setEllipsoidalMode( self.iface.mapCanvas().mapSettings().hasCrsTransformEnabled() ) da.setEllipsoid( QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE )[0] ) self.expressionDlg.expressionBuilderWidget.setGeomCalculator( da ) # If this layer-field is an AutoField, get its expression if self.optExistingField.isChecked(): fieldName = self.cboField.currentText() expression = self.autoFieldManager.getFieldExpression( layer, fieldName ) self.expressionDlg.expressionBuilderWidget.setExpressionText( expression ) self.expressionDlg.expression = expression # To remember it when closing/opening self.expressionDlg.expressionBuilderWidget.setExpressionContext( context ) self.expressionDlg.show()
def inasafe_impact_analysis_field_value(field, feature, parent): """Retrieve a value from a field in the impact analysis layer. e.g. inasafe_impact_analysis_field_value('total_not_exposed') -> 3 """ _ = feature, parent # NOQA project_context_scope = QgsExpressionContextUtils.projectScope() registry = QgsMapLayerRegistry.instance() key = provenance_layer_analysis_impacted_id['provenance_key'] if not project_context_scope.hasVariable(key): return None layer = registry.mapLayer(project_context_scope.variable(key)) if not layer: return None index = layer.fieldNameIndex(field) if index < 0: return None feature = layer.getFeatures().next() return feature[index]
def loadState(self, state=None): """ Loads all loaded workflows from current QgsProject instance. :param state: (str) this should be a strigfied map to QA's state variables. If none is given, state is retrieved from the project. """ state = json.loads( state or\ QgsExpressionContextUtils.projectScope(QgsProject.instance())\ .variable("dsgtools_qatoolbox_state") or\ "{}" ) workflows = state["workflows"] if "workflows" in state else {} self.resetComboBox() for idx, (name, workflowMap) in enumerate(workflows.items()): self.workflows[name] = QualityAssuranceWorkflow(workflowMap) self.comboBox.addItem(name) self.setWorkflowTooltip(idx + 1, self.workflows[name].metadata()) currentIdx = state["current_workflow"] if "current_workflow" in state \ else 0 self.comboBox.setCurrentIndex(currentIdx) showButtons = state["show_buttons"] if "show_buttons" in state else True self.showEditionButton(showButtons)
def checkParameterValues(self, parameters, context): # Check that the connection name has been configured connection_name = QgsExpressionContextUtils.projectScope( context.project()).variable('gobs_connection_name') if not connection_name: return False, tr( 'You must use the "Configure G-obs plugin" alg to set the database connection name' ) # Check that it corresponds to an existing connection if connection_name not in getPostgisConnectionList(): return False, tr( 'The configured connection name does not exists in QGIS') serie_id = self.parameterAsInt(parameters, self.SERIE_ID, context) # Check series id is in the list of existing series if serie_id and serie_id > 0: if serie_id not in self.SERIES_DICT.values(): return False, tr('Series ID does not exists in the database') return super(GetSeriesData, self).checkParameterValues(parameters, context)
def hazard_extra_keyword(keyword, feature, parent): """Given a keyword, it will return the value of the keyword from the hazard layer's extra keywords. For instance: * hazard_extra_keyword( 'depth' ) -> will return the value of 'depth' in current hazard layer's extra keywords. """ _ = feature, parent # NOQA hazard_layer_path = QgsExpressionContextUtils.projectScope().variable( 'hazard_layer') hazard_layer = load_layer(hazard_layer_path)[0] keywords = KeywordIO.read_keywords(hazard_layer) extra_keywords = keywords.get('extra_keywords') if extra_keywords: value = extra_keywords.get(keyword) if value: value_definition = definition(value) if value_definition: return value_definition['name'] return value else: return tr('Keyword %s is not found' % keyword) return tr('No extra keywords found')
def evaluate(params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Evaluate expressions against layer or features In parameters: LAYER=wms-layer-name EXPRESSION=An expression to evaluate or EXPRESSIONS=["first expression", "second expression"] or EXPRESSIONS={"key1": "first expression", "key2": "second expression"} // optionals FEATURE={"type": "Feature", "geometry": {}, "properties": {}} or FEATURES=[{"type": "Feature", "geometry": {}, "properties": {}}, {"type": "Feature", "geometry": {}, "properties": {}}] FORM_SCOPE=boolean to add formScope based on provided features """ layername = params.get('LAYER', '') if not layername: raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: LAYER parameter is mandatory", 400) # get layer layer = find_vector_layer(layername, project) # layer not found if not layer: raise ExpressionServiceError( "Bad request error", "Invalid LAYER parameter for 'Evaluate': {} provided".format(layername), 400) # get expressions expressions = params.get('EXPRESSIONS', '') if not expressions: expression = params.get('EXPRESSION', '') if not expression: raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: EXPRESSION or EXPRESSIONS parameter is mandatory", 400) expressions = '["{}"]'.format(expression) # try to load expressions list or dict try: exp_json = json.loads(expressions) except Exception: QgsMessageLog.logMessage( "JSON loads expressions '{}' exception:\n{}".format(expressions, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: EXPRESSIONS '{}' are not well formed".format(expressions), 400) # create expression context exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope(project)) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) # create distance area context da = QgsDistanceArea() da.setSourceCrs(layer.crs(), project.transformContext()) da.setEllipsoid(project.ellipsoid()) # parse expressions exp_map = {} exp_parser_errors = [] exp_items = [] if isinstance(exp_json, list): exp_items = enumerate(exp_json) elif isinstance(exp_json, dict): exp_items = exp_json.items() for k, e in exp_items: exp = QgsExpression(e) exp.setGeomCalculator(da) exp.setDistanceUnits(project.distanceUnits()) exp.setAreaUnits(project.areaUnits()) if exp.hasParserError(): exp_parser_errors.append('Error "{}": {}'.format(e, exp.parserErrorString())) continue if not exp.isValid(): exp_parser_errors.append('Expression not valid "{}"'.format(e)) continue exp.prepare(exp_context) exp_map[k] = exp # expression parser errors found if exp_parser_errors: raise ExpressionServiceError( "Bad request error", "Invalid EXPRESSIONS for 'Evaluate':\n{}".format('\n'.join(exp_parser_errors)), 400) # get features features = params.get('FEATURES', '') if not features: feature = params.get('FEATURE', '') if feature: features = '[' + feature + ']' # create the body body = { 'status': 'success', 'results': [], 'errors': [], 'features': 0 } # without features just evaluate expression with layer context if not features: result = {} error = {} for k, exp in exp_map.items(): value = exp.evaluate(exp_context) if exp.hasEvalError(): result[k] = None error[k] = exp.evalErrorString() else: result[k] = json.loads(QgsJsonUtils.encodeValue(value)) body['results'].append(result) body['errors'].append(error) write_json_response(body, response) return # Check features try: geojson = json.loads(features) except Exception: QgsMessageLog.logMessage( "JSON loads features '{}' exception:\n{}".format(features, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed".format(features), 400) if not geojson or not isinstance(geojson, list) or len(geojson) == 0: raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed".format(features), 400) if 'type' not in geojson[0] or geojson[0]['type'] != 'Feature': raise ExpressionServiceError( "Bad request error", ("Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed: type not defined or not " "Feature.").format(features), 400) # try to load features # read fields feature_fields = QgsJsonUtils.stringToFields( '{ "type": "FeatureCollection","features":' + features + '}', QTextCodec.codecForName("UTF-8")) # read features feature_list = QgsJsonUtils.stringToFeatureList( '{ "type": "FeatureCollection","features":' + features + '}', feature_fields, QTextCodec.codecForName("UTF-8")) # features not well formed if not feature_list: raise ExpressionServiceError( "Bad request error", "Invalid FEATURES for 'Evaluate': not GeoJSON features array provided\n{}".format(features), 400) # Extend layer fields with this provided in GeoJSON Features feat_fields = QgsFields(layer.fields()) feat_fields.extend(feature_fields) # form scope add_form_scope = params.get('FORM_SCOPE', '').lower() in ['true', '1', 't'] # loop through provided features to evaluate expressions for f in feature_list: # clone the features with all attributes # those defined in layer + fields from GeoJSON Features feat = QgsFeature(feat_fields) feat.setGeometry(f.geometry()) for field in f.fields(): fname = field.name() if feat_fields.indexOf(fname) != -1: feat.setAttribute(fname, f[fname]) # Add form scope to expression context if add_form_scope: exp_context.appendScope(QgsExpressionContextUtils.formScope(feat)) exp_context.setFeature(feat) exp_context.setFields(feat.fields()) # Evaluate expressions with the new feature result = {} error = {} for k, exp in exp_map.items(): if add_form_scope: # need to prepare the expression because the context has been updated with a new scope exp.prepare(exp_context) value = exp.evaluate(exp_context) if exp.hasEvalError(): result[k] = None error[k] = exp.evalErrorString() else: result[k] = json.loads(QgsJsonUtils.encodeValue(value)) error[k] = exp.expression() body['results'].append(result) body['errors'].append(error) write_json_response(body, response) return
def initAlgorithm(self, config): # INPUTS project = QgsProject.instance() connection_name = QgsExpressionContextUtils.projectScope( project).variable('gobs_connection_name') if not connection_name: connection_name = os.environ.get("GOBS_CONNECTION_NAME") get_data = QgsExpressionContextUtils.globalScope().variable( 'gobs_get_database_data') # List of spatial_layer sql = ''' SELECT id, sl_label FROM gobs.spatial_layer ORDER BY sl_label ''' data = [] if get_data == 'yes' and connection_name in getPostgisConnectionList(): [header, data, rowCount, ok, error_message] = fetchDataFromSqlQuery(connection_name, sql) self.SPATIALLAYERS = ['%s - %s' % (a[1], a[0]) for a in data] self.addParameter( QgsProcessingParameterEnum(self.SPATIALLAYER, tr('Target spatial layer'), options=self.SPATIALLAYERS, optional=False)) self.addParameter( QgsProcessingParameterVectorLayer(self.SOURCELAYER, tr('Source data layer'), optional=False)) self.addParameter( QgsProcessingParameterField( self.UNIQUEID, tr('Unique identifier'), parentLayerParameterName=self.SOURCELAYER)) self.addParameter( QgsProcessingParameterField( self.UNIQUELABEL, tr('Unique label'), parentLayerParameterName=self.SOURCELAYER, type=QgsProcessingParameterField.String)) # Min validity field self.addParameter( QgsProcessingParameterField( self.DATE_VALIDITY_MIN, tr('Start timestamp of validity. Field in ISO Format'), optional=True, parentLayerParameterName=self.SOURCELAYER)) # Manual min validity self.addParameter( QgsProcessingParameterString( self.MANUAL_DATE_VALIDITY_MIN, tr('Manual start timestamp of validity (2019-01-06 or 2019-01-06 22:59:50)' ), optional=True)) # Max validity field self.addParameter( QgsProcessingParameterField( self.DATE_VALIDITY_MAX, tr('End timestamp of validity. Field in ISO Format'), optional=True, parentLayerParameterName=self.SOURCELAYER)) # Manual max validity self.addParameter( QgsProcessingParameterString( self.MANUAL_DATE_VALIDITY_MAX, tr('Manual end timestamp of validity (2019-01-31 or 2019-01-31 23:59:59)' ), optional=True)) # OUTPUTS # Add output for message self.addOutput( QgsProcessingOutputString(self.OUTPUT_STRING, tr('Output message')))
def print_atlas(project, layout_name, feature_filter, scales=None, scale=None): """Generate an atlas. :param project: The project to render as atlas. :type project: QgsProject :param layout_name: Name of the layout. :type layout_name: basestring :param feature_filter: QGIS Expression to use to select the feature. It can return many features, a multiple pages PDF will be returned. :type feature_filter: basestring :param scale: A scale to force in the atlas context. Default to None. :type scale: int :param scales: A list of predefined list of scales to force in the atlas context. Default to None. :type scales: list :return: Path to the PDF. :rtype: basestring """ canvas = QgsMapCanvas() bridge = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas) bridge.setCanvasLayers() manager = project.layoutManager() master_layout = manager.layoutByName(layout_name) if not master_layout: raise AtlasPrintException('Layout not found') if master_layout.layoutType() != QgsMasterLayoutInterface.PrintLayout: raise AtlasPrintException('The layout is not a print layout') for l in manager.printLayouts(): if l.name() == layout_name: layout = l break else: raise AtlasPrintException('The layout is not found') atlas = layout.atlas() if not atlas.enabled(): raise AtlasPrintException('The layout is not enabled for an atlas') settings = QgsLayoutExporter.PdfExportSettings() if scale: layout.referenceMap().setAtlasScalingMode(QgsLayoutItemMap.Fixed) layout.referenceMap().setScale(scale) if scales: layout.referenceMap().setAtlasScalingMode(QgsLayoutItemMap.Predefined) if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = scales else: layout.reportContext().setPredefinedScales(scales) layer = atlas.coverageLayer() feature_filter = optimize_expression(layer, feature_filter) expression = QgsExpression(feature_filter) if expression.hasParserError(): raise AtlasPrintException( 'Expression is invalid, parser error: {}'.format( expression.parserErrorString())) context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(project)) context.appendScope(QgsExpressionContextUtils.layoutScope(layout)) context.appendScope(QgsExpressionContextUtils.atlasScope(atlas)) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) expression.prepare(context) if expression.hasEvalError(): raise AtlasPrintException( 'Expression is invalid, eval error: {}'.format( expression.evalErrorString())) atlas.setFilterFeatures(True) atlas.setFilterExpression(feature_filter) if not scales and layout.referenceMap().atlasScalingMode( ) == QgsLayoutItemMap.Predefined: if Qgis.QGIS_VERSION_INT >= 30900: use_project = project.useProjectScales() map_scales = project.mapScales() else: map_scales = project_scales(project) use_project = len(map_scales) == 0 if not use_project or len(map_scales) == 0: QgsMessageLog.logMessage( 'Map scales not found in project, fetching predefined map scales in global config', 'atlasprint', Qgis.Info) map_scales = global_scales() if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = map_scales else: layout.reportContext().setPredefinedScales(map_scales) export_path = os.path.join(tempfile.gettempdir(), '{}_{}.pdf'.format(layout_name, uuid4())) exporter = QgsLayoutExporter(layout) result = exporter.exportToPdf(atlas, export_path, settings) if result[0] != QgsLayoutExporter.Success and not os.path.isfile( export_path): raise Exception('export not generated {}'.format(export_path)) return export_path
def print_layout(project, layout_name, feature_filter: str = None, scales=None, scale=None, **kwargs): """Generate a PDF for an atlas or a report. :param project: The QGIS project. :type project: QgsProject :param layout_name: Name of the layout of the atlas or report. :type layout_name: basestring :param feature_filter: QGIS Expression to use to select the feature. It can return many features, a multiple pages PDF will be returned. This is required to print atlas, not report :type feature_filter: basestring :param scale: A scale to force in the atlas context. Default to None. :type scale: int :param scales: A list of predefined list of scales to force in the atlas context. Default to None. :type scales: list :return: Path to the PDF. :rtype: basestring """ canvas = QgsMapCanvas() bridge = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas) bridge.setCanvasLayers() manager = project.layoutManager() master_layout = manager.layoutByName(layout_name) settings = QgsLayoutExporter.PdfExportSettings() atlas = None atlas_layout = None report_layout = None logger = Logger() if not master_layout: raise AtlasPrintException('Layout `{}` not found'.format(layout_name)) if master_layout.layoutType() == QgsMasterLayoutInterface.PrintLayout: for _print_layout in manager.printLayouts(): if _print_layout.name() == layout_name: atlas_layout = _print_layout break atlas = atlas_layout.atlas() if not atlas.enabled(): raise AtlasPrintException('The layout is not enabled for an atlas') layer = atlas.coverageLayer() if feature_filter is None: raise AtlasPrintException( 'EXP_FILTER is mandatory to print an atlas layout') feature_filter = optimize_expression(layer, feature_filter) expression = QgsExpression(feature_filter) if expression.hasParserError(): raise AtlasPrintException( 'Expression is invalid, parser error: {}'.format( expression.parserErrorString())) context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(project)) context.appendScope( QgsExpressionContextUtils.layoutScope(atlas_layout)) context.appendScope(QgsExpressionContextUtils.atlasScope(atlas)) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) expression.prepare(context) if expression.hasEvalError(): raise AtlasPrintException( 'Expression is invalid, eval error: {}'.format( expression.evalErrorString())) atlas.setFilterFeatures(True) atlas.setFilterExpression(feature_filter) if scale: atlas_layout.referenceMap().setAtlasScalingMode( QgsLayoutItemMap.Fixed) atlas_layout.referenceMap().setScale(scale) if scales: atlas_layout.referenceMap().setAtlasScalingMode( QgsLayoutItemMap.Predefined) if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = scales else: atlas_layout.reportContext().setPredefinedScales(scales) if not scales and atlas_layout.referenceMap().atlasScalingMode( ) == QgsLayoutItemMap.Predefined: if Qgis.QGIS_VERSION_INT >= 30900: use_project = project.useProjectScales() map_scales = project.mapScales() else: map_scales = project_scales(project) use_project = len(map_scales) == 0 if not use_project or len(map_scales) == 0: logger.info( 'Map scales not found in project, fetching predefined map scales in global config' ) map_scales = global_scales() if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = map_scales else: atlas_layout.reportContext().setPredefinedScales(map_scales) elif master_layout.layoutType() == QgsMasterLayoutInterface.Report: report_layout = master_layout else: raise AtlasPrintException('The layout is not supported by the plugin') for key, value in kwargs.items(): found = False if atlas_layout: item = atlas_layout.itemById(key.lower()) if isinstance(item, QgsLayoutItemLabel): item.setText(value) found = True logger.info( 'Additional parameters: {} found in layout {}, value {}'.format( key, found, value)) export_path = os.path.join(tempfile.gettempdir(), '{}_{}.pdf'.format(layout_name, uuid4())) result, error = QgsLayoutExporter.exportToPdf(atlas or report_layout, export_path, settings) if result != QgsLayoutExporter.Success and not os.path.isfile(export_path): raise Exception('export not generated {} ({})'.format( export_path, error)) return export_path
def fetchResults(self, search, context, feedback): self.info('search {}'.format(search)) if len(search) < 3: return if search in 'tomtom ': return project = QgsProject.instance() try: key = QgsExpressionContextUtils.projectScope(project).variable( 'tomtom_api_key').strip() except: #QgsExpressionContextUtils.setProjectVariable(project, 'tomtom_api_key', '') self.info('Add tomtom_api_key variable to your project') key = '' return # End with a space to trigger a search: #if search[-1] != ' ': # return url = '{}{}'.format(self.SEARCH_URL, search.strip()) url = url + '.json?' url = url + '&key=' + key url = url + '&idxSet=POI,Geo,Addr,PAD,Str,Xstr' self.info('Search url {}'.format(url)) nam = NetworkAccessManager() try: # use BLOCKING request, as fetchResults already has it's own thread! (response, content) = nam.request(url, blocking=True) #self.info(response) #self.info(response.status_code) if response.status_code == 200: # other codes are handled by NetworkAccessManager content_string = content.decode('utf-8') locations = json.loads(content_string) for loc in locations['results']: result = QgsLocatorResult() result.filter = self if loc['type'] == 'Geography': loc_type = loc['entityType'] else: loc_type = loc['type'] if loc['type'] == 'Geography': loc_display = loc['address'][ 'freeformAddress'] + ', ' + loc['address'][ 'country'] elif loc['type'] == 'Street' or loc[ 'type'] == 'Cross Street': loc_display = loc['address']['streetName'] + ', ' + loc[ 'address']['municipality'] + ', ' + loc['address'][ 'country'] elif loc['type'] == 'POI': if loc['poi'].get('brands'): loc_display = loc['poi']['brands'][0][ 'name'] + ' ' + loc['poi'][ 'name'] + ' - ' + loc['address'][ 'municipality'] + ', ' + loc[ 'address']['country'] else: loc_display = loc['poi']['name'] + ' - ' + loc[ 'address']['municipality'] + ', ' + loc[ 'address']['country'] else: loc_display = loc['address'][ 'freeformAddress'] + ', ' + loc['address'][ 'country'] result.displayString = '{} ({})'.format( loc_display, loc_type) # use the json full item as userData, so all info is in it: result.userData = loc self.resultFetched.emit(result) except RequestsException as err: # Handle exception.. # only this one seems to work self.info(err) # THIS: results in a floating window with a warning in it, wrong thread/parent? #self.iface.messageBar().pushWarning("TomTomLocatorFilter Error", '{}'.format(err)) # THIS: emitting the signal here does not work either? self.resultProblem.emit('{}'.format(err))
def processAlgorithm(self, parameters, context, feedback): # parameters # Database connection parameters connection_name = QgsExpressionContextUtils.projectScope( context.project()).variable('gobs_connection_name') if not connection_name: connection_name = os.environ.get("GOBS_CONNECTION_NAME") spatiallayer = self.SPATIALLAYERS[parameters[self.SPATIALLAYER]] sourcelayer = self.parameterAsVectorLayer(parameters, self.SOURCELAYER, context) uniqueid = self.parameterAsString(parameters, self.UNIQUEID, context) uniquelabel = self.parameterAsString(parameters, self.UNIQUELABEL, context) date_validity_min = self.parameterAsString(parameters, self.DATE_VALIDITY_MIN, context) manual_date_validity_min = self.parameterAsString( parameters, self.MANUAL_DATE_VALIDITY_MIN, context) date_validity_max = self.parameterAsString(parameters, self.DATE_VALIDITY_MAX, context) manual_date_validity_max = self.parameterAsString( parameters, self.MANUAL_DATE_VALIDITY_MAX, context) msg = '' status = 1 # Get chosen spatial layer id id_spatial_layer = spatiallayer.split('-')[-1].strip() feedback.pushInfo( tr('CHECK COMPATIBILITY BETWEEN SOURCE AND TARGET GEOMETRY TYPES')) # Get spatial layer geometry type sql = ''' SELECT sl_geometry_type FROM gobs.spatial_layer WHERE id = {0} LIMIT 1 '''.format(id_spatial_layer) target_type = None [header, data, rowCount, ok, error_message] = fetchDataFromSqlQuery(connection_name, sql) if not ok: status = 0 msg = tr('* The following error has been raised' ) + ' %s' % error_message feedback.reportError(msg) raise QgsProcessingException(msg) else: for line in data: target_type = line[0].lower() # Check multi type target_is_multi = target_type.startswith('multi') # Get vector layer geometry type # And compare it with the spatial_layer type source_type = QgsWkbTypes.geometryDisplayString( int(sourcelayer.geometryType())).lower() source_wtype = QgsWkbTypes.displayString(int( sourcelayer.wkbType())).lower() ok = True if not target_type.endswith(source_type): ok = False msg = tr( 'Source vector layer and target spatial layer do not have compatible geometry types' ) msg += ' - SOURCE: {}, TARGET: {}'.format(source_type, target_type) feedback.pushInfo(msg) raise QgsProcessingException(msg) source_is_multi = source_wtype.startswith('multi') # Cannot import multi type into single type target spatial layer if source_is_multi and not target_is_multi: ok = False msg = tr( 'Cannot import a vector layer with multi geometries into a target spatial layer with a simple geometry type defined' ) msg += ' - SOURCE: {}, TARGET: {}'.format(source_wtype, target_type) feedback.pushInfo(msg) raise QgsProcessingException(msg) # Import data to temporary table feedback.pushInfo(tr('IMPORT SOURCE LAYER INTO TEMPORARY TABLE')) temp_schema = 'public' temp_table = 'temp_' + str(time.time()).replace('.', '') processing.run("qgis:importintopostgis", { 'INPUT': parameters[self.SOURCELAYER], 'DATABASE': connection_name, 'SCHEMA': temp_schema, 'TABLENAME': temp_table, 'PRIMARY_KEY': 'gobs_id', 'GEOMETRY_COLUMN': 'geom', 'ENCODING': 'UTF-8', 'OVERWRITE': True, 'CREATEINDEX': False, 'LOWERCASE_NAMES': False, 'DROP_STRING_LENGTH': True, 'FORCE_SINGLEPART': False }, context=context, feedback=feedback) feedback.pushInfo( tr('* Source layer has been imported into temporary table')) # Add ST_Multi if needed st_multi_left = '' st_multi_right = '' if target_is_multi: st_multi_left = 'ST_Multi(' st_multi_right = ')' # Get target geometry type in integer geometry_type_integer = 1 if target_type.replace('multi', '') == 'linestring': geometry_type_integer = 2 if target_type.replace('multi', '') == 'polygon': geometry_type_integer = 3 # Format validity timestamp fields if manual_date_validity_min.strip(): manualdate = manual_date_validity_min.strip().replace('/', '-') casted_timestamp_min = ''' '{0}'::timestamp '''.format(manualdate) else: casted_timestamp_min = ''' s."{0}"::timestamp '''.format(date_validity_min) has_max_validity = False if manual_date_validity_max.strip() or date_validity_max: has_max_validity = True if manual_date_validity_max.strip(): manualdate = manual_date_validity_max.strip().replace('/', '-') casted_timestamp_max = ''' '{0}'::timestamp '''.format(manualdate) else: casted_timestamp_max = ''' s."{0}"::timestamp '''.format(date_validity_max) # Copy data to spatial_object feedback.pushInfo(tr('COPY IMPORTED DATA TO spatial_object')) sql = ''' INSERT INTO gobs.spatial_object ( so_unique_id, so_unique_label, geom, fk_id_spatial_layer, so_valid_from ''' if has_max_validity: sql += ', so_valid_to' sql += ''' ) SELECT "{so_unique_id}", "{so_unique_label}", {st_multi_left}ST_Transform(ST_CollectionExtract(ST_MakeValid(geom),{geometry_type_integer}), 4326){st_multi_right} AS geom, {id_spatial_layer}, {casted_timestamp_min} '''.format(so_unique_id=uniqueid, so_unique_label=uniquelabel, st_multi_left=st_multi_left, geometry_type_integer=geometry_type_integer, st_multi_right=st_multi_right, id_spatial_layer=id_spatial_layer, casted_timestamp_min=casted_timestamp_min) if has_max_validity: sql += ', {casted_timestamp_max}'.format( casted_timestamp_max=casted_timestamp_max) sql += ''' FROM "{temp_schema}"."{temp_table}" AS s -- Update line if data already exists -- i.e. Same external ids for the same layer and the same start validity date -- so_unique_id, fk_id_spatial_layer AND so_valid_from are the same -- This is considered as the same object as the one already in database -- We update the geometry, label, and end date of validity ON CONFLICT ON CONSTRAINT spatial_object_unique_key DO UPDATE SET (geom, so_unique_label, so_valid_to) = (EXCLUDED.geom, EXCLUDED.so_unique_label, EXCLUDED.so_valid_to) WHERE True ; '''.format(temp_schema=temp_schema, temp_table=temp_table) try: [header, data, rowCount, ok, error_message] = fetchDataFromSqlQuery(connection_name, sql) if not ok: status = 0 msg = tr('* The following error has been raised' ) + ' %s' % error_message feedback.reportError(msg) feedback.pushInfo(sql) else: status = 1 msg = tr('* Source data has been successfully imported !') feedback.pushInfo(msg) except Exception as e: status = 0 msg = tr( '* An unknown error occured while adding features to spatial_object table' ) msg += ' ' + str(e) # Check there is no issues with related observation data # For each series related to the chosen spatial layer # SELECT gobs.find_observation_with_wrong_spatial_object({fk_id_series}) # v1/ Only check and display warning # v2/ Check and try to update with gobs.update_observations_with_wrong_spatial_objects # v3/ Find orphans # Remove temporary table feedback.pushInfo(tr('DROP TEMPORARY DATA')) sql = ''' DROP TABLE IF EXISTS "%s"."%s" ; ''' % (temp_schema, temp_table) [header, data, rowCount, ok, error_message] = fetchDataFromSqlQuery(connection_name, sql) if ok: feedback.pushInfo(tr('* Temporary data has been deleted.')) else: feedback.reportError( tr('* An error occured while droping temporary table') + ' "%s"."%s"' % (temp_schema, temp_table)) msg = tr('SPATIAL LAYER HAS BEEN SUCCESSFULLY IMPORTED !') return {self.OUTPUT_STATUS: status, self.OUTPUT_STRING: msg}
def virtualFields(params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Get virtual fields for features In parameters: LAYER=wms-layer-name VIRTUALS={"key1": "first expression", "key2": "second expression"} // optionals FILTER=An expression to filter layer FIELDS=list of requested field separated by comma WITH_GEOMETRY=False """ layer_name = params.get('LAYER', '') if not layer_name: raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: LAYER parameter is mandatory", 400) # get layer layer = find_vector_layer(layer_name, project) # layer not found if not layer: raise ExpressionServiceError( "Bad request error", "Invalid LAYER parameter for 'VirtualFields': {} provided".format(layer_name), 400) # get virtuals virtuals = params.get('VIRTUALS', '') if not virtuals: raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: VIRTUALS parameter is mandatory", 400) # try to load virtuals dict try: vir_json = json.loads(virtuals) except Exception: QgsMessageLog.logMessage( "JSON loads virtuals '{}' exception:\n{}".format(virtuals, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: VIRTUALS '{}' are not well formed".format(virtuals), 400) if not isinstance(vir_json, dict): raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: VIRTUALS '{}' are not well formed".format(virtuals), 400) # create expression context exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope(project)) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) # create distance area context da = QgsDistanceArea() da.setSourceCrs(layer.crs(), project.transformContext()) da.setEllipsoid(project.ellipsoid()) # parse virtuals exp_map = {} exp_parser_errors = [] for k, e in vir_json.items(): exp = QgsExpression(e) exp.setGeomCalculator(da) exp.setDistanceUnits(project.distanceUnits()) exp.setAreaUnits(project.areaUnits()) if exp.hasParserError(): exp_parser_errors.append('Error "{}": {}'.format(e, exp.parserErrorString())) continue if not exp.isValid(): exp_parser_errors.append('Expression not valid "{}"'.format(e)) continue exp.prepare(exp_context) exp_map[k] = exp # expression parser errors found if exp_parser_errors: raise ExpressionServiceError( "Bad request error", "Invalid VIRTUALS for 'VirtualFields':\n{}".format('\n'.join(exp_parser_errors)), 400) req = QgsFeatureRequest() # get filter req_filter = params.get('FILTER', '') if req_filter: req_exp = QgsExpression(req_filter) req_exp.setGeomCalculator(da) req_exp.setDistanceUnits(project.distanceUnits()) req_exp.setAreaUnits(project.areaUnits()) if req_exp.hasParserError(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'VirtualFields' Error \"{}\": {}".format( req_filter, req_exp.parserErrorString()), 400) if not req_exp.isValid(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'VirtualFields' Expression not valid \"{}\"".format(req_filter), 400) req_exp.prepare(exp_context) req = QgsFeatureRequest(req_exp, exp_context) # With geometry with_geom = params.get('WITH_GEOMETRY', '').lower() in ['true', '1', 't'] if not with_geom: req.setFlags(QgsFeatureRequest.NoGeometry) # Fields pk_attributes = layer.primaryKeyAttributes() attribute_list = [i for i in pk_attributes] fields = layer.fields() r_fields = [f.strip() for f in params.get('FIELDS', '').split(',') if f] for f in r_fields: attribute_list.append(fields.indexOf(f)) # response response.setStatusCode(200) response.setHeader("Content-Type", "application/json") response.write('{ "type": "FeatureCollection","features":[') response.flush() json_exporter = QgsJsonExporter(layer) if attribute_list: json_exporter.setAttributes(attribute_list) separator = '' for feat in layer.getFeatures(req): fid = layer_name + '.' + get_server_fid(feat, pk_attributes) extra = {} # Update context exp_context.setFeature(feat) exp_context.setFields(feat.fields()) # Evaluate expressions for virtual fields errors = {} for k, exp in exp_map.items(): value = exp.evaluate(exp_context) if exp.hasEvalError(): extra[k] = None errors[k] = exp.evalErrorString() else: extra[k] = json.loads(QgsJsonUtils.encodeValue(value)) errors[k] = exp.expression() response.write(separator + json_exporter.exportFeature(feat, extra, fid)) response.flush() separator = ',\n' response.write(']}') return
def processAlgorithm(self, progress): layer = self.getParameterValue(self.INPUT_LAYER) mapping = self.getParameterValue(self.FIELDS_MAPPING) output = self.getOutputFromName(self.OUTPUT_LAYER) layer = dataobjects.getObjectFromUri(layer) fields = [] expressions = [] da = QgsDistanceArea() da.setSourceCrs(layer.crs().srsid()) da.setEllipsoidalMode( iface.mapCanvas().mapSettings().hasCrsTransformEnabled()) da.setEllipsoid(QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE)[0]) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) for field_def in mapping: fields.append( QgsField(name=field_def['name'], type=field_def['type'], len=field_def['length'], prec=field_def['precision'])) expression = QgsExpression(field_def['expression']) expression.setGeomCalculator(da) expression.setDistanceUnits(QgsProject.instance().distanceUnits()) expression.setAreaUnits(QgsProject.instance().areaUnits()) if expression.hasParserError(): raise GeoAlgorithmExecutionException( self.tr(u'Parser error in expression "{}": {}').format( str(field_def['expression']), str(expression.parserErrorString()))) expression.prepare(exp_context) if expression.hasEvalError(): raise GeoAlgorithmExecutionException( self.tr(u'Evaluation error in expression "{}": {}').format( str(field_def['expression']), str(expression.evalErrorString()))) expressions.append(expression) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs()) # Create output vector layer with new attributes error = '' calculationSuccess = True inFeat = QgsFeature() outFeat = QgsFeature() features = vector.features(layer) total = 100.0 / len(features) for current, inFeat in enumerate(features): rownum = current + 1 geometry = inFeat.geometry() outFeat.setGeometry(geometry) attrs = [] for i in range(0, len(mapping)): field_def = mapping[i] expression = expressions[i] exp_context.setFeature(inFeat) exp_context.lastScope().setVariable("row_number", rownum) value = expression.evaluate(exp_context) if expression.hasEvalError(): calculationSuccess = False error = expression.evalErrorString() break attrs.append(value) outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer if not calculationSuccess: raise GeoAlgorithmExecutionException( self.tr('An error occurred while evaluating the calculation' ' string:\n') + error)
def getProjectVariable(project, variable): if (project is not None): scope = QgsExpressionContextUtils.projectScope(project) return scope.variable(variable) else: return None
def processAlgorithm(self, progress): layer = self.getParameterValue(self.INPUT_LAYER) mapping = self.getParameterValue(self.FIELDS_MAPPING) output = self.getOutputFromName(self.OUTPUT_LAYER) layer = dataobjects.getObjectFromUri(layer) fields = [] expressions = [] da = QgsDistanceArea() da.setSourceCrs(layer.crs().srsid()) da.setEllipsoidalMode( iface.mapCanvas().mapSettings().hasCrsTransformEnabled()) da.setEllipsoid(QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE)[0]) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) for field_def in mapping: fields.append(QgsField(name=field_def['name'], type=field_def['type'], len=field_def['length'], prec=field_def['precision'])) expression = QgsExpression(field_def['expression']) expression.setGeomCalculator(da) expression.setDistanceUnits(QgsProject.instance().distanceUnits()) expression.setAreaUnits(QgsProject.instance().areaUnits()) if expression.hasParserError(): raise GeoAlgorithmExecutionException( self.tr(u'Parser error in expression "{}": {}') .format(str(field_def['expression']), str(expression.parserErrorString()))) expression.prepare(exp_context) if expression.hasEvalError(): raise GeoAlgorithmExecutionException( self.tr(u'Evaluation error in expression "{}": {}') .format(str(field_def['expression']), str(expression.evalErrorString()))) expressions.append(expression) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs()) # Create output vector layer with new attributes error = '' calculationSuccess = True inFeat = QgsFeature() outFeat = QgsFeature() features = vector.features(layer) total = 100.0 / len(features) for current, inFeat in enumerate(features): rownum = current + 1 geometry = inFeat.geometry() outFeat.setGeometry(geometry) attrs = [] for i in range(0, len(mapping)): field_def = mapping[i] expression = expressions[i] exp_context.setFeature(inFeat) exp_context.lastScope().setVariable("row_number", rownum) value = expression.evaluate(exp_context) if expression.hasEvalError(): calculationSuccess = False error = expression.evalErrorString() break attrs.append(value) outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer if not calculationSuccess: raise GeoAlgorithmExecutionException( self.tr('An error occurred while evaluating the calculation' ' string:\n') + error)
def testHomePath(self): p = QgsProject() path_changed_spy = QSignalSpy(p.homePathChanged) self.assertFalse(p.homePath()) self.assertFalse(p.presetHomePath()) # simulate save file tmp_dir = QTemporaryDir() tmp_file = "{}/project.qgs".format(tmp_dir.path()) with open(tmp_file, 'w') as f: pass p.setFileName(tmp_file) # home path should be file path self.assertEqual(p.homePath(), tmp_dir.path()) self.assertFalse(p.presetHomePath()) self.assertEqual(len(path_changed_spy), 1) # manually override home path p.setPresetHomePath('/tmp/my_path') self.assertEqual(p.homePath(), '/tmp/my_path') self.assertEqual(p.presetHomePath(), '/tmp/my_path') self.assertEqual(len(path_changed_spy), 2) # check project scope scope = QgsExpressionContextUtils.projectScope(p) self.assertEqual(scope.variable('project_home'), '/tmp/my_path') # no extra signal if path is unchanged p.setPresetHomePath('/tmp/my_path') self.assertEqual(p.homePath(), '/tmp/my_path') self.assertEqual(p.presetHomePath(), '/tmp/my_path') self.assertEqual(len(path_changed_spy), 2) # setting file name should not affect home path is manually set tmp_file_2 = "{}/project/project2.qgs".format(tmp_dir.path()) os.mkdir(tmp_dir.path() + '/project') with open(tmp_file_2, 'w') as f: pass p.setFileName(tmp_file_2) self.assertEqual(p.homePath(), '/tmp/my_path') self.assertEqual(p.presetHomePath(), '/tmp/my_path') self.assertEqual(len(path_changed_spy), 2) scope = QgsExpressionContextUtils.projectScope(p) self.assertEqual(scope.variable('project_home'), '/tmp/my_path') # clear manual path p.setPresetHomePath('') self.assertEqual(p.homePath(), tmp_dir.path() + '/project') self.assertFalse(p.presetHomePath()) self.assertEqual(len(path_changed_spy), 3) scope = QgsExpressionContextUtils.projectScope(p) self.assertEqual(scope.variable('project_home'), tmp_dir.path() + '/project') # relative path p.setPresetHomePath('../home') self.assertEqual(p.homePath(), tmp_dir.path() + '/home') self.assertEqual(p.presetHomePath(), '../home') self.assertEqual(len(path_changed_spy), 4) scope = QgsExpressionContextUtils.projectScope(p) self.assertEqual(scope.variable('project_home'), tmp_dir.path() + '/home') # relative path, no filename p.setFileName('') self.assertEqual(p.homePath(), '../home') self.assertEqual(p.presetHomePath(), '../home') scope = QgsExpressionContextUtils.projectScope(p) self.assertEqual(scope.variable('project_home'), '../home')
def checkParameterValues(self, parameters, context): # Check that the connection name has been configured connection_name = QgsExpressionContextUtils.projectScope( context.project()).variable('gobs_connection_name') connection_name_env = os.environ.get("GOBS_CONNECTION_NAME") if not connection_name and not connection_name_env: return False, tr( 'You must use the "Configure G-obs plugin" alg to set the database connection name' ) # Check that it corresponds to an existing connection if connection_name and connection_name not in getPostgisConnectionList( ): return False, tr( 'The configured connection name does not exists in QGIS') # replace connection_name by env variable if not connection_name: connection_name = connection_name_env # Check correct validity timestamps have been given date_fields = { 'Start of validity': { 'field': self.DATE_VALIDITY_MIN, 'manual': self.MANUAL_DATE_VALIDITY_MIN, 'optional': False }, 'End of validity': { 'field': self.DATE_VALIDITY_MAX, 'manual': self.MANUAL_DATE_VALIDITY_MAX, 'optional': True } } for key in date_fields: ok = True item = date_fields[key] field_timestamp = self.parameterAsString(parameters, item['field'], context) manualdate = (self.parameterAsString(parameters, item['manual'], context)).strip().replace( '/', '-') if not field_timestamp and not manualdate and not item['optional']: ok = False msg = tr(key) + ' - ' msg += tr( 'You need to enter either a timestamp field or a manual timestamp' ) # check validity of given manual date if manualdate: ok, msg = validateTimestamp(manualdate) if not ok: return False, tr(key) + ' - ' + msg ok = True if not ok: return False, msg return super(ImportSpatialLayerData, self).checkParameterValues(parameters, context)
def replace_expression_text(params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Replace expression texts against layer or features In parameters: LAYER=wms-layer-name STRING=A string with expression between [% and %] or STRINGS=["first string with expression", "second string with expression"] or STRINGS={"key1": "first string with expression", "key2": "second string with expression"} // optionals FEATURE={"type": "Feature", "geometry": {}, "properties": {}} or FEATURES=[{"type": "Feature", "geometry": {}, "properties": {}}, {"type": "Feature", "geometry": {}, "properties": {}}] FORM_SCOPE=boolean to add formScope based on provided features """ layername = params.get('LAYER', '') if not layername: raise ExpressionServiceError( "Bad request error", "Invalid 'ReplaceExpressionText' REQUEST: LAYER parameter is mandatory", 400) # get layer layer = find_vector_layer(layername, project) # layer not found if not layer: raise ExpressionServiceError( "Bad request error", "Invalid LAYER parameter for 'ReplaceExpressionText': {} provided".format(layername), 400) # get strings strings = params.get('STRINGS', '') if not strings: the_string = params.get('STRING', '') if not the_string: raise ExpressionServiceError( "Bad request error", "Invalid 'ReplaceExpressionText' REQUEST: STRING or STRINGS parameter is mandatory", 400) strings = '["{}"]'.format(the_string) # try to load expressions list or dict try: str_json = json.loads(strings) except Exception: QgsMessageLog.logMessage( "JSON loads strings '{}' exception:\n{}".format(strings, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'ReplaceExpressionText' REQUEST: STRINGS '{}' are not well formed".format(strings), 400) # get features features = params.get('FEATURES', '') if not features: feature = params.get('FEATURE', '') if feature: features = '[' + feature + ']' # create expression context exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope(project)) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) # create distance area context da = QgsDistanceArea() da.setSourceCrs(layer.crs(), project.transformContext()) da.setEllipsoid(project.ellipsoid()) # organized strings str_map = {} str_items = [] if isinstance(str_json, list): str_items = enumerate(str_json) elif isinstance(str_json, dict): str_items = str_json.items() for k, s in str_items: str_map[k] = s # create the body body = { 'status': 'success', 'results': [], 'errors': [], 'features': 0 } # without features just replace expression string with layer context if not features: result = {} for k, s in str_map.items(): value = QgsExpression.replaceExpressionText(s, exp_context, da) result[k] = json.loads(QgsJsonUtils.encodeValue(value)) body['results'].append(result) write_json_response(body, response) return # Check features try: geojson = json.loads(features) except Exception: QgsMessageLog.logMessage( "JSON loads features '{}' exception:\n{}".format(features, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed".format(features), 400) if not geojson or not isinstance(geojson, list) or len(geojson) == 0: raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed".format(features), 400) if ('type' not in geojson[0]) or geojson[0]['type'] != 'Feature': raise ExpressionServiceError( "Bad request error", ("Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed: type not defined or not " "Feature.").format(features), 400) # try to load features # read fields feature_fields = QgsJsonUtils.stringToFields( '{ "type": "FeatureCollection","features":' + features + '}', QTextCodec.codecForName("UTF-8")) # read features feature_list = QgsJsonUtils.stringToFeatureList( '{ "type": "FeatureCollection","features":' + features + '}', feature_fields, QTextCodec.codecForName("UTF-8")) # features not well formed if not feature_list: raise ExpressionServiceError( "Bad request error", ("Invalid FEATURES for 'ReplaceExpressionText': not GeoJSON features array " "provided\n{}").format(features), 400) # Extend layer fields with this provided in GeoJSON Features feat_fields = QgsFields(layer.fields()) feat_fields.extend(feature_fields) # form scope add_form_scope = params.get('FORM_SCOPE', '').lower() in ['true', '1', 't'] # loop through provided features to replace expression strings for f in feature_list: # clone the features with all attributes # those defined in layer + fields from GeoJSON Features feat = QgsFeature(feat_fields) feat.setGeometry(f.geometry()) for field in f.fields(): field_name = field.name() if feat_fields.indexOf(field_name) != -1: feat.setAttribute(field_name, f[field_name]) # Add form scope to expression context if add_form_scope: exp_context.appendScope(QgsExpressionContextUtils.formScope(feat)) exp_context.setFeature(feat) exp_context.setFields(feat.fields()) # replace expression strings with the new feature result = {} for k, s in str_map.items(): value = QgsExpression.replaceExpressionText(s, exp_context, da) result[k] = json.loads(QgsJsonUtils.encodeValue(value)) body['results'].append(result) write_json_response(body, response) return
def get_feature_with_form_scope(params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Get filtered features with a form scope In parameters: LAYER=wms-layer-name FILTER=An expression to filter layer FORM_FEATURE={"type": "Feature", "geometry": {}, "properties": {}} // optionals FIELDS=list of requested field separated by comma WITH_GEOMETRY=False """ layer_name = params.get('LAYER', '') if not layer_name: raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: LAYER parameter is mandatory", 400) # get layer layer = find_vector_layer(layer_name, project) # layer not found if not layer: raise ExpressionServiceError( "Bad request error", "Invalid LAYER parameter for 'VirtualField': {} provided".format(layer_name), 400) # get filter exp_filter = params.get('FILTER', '') if not exp_filter: raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FILTER parameter is mandatory", 400) # get form feature form_feature = params.get('FORM_FEATURE', '') if not form_feature: raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE parameter is mandatory", 400) # Check features try: geojson = json.loads(form_feature) except Exception: QgsMessageLog.logMessage( "JSON loads form feature '{}' exception:\n{}".format(form_feature, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed".format(form_feature), 400) if not geojson or not isinstance(geojson, dict): raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed".format(form_feature), 400) if ('type' not in geojson) or geojson['type'] != 'Feature': raise ExpressionServiceError( "Bad request error", ("Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed: type not defined " "or not Feature.").format(form_feature), 400) # try to load form feature # read fields form_feature_fields = QgsJsonUtils.stringToFields( form_feature, QTextCodec.codecForName("UTF-8")) # read features form_feature_list = QgsJsonUtils.stringToFeatureList( form_feature, form_feature_fields, QTextCodec.codecForName("UTF-8")) # features not well formed if not form_feature_list: raise ExpressionServiceError( "Bad request error", ("Invalid FORM_FEATURE for 'GetFeatureWithFormScope': not GeoJSON feature provided\n" "{}").format(form_feature), 400) if len(form_feature_list) != 1: raise ExpressionServiceError( "Bad request error", ("Invalid FORM_FEATURE for 'GetFeatureWithFormScope': not GeoJSON feature provided\n" "{}").format(form_feature), 400) # Get the form feature form_feat = form_feature_list[0] # create expression context exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope(project)) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) exp_context.appendScope(QgsExpressionContextUtils.formScope(form_feat)) # create distance area context da = QgsDistanceArea() da.setSourceCrs(layer.crs(), project.transformContext()) da.setEllipsoid(project.ellipsoid()) # Get filter expression exp_f = QgsExpression(exp_filter) exp_f.setGeomCalculator(da) exp_f.setDistanceUnits(project.distanceUnits()) exp_f.setAreaUnits(project.areaUnits()) if exp_f.hasParserError(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'GetFeatureWithFormScope': Error \"{}\": {}".format( exp_filter, exp_f.parserErrorString()), 400) if not exp_f.isValid(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'GetFeatureWithFormScope': Expression not valid \"{}\"".format(exp_filter), 400) exp_f.prepare(exp_context) req = QgsFeatureRequest(exp_f, exp_context) # With geometry with_geom = params.get('WITH_GEOMETRY', '').lower() in ['true', '1', 't'] if not with_geom: req.setFlags(QgsFeatureRequest.NoGeometry) # Fields pk_attributes = layer.primaryKeyAttributes() attribute_list = [i for i in pk_attributes] fields = layer.fields() r_fields = [f.strip() for f in params.get('FIELDS', '').split(',') if f] for f in r_fields: attribute_list.append(fields.indexOf(f)) # response response.setStatusCode(200) response.setHeader("Content-Type", "application/json") response.write('{ "type": "FeatureCollection","features":[') response.flush() json_exporter = QgsJsonExporter(layer) if attribute_list: json_exporter.setAttributes(attribute_list) separator = '' for feat in layer.getFeatures(req): fid = layer_name + '.' + get_server_fid(feat, pk_attributes) response.write(separator + json_exporter.exportFeature(feat, {}, fid)) response.flush() separator = ',\n' response.write(']}') return
def photoDetails_field(self, restrictionDialog, currRestrictionLayer, currRestriction): # Function to deal with photo fields self.demandDialog = restrictionDialog self.currDemandLayer = currRestrictionLayer self.currFeature = currRestriction TOMsMessageLog.logMessage("gnns: In photoDetails", level=Qgis.Info) photoPath = QgsExpressionContextUtils.projectScope( QgsProject.instance()).variable('PhotoPath') #path_absolute = photoPath projectFolder = QgsExpressionContextUtils.projectScope( QgsProject.instance()).variable('project_home') path_absolute = os.path.join(projectFolder, photoPath) if path_absolute == None: reply = QMessageBox.information(None, "Information", "Please set value for PhotoPath.", QMessageBox.Ok) return # Check path exists ... if os.path.isdir(path_absolute) == False: reply = QMessageBox.information( None, "Information", "PhotoPath folder " + str(path_absolute) + " does not exist. Please check value.", QMessageBox.Ok) return # if cv2 is available, check camera nr try: cameraNr = int(self.params.setParam("CameraNr")) except Exception as e: TOMsMessageLog.logMessage( "In photoDetails_field: cameraNr issue: {}".format(e), level=Qgis.Info) if cv2_available: cameraNr = QMessageBox.information( None, "Information", "Please set value for CameraNr.", QMessageBox.Ok) cameraNr = None TOMsMessageLog.logMessage( "In photoDetails_field: cameraNr is: {}".format(cameraNr), level=Qgis.Info) # get image resolution frameWidth, frameHeight = self.getCameraResolution() TOMsMessageLog.logMessage( "In gnns: In photoDetails: ... resolution: {}*{} ".format( frameWidth, frameHeight), level=Qgis.Warning) layerName = self.currDemandLayer.name() # Generate the full path to the file fileName1 = "Photos_01" fileName2 = "Photos_02" fileName3 = "Photos_03" idx1 = self.currDemandLayer.fields().indexFromName(fileName1) idx2 = self.currDemandLayer.fields().indexFromName(fileName2) idx3 = self.currDemandLayer.fields().indexFromName(fileName3) TOMsMessageLog.logMessage("In photoDetails. idx1: " + str(idx1) + "; " + str(idx2) + "; " + str(idx3), level=Qgis.Info) if cameraNr is not None: TOMsMessageLog.logMessage("Camera TRUE", level=Qgis.Info) takePhoto = True else: TOMsMessageLog.logMessage("Camera FALSE", level=Qgis.Info) takePhoto = False FIELD1 = self.demandDialog.findChild(QLabel, "Photo_Widget_01") FIELD2 = self.demandDialog.findChild(QLabel, "Photo_Widget_02") FIELD3 = self.demandDialog.findChild(QLabel, "Photo_Widget_03") if FIELD1: TOMsMessageLog.logMessage("In photoDetails. FIELD 1 exists", level=Qgis.Info) if self.currFeature[idx1]: newPhotoFileName1 = os.path.join(path_absolute, self.currFeature[idx1]) TOMsMessageLog.logMessage( "In photoDetails. photo1: {}".format(newPhotoFileName1), level=Qgis.Info) else: newPhotoFileName1 = None pixmap1 = QPixmap(newPhotoFileName1) tab = FIELD1.parentWidget() grid = FIELD1.parentWidget().layout() photo_Widget1 = imageLabel(tab) TOMsMessageLog.logMessage( "In photoDetails. FIELD 1 w: {}; h: {}".format( FIELD1.width(), FIELD1.height()), level=Qgis.Info) photo_Widget1.setObjectName("Photo_Widget_01") photo_Widget1.setText("No photo is here") #photo_Widget1 = imageLabel(tab) grid.addWidget(photo_Widget1, 0, 0, 1, 1) FIELD1.hide() FIELD1.setParent(None) FIELD1 = photo_Widget1 FIELD1.set_Pixmap(pixmap1) TOMsMessageLog.logMessage("In photoDetails. FIELD 1 Photo1: " + str(newPhotoFileName1), level=Qgis.Info) TOMsMessageLog.logMessage( "In photoDetails.pixmap1 size: {}".format(pixmap1.size()), level=Qgis.Info) FIELD1.pixmapUpdated.connect( functools.partial(self.displayPixmapUpdated, FIELD1)) if takePhoto: START_CAMERA_1 = self.demandDialog.findChild( QPushButton, "startCamera1") TAKE_PHOTO_1 = self.demandDialog.findChild( QPushButton, "getPhoto1") TAKE_PHOTO_1.setEnabled(False) self.camera1 = formCamera(path_absolute, newPhotoFileName1, cameraNr, frameWidth, frameHeight) START_CAMERA_1.clicked.connect( functools.partial(self.camera1.useCamera, START_CAMERA_1, TAKE_PHOTO_1, FIELD1)) self.camera1.notifyPhotoTaken.connect( functools.partial(self.savePhotoTaken, idx1)) self.camera1.pixmapUpdated.connect( functools.partial(self.displayImage, FIELD1)) if FIELD2: TOMsMessageLog.logMessage("In photoDetails. FIELD 2 exisits", level=Qgis.Info) if self.currFeature[idx2]: newPhotoFileName2 = os.path.join(path_absolute, self.currFeature[idx2]) TOMsMessageLog.logMessage("In photoDetails. Photo1: " + str(newPhotoFileName2), level=Qgis.Info) else: newPhotoFileName2 = None pixmap2 = QPixmap(newPhotoFileName2) tab = FIELD2.parentWidget() grid = FIELD2.parentWidget().layout() photo_Widget2 = imageLabel(tab) TOMsMessageLog.logMessage( "In photoDetails. FIELD 2 w: {}; h: {}".format( FIELD2.width(), FIELD2.height()), level=Qgis.Info) photo_Widget2.setObjectName("Photo_Widget_02") photo_Widget2.setText("No photo is here") #photo_Widget2 = imageLabel(tab) grid.addWidget(photo_Widget2, 0, 0, 1, 1) FIELD2.hide() FIELD2.setParent(None) FIELD2 = photo_Widget2 FIELD2.set_Pixmap(pixmap2) TOMsMessageLog.logMessage("In photoDetails. FIELD 2 Photo2: " + str(newPhotoFileName2), level=Qgis.Info) TOMsMessageLog.logMessage( "In photoDetails.pixmap2 size: {}".format(pixmap2.size()), level=Qgis.Info) FIELD2.pixmapUpdated.connect( functools.partial(self.displayPixmapUpdated, FIELD2)) if takePhoto: START_CAMERA_2 = self.demandDialog.findChild( QPushButton, "startCamera2") TAKE_PHOTO_2 = self.demandDialog.findChild( QPushButton, "getPhoto2") TAKE_PHOTO_2.setEnabled(False) self.camera2 = formCamera(path_absolute, newPhotoFileName2, cameraNr, frameWidth, frameHeight) START_CAMERA_2.clicked.connect( functools.partial(self.camera2.useCamera, START_CAMERA_2, TAKE_PHOTO_2, FIELD2)) self.camera2.notifyPhotoTaken.connect( functools.partial(self.savePhotoTaken, idx2)) self.camera2.pixmapUpdated.connect( functools.partial(self.displayImage, FIELD2)) if FIELD3: TOMsMessageLog.logMessage("In photoDetails. FIELD 3 exisits", level=Qgis.Info) if self.currFeature[idx3]: newPhotoFileName3 = os.path.join(path_absolute, self.currFeature[idx3]) TOMsMessageLog.logMessage("In photoDetails. Photo1: " + str(newPhotoFileName3), level=Qgis.Info) else: newPhotoFileName3 = None pixmap3 = QPixmap(newPhotoFileName3) tab = FIELD3.parentWidget() grid = FIELD3.parentWidget().layout() photo_Widget3 = imageLabel(tab) TOMsMessageLog.logMessage( "In photoDetails. FIELD 3 w: {}; h: {}".format( FIELD3.width(), FIELD3.height()), level=Qgis.Info) photo_Widget3.setObjectName("Photo_Widget_03") photo_Widget3.setText("No photo is here") #photo_Widget3 = imageLabel(tab) grid.addWidget(photo_Widget3, 0, 0, 1, 1) FIELD3.hide() FIELD3.setParent(None) FIELD3 = photo_Widget3 FIELD3.set_Pixmap(pixmap3) TOMsMessageLog.logMessage("In photoDetails. FIELD 3 Photo3: " + str(newPhotoFileName3), level=Qgis.Info) TOMsMessageLog.logMessage( "In photoDetails.pixmap3 size: {}".format(pixmap3.size()), level=Qgis.Info) FIELD3.pixmapUpdated.connect( functools.partial(self.displayPixmapUpdated, FIELD3)) if takePhoto: START_CAMERA_3 = self.demandDialog.findChild( QPushButton, "startCamera3") TAKE_PHOTO_3 = self.demandDialog.findChild( QPushButton, "getPhoto3") TAKE_PHOTO_3.setEnabled(False) self.camera3 = formCamera(path_absolute, newPhotoFileName3, cameraNr, frameWidth, frameHeight) START_CAMERA_3.clicked.connect( functools.partial(self.camera3.useCamera, START_CAMERA_3, TAKE_PHOTO_3, FIELD3)) self.camera3.notifyPhotoTaken.connect( functools.partial(self.savePhotoTaken, idx3)) self.camera3.pixmapUpdated.connect( functools.partial(self.displayImage, FIELD3)) pass
def __init__(self, path: str): super(UiBuilder, self).__init__() if not path: raise ValueError("path is None") self.prefix = "ve" self.var_format = "{0}_{1}" self.project = QgsProject.instance() self.user_ui = createClass(path) proj_variables = QgsExpressionContextUtils.projectScope(self.project) # signals and init variables ui_objs = self.user_ui.findChildren(QObject) for obj in ui_objs: name = obj.objectName() if name: var_name = self.var_format.format(self.prefix, name) if isinstance(obj, QCheckBox): if var_name in proj_variables.variableNames(): try: value = int(proj_variables.variable(var_name)) except ValueError: value = 0 finally: obj.setCheckState(value) else: self.store_variable(name, obj.checkState()) obj.stateChanged.connect(self.widget_connector) elif isinstance(obj, QComboBox): if var_name in proj_variables.variableNames(): value = proj_variables.variable(var_name) obj.setCurrentText(value) else: self.store_variable(name, obj.currentText()) obj.currentIndexChanged.connect(self.widget_connector) elif isinstance(obj, QAbstractSpinBox): if var_name in proj_variables.variableNames(): value = proj_variables.variable(var_name) obj.lineEdit().setText(value) else: self.store_variable(name, obj.text()) obj.editingFinished.connect(self.widget_connector) elif isinstance(obj, QLineEdit): if var_name in proj_variables.variableNames(): value = proj_variables.variable(var_name) obj.setText(value) else: self.store_variable(name, obj.text()) obj.editingFinished.connect(self.widget_connector) elif isinstance(obj, QAbstractSlider): if var_name in proj_variables.variableNames(): try: value = int(proj_variables.variable(var_name)) except ValueError: value = 0 finally: obj.setValue(value) else: self.store_variable(name, obj.value()) obj.valueChanged.connect(self.widget_connector) self.user_ui.show()
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_LAYER)) fieldName = self.getParameterValue(self.FIELD_NAME) fieldType = self.TYPES[self.getParameterValue(self.FIELD_TYPE)] width = self.getParameterValue(self.FIELD_LENGTH) precision = self.getParameterValue(self.FIELD_PRECISION) newField = self.getParameterValue(self.NEW_FIELD) formula = self.getParameterValue(self.FORMULA) output = self.getOutputFromName(self.OUTPUT_LAYER) fields = layer.fields() if newField: fields.append(QgsField(fieldName, fieldType, '', width, precision)) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs()) exp = QgsExpression(formula) da = QgsDistanceArea() da.setSourceCrs(layer.crs().srsid()) da.setEllipsoidalMode( iface.mapCanvas().mapSettings().hasCrsTransformEnabled()) da.setEllipsoid(QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE)[0]) exp.setGeomCalculator(da) exp.setDistanceUnits(QgsProject.instance().distanceUnits()) exp.setAreaUnits(QgsProject.instance().areaUnits()) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) if not exp.prepare(exp_context): raise GeoAlgorithmExecutionException( self.tr('Evaluation error: %s' % exp.evalErrorString())) outFeature = QgsFeature() outFeature.initAttributes(len(fields)) outFeature.setFields(fields) error = '' calculationSuccess = True features = vector.features(layer) total = 100.0 / len(features) rownum = 1 for current, f in enumerate(features): rownum = current + 1 exp_context.setFeature(f) exp_context.lastScope().setVariable("row_number", rownum) value = exp.evaluate(exp_context) if exp.hasEvalError(): calculationSuccess = False error = exp.evalErrorString() break else: outFeature.setGeometry(f.geometry()) for fld in f.fields(): outFeature[fld.name()] = f[fld.name()] outFeature[fieldName] = value writer.addFeature(outFeature) progress.setPercentage(int(current * total)) del writer if not calculationSuccess: raise GeoAlgorithmExecutionException( self.tr('An error occurred while evaluating the calculation ' 'string:\n%s' % error))
def populateMetadataItems(self, m, layout): """Get the current value of metadata items from the project or layout variable, and populate the Edit Metadata dialog See *updateVars* to populate variable values from th Edit Metadata UI """ currProject = QgsProject.instance() # Check that all the variables exist, and if they don't, create them and give them a default value where appropriate with open(os.path.join(self.plugin_dir, "input/metadata_items.csv"), 'r') as metadata_file: reader = csv.reader(metadata_file, delimiter=',') metadata_list = list(reader) for x in metadata_list: ma_variable = str(x[0]) elem_name = str(x[1]) elem_name = elem_name.strip() ma_level = str(x[2]) default_value = str(x[3]) ma_level = ma_level.strip() # If project level variables don't exist, create them and populate with the default value if (ma_level == 'project'): if str( QgsExpressionContextUtils.projectScope( currProject).variable(ma_variable)) == 'None': QgsExpressionContextUtils.setProjectVariable( currProject, ma_variable, default_value) # Populate comboboxes # Populate values of Status combobox self.dlg.maStatus.addItem('New') self.dlg.maStatus.addItem('Correction') self.dlg.maStatus.addItem('Update') # Populate values of Access combobox self.dlg.maAccess.addItem('Public') self.dlg.maAccess.addItem('MapAction') self.dlg.maAccess.addItem('Selected partners') # Populate values of Language combobox self.dlg.maLanguage.addItem('English') self.dlg.maLanguage.addItem('French') self.dlg.maLanguage.addItem('Spanish') # Populate the Edit Metadata dialog with current values from variables for x in m: ma_variable = str(x[0]) elem_name = str(x[1]) elem_name = elem_name.strip() ma_level = str(x[2]) ma_level = ma_level.strip() default_value = str(x[3]) proj_crs = QgsProject.instance().crs() if (ma_level == 'project'): # Project: get current value for each variable from project and populate field if ma_variable == 'ma_country': self.dlg.maCountry.setText( str( QgsExpressionContextUtils.projectScope( currProject).variable(ma_variable))) elif ma_variable == 'ma_crs': self.dlg.maCrs.setText( str( QgsCoordinateReferenceSystem( proj_crs).description())) elif ma_variable == 'ma_glide_number': self.dlg.maGlide.setText( str( QgsExpressionContextUtils.projectScope( currProject).variable(ma_variable))) elif ma_variable == 'ma_organisation': self.dlg.maOrganisation.setText( str( QgsExpressionContextUtils.projectScope( currProject).variable(ma_variable))) elif ma_variable == 'ma_opid': self.dlg.maOperationID.setText( str( QgsExpressionContextUtils.projectScope( currProject).variable(ma_variable))) elif ma_variable == 'ma_sourceorg': self.dlg.maSourceOrg.setText( str( QgsExpressionContextUtils.projectScope( currProject).variable(ma_variable))) elif ma_variable == 'ma_acknowledgements': self.dlg.maAcknowledgements.setText( str( QgsExpressionContextUtils.projectScope( currProject).variable(ma_variable))) elif ma_variable == 'ma_disclaimer': self.dlg.maDisclaimer.setText( str( QgsExpressionContextUtils.projectScope( currProject).variable(ma_variable))) # Layout: Get the current value of the variable if it exists and populate the field elif (ma_level == 'layout'): for layout in QgsProject.instance().layoutManager( ).printLayouts(): # If the variable doesn't exist, create it if layout.name() == self.dlg.layoutSelect.currentText(): if str( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable)) == 'None': QgsExpressionContextUtils.setLayoutVariable( layout, ma_variable, default_value) elif ma_variable == 'ma_map_number': self.dlg.maMapNumber.setText( str( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable))) elif ma_variable == 'ma_summary': self.dlg.maSummary.setText( str( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable))) elif ma_variable == 'ma_datasource': self.dlg.maDatasource.setText( str( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable))) elif ma_variable == 'ma_title': self.dlg.maTitle.setText( str( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable))) elif ma_variable == 'ma_version': self.dlg.maVersion.setValue( int( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable))) elif ma_variable == 'ma_status': self.dlg.maStatus.setCurrentText( str( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable))) elif ma_variable == 'ma_access': self.dlg.maAccess.setCurrentText( str( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable))) elif ma_variable == 'ma_language': self.dlg.maLanguage.setCurrentText( str( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable))) else: # ACTION: update or remove this message QgsMessageLog.logMessage('Warning: level ' + str(ma_level), 'MapExport')
def exportLayout(self, cView, folder, title): """Function that sets how to export files.""" currProject = QgsProject.instance() printer = QPrinter() painter = QPainter() exporter = QgsLayoutExporter(cView) # Set page progressbar maximum value self.dlg.pageBar.setValue(0) self.dlg.pageBar.setMaximum(11) # Do the export process if not os.path.exists(os.path.join(folder, title)): os.makedirs(os.path.join(folder, title)) exporter.exportToPdf(os.path.join(folder, title, title + '.pdf'), QgsLayoutExporter.PdfExportSettings()) exporter.exportToImage(os.path.join(folder, title, title + '.jpg'), QgsLayoutExporter.ImageExportSettings()) # read CSV file & load into list with open(os.path.join(self.plugin_dir, "input/metadata_items.csv"), 'r') as metadata_file: reader = csv.reader(metadata_file, delimiter=',') metadata_list = list(reader) settings = ET.Element("mapdoc") mapdata = ET.SubElement(settings, "mapdata") # output fixed QGIS variables to XML """ACTION?""" # output project variables listed in CSV to XML for x in metadata_list: ma_variable = str(x[0]) elem_name = str(x[1]) elem_name = elem_name.strip() ma_level = str(x[2]) ma_level = ma_level.strip() if (ma_level == 'project') and (elem_name != 'no_xml'): elem_value = str( QgsExpressionContextUtils.projectScope( currProject).variable(ma_variable)) ET.SubElement(mapdata, elem_name).text = elem_value if elem_value.strip(): QgsMessageLog.logMessage( ma_variable + ' exported as ' + elem_value, 'MapExport', Qgis.Info) else: msgBar.pushMessage( 'Warning: missing value for ' + ma_variable, 5) QgsMessageLog.logMessage( 'Warning: missing value for ' + ma_variable, 'MapExport') themes = ET.SubElement(mapdata, "themes") for theme in self.dlg.themeBox.findChildren(QCheckBox): if theme.isChecked(): ET.SubElement(themes, 'theme').text = theme.text() for layout in QgsProject.instance().layoutManager().printLayouts(): # Set values of internal variables if layout.name() == self.dlg.layoutSelect.currentText(): date_now = datetime.date.today().strftime("%B %d, %Y") ET.SubElement(mapdata, 'lastUpdated').text = date_now title = layout.name() ET.SubElement(mapdata, 'jpgfilename').text = layout.name() + '.jpg' ET.SubElement(mapdata, 'pdffilename').text = layout.name() + '.pdf' # Action: Which map is selected by this? item = layout.referenceMap() # item = layout.itemById('main') # Get the attr by name and call map_scale = getattr(item, 'scale')() ET.SubElement(mapdata, 'scale').text = str(round(map_scale)) map_extent = item.extent() map_xmin = map_extent.xMinimum() map_xmax = map_extent.xMaximum() map_ymin = map_extent.yMinimum() map_ymax = map_extent.yMaximum() QgsMessageLog.logMessage('Scale ' + str(map_xmin), 'MapExport', Qgis.Info) ET.SubElement(mapdata, 'xmin').text = str(round(map_xmin)) ET.SubElement(mapdata, 'xmax').text = str(round(map_xmax)) ET.SubElement(mapdata, 'ymin').text = str(round(map_ymin)) ET.SubElement(mapdata, 'ymax').text = str(round(map_ymax)) for x in metadata_list: ma_variable = str(x[0]) elem_name = str(x[1]) elem_name = elem_name.strip() ma_level = str(x[2]) ma_level = ma_level.strip() if ma_level == 'layout': elem_value = str( QgsExpressionContextUtils.layoutScope( layout).variable(ma_variable)) ET.SubElement(mapdata, elem_name).text = elem_value if elem_value.strip(): QgsMessageLog.logMessage( ma_variable + ' exported as ' + elem_value, 'MapExport', Qgis.Info) else: msgBar.pushMessage( 'Warning: missing value for ' + ma_variable, 5) QgsMessageLog.logMessage( 'Warning: missing value for ' + ma_variable, 'MapExport') tree = ET.ElementTree(settings) tree.write(os.path.join(folder, title, title + '.xml')) # Set the location and the file name of the zip zippath = os.path.join(folder, title) zf = zipfile.ZipFile( os.path.abspath(folder) + os.sep + title + ".zip", "w") for dirnames, folders, files in os.walk(os.path.join(folder, title)): # for root, dirs, files in os.walk(folder): for file in files: zf.write(os.path.join(os.path.join(folder, title), file), file) zf.close() self.pageProcessed()
def processAlgorithm(self, parameters, context, feedback): t_regard = self.parameterAsSource(parameters, self.MANHOLES_TABLE, context) g_regard = self.parameterAsSource(parameters, self.GEOM_MANHOLES, context) t_troncon = self.parameterAsVectorLayer(parameters, self.SEGMENTS_TABLE, context) g_troncon = self.parameterAsVectorLayer(parameters, self.GEOM_SEGMENTS, context) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope( QgsExpressionContextUtils.layerScope(t_troncon)) exp_str = '"id_geom_troncon" IS NULL' exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) r_ids = [] # identifiant des regards l_t_f = {} # lien troncon fichier l_f_t = {} # lien fichier troncons troncons = {} sorties = {} entrees = {} for tro in t_troncon.getFeatures(request): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} segment_number = tro['id'] r1 = tro['id_regard1'] r2 = tro['id_regard2'] if r1 not in r_ids: r_ids.append(r1) if r2 not in r_ids: r_ids.append(r2) fid = tro['id_file'] l_t_f[segment_number] = fid if fid in l_f_t: l_f_t[fid] = l_f_t[fid] + [segment_number] else: l_f_t[fid] = [segment_number] troncons[segment_number] = (r1, r2) if r1 in sorties: sorties[r1] = sorties[r1] + [segment_number] else: sorties[r1] = [segment_number] if r2 in entrees: entrees[r2] = entrees[r2] + [segment_number] else: entrees[r2] = [segment_number] exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope(t_regard.createExpressionContextScope()) exp_str = ('"id_geom_regard" IS NOT NULL ' 'AND ' '"id" IN ({})').format(','.join([str(i) for i in r_ids] + ['-1'])) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) g_ids = [] # identifiants des géométrie de regards l_r_g = {} # lien regard geometrie l_g_r = {} # lien geometrie regards for reg in t_regard.getFeatures(request): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} segment_number = reg['id'] fid = reg['id_file'] if segment_number in sorties: sorties[segment_number] = [ trid for trid in sorties[segment_number] if l_t_f[trid] == fid ] if segment_number in entrees: entrees[segment_number] = [ trid for trid in entrees[segment_number] if l_t_f[trid] == fid ] gid = reg['id_geom_regard'] l_r_g[segment_number] = gid if gid not in g_ids: g_ids.append(gid) if gid in l_g_r: l_g_r[gid] = l_g_r[gid] + [segment_number] else: l_g_r[gid] = [segment_number] exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope(g_regard.createExpressionContextScope()) exp_str = '"id" IN ({})'.format(','.join([str(i) for i in g_ids] + ['-1'])) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) points = {} pt_labels = {} for reg in g_regard.getFeatures(request): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} segment_number = reg['id'] points[segment_number] = reg.geometry().asPoint() pt_labels[segment_number] = reg['label'] lines = {} for gid in points: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if gid not in l_g_r: continue for rid in l_g_r[gid]: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if rid in sorties: for tid in sorties[rid]: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if tid in lines: continue if tid not in troncons: continue r2 = troncons[tid][1] if r2 not in l_r_g: continue g2 = l_r_g[r2] if g2 not in points: continue lines[tid] = (gid, g2) if rid in entrees: for tid in entrees[rid]: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if tid in lines: continue if tid not in troncons: continue r1 = troncons[tid][0] if r1 not in l_r_g: continue g1 = l_r_g[r1] if g1 not in points: continue lines[tid] = (g1, gid) # Creation des troncons l_t_g = {} # lien troncon et geometrie troncon l_pts_t = {} # lien points troncons features = [] # les objets de geometrie de troncon geom_point_keys = [] # liste des clés des points troncons for tid, pts in lines.items(): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope( QgsExpressionContextUtils.layerScope(g_troncon)) exp_str = ('"id_geom_regard_amont" = {} AND ' '"id_geom_regard_aval" = {}').format(pts[0], pts[1]) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) request.setLimit(1) for tro in g_troncon.getFeatures(request): l_t_g[tid] = tro['id'] continue if (pts[0], pts[1]) in geom_point_keys: l_pts_t[(pts[0], pts[1])].append(tid) continue else: l_pts_t[(pts[0], pts[1])] = [tid] geom_point_keys.append((pts[0], pts[1])) feat_t = QgsVectorLayerUtils.createFeature(g_troncon) feat_t.setAttribute( 'label', '{}-{}'.format(pt_labels[pts[0]], pt_labels[pts[1]])) feat_t.setAttribute('id_geom_regard_amont', pts[0]) feat_t.setAttribute('id_geom_regard_aval', pts[1]) feat_t.setGeometry( QgsGeometry.fromPolylineXY([points[pts[0]], points[pts[1]]])) features.append(feat_t) # Ajout des objets troncons if features: g_troncon.startEditing() (res, outFeats) = g_troncon.dataProvider().addFeatures(features) if not res or not outFeats: raise QgsProcessingException( tr('* ERREUR: lors de l\'enregistrement ' 'des regards {}').format(', '.join( g_troncon.dataProvider().errors()))) if not g_troncon.commitChanges(): raise QgsProcessingException( tr('* ERROR: Commit {}.').format(g_troncon.commitErrors())) for tro in outFeats: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if not tro['id']: continue key = (tro['id_geom_regard_amont'], tro['id_geom_regard_aval']) if key not in geom_point_keys: continue for tid in l_pts_t[(pts[0], pts[1])]: l_t_g[tid] = tro['id'] # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} for tid, pts in lines.items(): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if tid in l_t_g: continue exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope( QgsExpressionContextUtils.layerScope(g_troncon)) exp_str = ('"id_geom_regard_amont" = {} AND ' '"id_geom_regard_aval" = {}').format(pts[0], pts[1]) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression {} has eval error: {}').format( exp.expression(), exp.evalErrorString())) request = QgsFeatureRequest(exp, exp_context) request.setLimit(1) for tro in g_troncon.getFeatures(request): l_t_g[tid] = tro['id'] # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} if not l_t_g.keys(): raise QgsProcessingException( tr('* ERREUR: Aucune géométrie de tronçon')) # Mise a jour de la table troncon exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(context.project())) exp_context.appendScope( QgsExpressionContextUtils.layerScope(t_troncon)) exp_str = ('"id_geom_troncon" IS NULL AND ' 'id IN ({})').format(','.join( [str(i) for i in l_t_g.keys()])) exp = QgsExpression(exp_str) exp.prepare(exp_context) if exp.hasEvalError(): raise QgsProcessingException( tr('* ERROR: Expression %s has eval error: %s').format( exp.expression(), exp.evalErrorString())) # Mise a jour de la table de tronçon request = QgsFeatureRequest(exp, exp_context) t_troncon.startEditing() segment_number = 0 for tro in t_troncon.getFeatures(request): tro.setAttribute('id_geom_troncon', l_t_g[tro['id']]) t_troncon.updateFeature(tro) # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): return {self.SEGMENT_CREATED: None} segment_number += 1 if not t_troncon.commitChanges(): raise QgsProcessingException( tr('* ERROR: Commit %s.') % t_troncon.commitErrors()) # Returns empty dict if no outputs return {self.SEGMENT_CREATED: segment_number}
def expressionBasedUpdate( self, layer, dictProperties, featureId, index=None, value=None ): """ Defines the logic of the expression-based update to be applied. This SLOT listens to featureAdded, geometryChanged, and attributeValueChanged SIGNALS. """ # Check if AutoField is there, otherwise return fieldIndex = layer.fieldNameIndex( dictProperties['field'] ) if fieldIndex == -1: self.msg.show( QApplication.translate( "EventManager", "[Error] Updating AutoField " ) + \ dictProperties['field'] + \ QApplication.translate( "EventManager", " in layer " ) + \ layer.name() + QApplication.translate( "EventManager", " was NOT possible." ) + \ QApplication.translate( "EventManager", " Perhaps you just removed it but haven't saved the changes yet?" ), 'warning' ) return event = "" result = None expression = QgsExpression( dictProperties['expression'] ) if expression.hasParserError(): self.msg.show( QApplication.translate( "EventManager", "[Error] (Parsing) " ) + \ expression.parserErrorString(), 'critical' ) result = NULL # Avoid infinite recursion (changing the same attribute value infinitely). if not index is None: # Filters out the featureAdded SIGNAL if type( index ) == int: # Filters out the geometryChanged SIGNAL if index == fieldIndex: # This call comes from the same AutoField, so return return if self.afm.isFieldAnAutoField( layer, layer.fields()[index].name() ): # Call from AutoField, don't listen # This is to prevent corrupting the layerEditBuffer and being bitten by: # Fatal: ASSERT: "mChangedAttributeValues.isEmpty()" in file /tmp/buildd/qgis-2.14.2+20trusty/src/core/qgsvectorlayereditbuffer.cpp, line 585 return #if type(value)==QPyNullVariant: # Vector layers with numeric field whose value for 1st feature is NULL # trigger an attributeValueChanged SIGNAL when start editing from the # attribute table window. We use this conditional to avoid such SIGNAL. # The ideal case is that such NULL valued SIGNAL shouldn't be emitted by QGIS. # return # While the previous block reduces the number of times attributeValueChanged # is called from the attribute table, it leads to a QGIS bug: # Fatal: ASSERT: "mChangedAttributeValues.isEmpty()" in file /tmp/buildd/qgis-2.14.2+20trusty/src/core/qgsvectorlayereditbuffer.cpp, line 585 # I prefer the attributeValueChanged to be called multiple # times (inefficient) than to open the possibility to a bug. # As soon as QGIS bug #15272 is solved, the number of calls will be reduced! event = "attributeValueChanged" else: event = "geometryChanged" else: event = "featureAdded" feature = layer.getFeatures( QgsFeatureRequest( featureId ) ).next() if result is None: context = QgsExpressionContext() context.appendScope( QgsExpressionContextUtils.globalScope() ) context.appendScope( QgsExpressionContextUtils.projectScope() ) context.appendScope( QgsExpressionContextUtils.layerScope( layer ) ) context.setFields( feature.fields() ) context.setFeature( feature ) if expression.needsGeometry(): if self.iface: # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py da = QgsDistanceArea() da.setSourceCrs( layer.crs().srsid() ) da.setEllipsoidalMode( self.iface.mapCanvas().mapSettings().hasCrsTransformEnabled() ) da.setEllipsoid( QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE )[0] ) expression.setGeomCalculator( da ) if QGis.QGIS_VERSION_INT >= 21400: # Methods added in QGIS 2.14 expression.setDistanceUnits( QgsProject.instance().distanceUnits() ) expression.setAreaUnits( QgsProject.instance().areaUnits() ) expression.prepare( context ) result = expression.evaluate( context ) if expression.hasEvalError(): self.msg.show( QApplication.translate( "EventManager", "[Error] (Evaluating) " ) + \ expression.evalErrorString(), 'critical' ) result = NULL field = layer.fields()[fieldIndex] res = field.convertCompatible( result ) # If result is None, res will be None, but even in that case, QGIS knows # what to do with it while saving, it seems it's treated as NULL. # TODO when bug #15311 is fixed, this block should work better #if dictProperties['expression'] in self.listProviderExpressions: # # Save directly to provider # layer.dataProvider().changeAttributeValues( { featureId : { fieldIndex : res } } ) #else: # Save to layer # layer.changeAttributeValue( featureId, fieldIndex, res ) # Workaround if event == 'featureAdded': # Save directly to the provider layer.dataProvider().changeAttributeValues( { featureId : { fieldIndex : res } } ) else: # Save to layer layer.changeAttributeValue( featureId, fieldIndex, res ) self.msg.show( "[Info] * AutoField's value updated to " + unicode(res) + \ ", (" + layer.name() + "." + dictProperties['field'] + ") by " + event +".", 'info', True )
def photoDetails(self): # Function to deal with photo fields TOMsMessageLog.logMessage("In photoDetails", level=Qgis.Info) FIELD1 = self.ui.findChild(QLabel, "Photo_Widget_01") FIELD2 = self.ui.findChild(QLabel, "Photo_Widget_02") FIELD3 = self.ui.findChild(QLabel, "Photo_Widget_03") path_absolute = QgsExpressionContextUtils.projectScope( QgsProject.instance()).variable('PhotoPath') if path_absolute == None: reply = QMessageBox.information(None, "Information", "Please set value for PhotoPath.", QMessageBox.Ok) return layerName = self.currRestrictionLayer.name() # Generate the full path to the file fileName1 = "Photos_01" fileName2 = "Photos_02" fileName3 = "Photos_03" idx1 = self.currRestrictionLayer.fields().indexFromName(fileName1) idx2 = self.currRestrictionLayer.fields().indexFromName(fileName2) idx3 = self.currRestrictionLayer.fields().indexFromName(fileName3) TOMsMessageLog.logMessage("In photoDetails. idx1: " + str(idx1) + "; " + str(idx2) + "; " + str(idx3), level=Qgis.Info) #if currRestrictionFeature[idx1]: #TOMsMessageLog.logMessage("In photoDetails. photo1: " + str(currRestrictionFeature[idx1]), level=Qgis.Info) #TOMsMessageLog.logMessage("In photoDetails. photo2: " + str(currRestrictionFeature.attribute(idx2)), level=Qgis.Info) #TOMsMessageLog.logMessage("In photoDetails. photo3: " + str(currRestrictionFeature.attribute(idx3)), level=Qgis.Info) if FIELD1: TOMsMessageLog.logMessage("In photoDetails. FIELD 1 exisits", level=Qgis.Info) if self.currRestriction[idx1]: newPhotoFileName1 = os.path.join(path_absolute, self.currRestriction[idx1]) else: newPhotoFileName1 = None TOMsMessageLog.logMessage("In photoDetails. A. Photo1: " + str(newPhotoFileName1), level=Qgis.Info) pixmap1 = QPixmap(newPhotoFileName1) if pixmap1.isNull(): pass # FIELD1.setText('Picture could not be opened ({path})'.format(path=newPhotoFileName1)) else: FIELD1.setPixmap(pixmap1) FIELD1.setScaledContents(True) TOMsMessageLog.logMessage("In photoDetails. Photo1: " + str(newPhotoFileName1), level=Qgis.Info) if FIELD2: TOMsMessageLog.logMessage("In photoDetails. FIELD 2 exisits", level=Qgis.Info) if self.currRestriction[idx2]: newPhotoFileName2 = os.path.join(path_absolute, self.currRestriction[idx2]) else: newPhotoFileName2 = None #newPhotoFileName2 = os.path.join(path_absolute, str(currRestrictionFeature[idx2])) #newPhotoFileName2 = os.path.join(path_absolute, str(currRestrictionFeature.attribute(fileName2))) TOMsMessageLog.logMessage("In photoDetails. A. Photo2: " + str(newPhotoFileName2), level=Qgis.Info) pixmap2 = QPixmap(newPhotoFileName2) if pixmap2.isNull(): pass # FIELD1.setText('Picture could not be opened ({path})'.format(path=newPhotoFileName1)) else: FIELD1.setPixmap(pixmap2) FIELD1.setScaledContents(True) TOMsMessageLog.logMessage("In photoDetails. Photo2: " + str(newPhotoFileName2), level=Qgis.Info) if FIELD3: TOMsMessageLog.logMessage("In photoDetails. FIELD 3 exisits", level=Qgis.Info) if self.currRestriction[idx3]: newPhotoFileName3 = os.path.join(path_absolute, self.currRestriction[idx3]) else: newPhotoFileName3 = None #newPhotoFileName3 = os.path.join(path_absolute, str(currRestrictionFeature[idx3])) #newPhotoFileName3 = os.path.join(path_absolute, # str(currRestrictionFeature.attribute(fileName3))) #newPhotoFileName3 = os.path.join(path_absolute, str(layerName + "_Photos_03")) pixmap3 = QPixmap(newPhotoFileName3) if pixmap3.isNull(): pass # FIELD1.setText('Picture could not be opened ({path})'.format(path=newPhotoFileName1)) else: FIELD1.setPixmap(pixmap3) FIELD1.setScaledContents(True) TOMsMessageLog.logMessage("In photoDetails. Photo3: " + str(newPhotoFileName3), level=Qgis.Info) pass
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) fieldName = self.getParameterValue(self.FIELD_NAME) fieldType = self.TYPES[self.getParameterValue(self.FIELD_TYPE)] width = self.getParameterValue(self.FIELD_LENGTH) precision = self.getParameterValue(self.FIELD_PRECISION) newField = self.getParameterValue(self.NEW_FIELD) formula = self.getParameterValue(self.FORMULA) output = self.getOutputFromName(self.OUTPUT_LAYER) fields = layer.fields() if newField: fields.append(QgsField(fieldName, fieldType, '', width, precision)) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs()) exp = QgsExpression(formula) da = QgsDistanceArea() da.setSourceCrs(layer.crs().srsid()) da.setEllipsoidalMode( iface.mapCanvas().mapSettings().hasCrsTransformEnabled()) da.setEllipsoid(QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE)[0]) exp.setGeomCalculator(da) exp.setDistanceUnits(QgsProject.instance().distanceUnits()) exp.setAreaUnits(QgsProject.instance().areaUnits()) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) if not exp.prepare(exp_context): raise GeoAlgorithmExecutionException( self.tr('Evaluation error: %s' % exp.evalErrorString())) outFeature = QgsFeature() outFeature.initAttributes(len(fields)) outFeature.setFields(fields) error = '' calculationSuccess = True features = vector.features(layer) total = 100.0 / len(features) rownum = 1 for current, f in enumerate(features): rownum = current + 1 exp_context.setFeature(f) exp_context.lastScope().setVariable("row_number", rownum) value = exp.evaluate(exp_context) if exp.hasEvalError(): calculationSuccess = False error = exp.evalErrorString() break else: outFeature.setGeometry(f.geometry()) for fld in f.fields(): outFeature[fld.name()] = f[fld.name()] outFeature[fieldName] = value writer.addFeature(outFeature) progress.setPercentage(int(current * total)) del writer if not calculationSuccess: raise GeoAlgorithmExecutionException( self.tr('An error occurred while evaluating the calculation ' 'string:\n%s' % error))
def expression_eval(expression_text, project_id=None, qgs_layer_id=None, form_data=None, formatter=0): """Evaluates a QgsExpression and returns the result :param expression_text: The QgsExpression text :type expression_text: str :param project_id: ID of the qdjango project, defaults to None :type project_id: int, optional :param qgs_layer_id: ID of the QGIS Layer, defaults to None :type qgslayer_id: str, optional :param form_data: A dictionary that maps to a GeoJSON representation of the feature currently edited in the form :type form_data: dict, optional :param formatter: Indicate if form_data values contains formatter values or original features value. :type formatter: int, optional """ expression = QgsExpression(expression_text) expression_context = QgsExpressionContext() layer = None for func_name in expression.referencedFunctions(): if func_name in FORBIDDEN_FUNCTIONS: raise ExpressionForbiddenError( _('Function "{}" is not allowed for security reasons!').format( func_name)) for var_name in expression.referencedVariables(): if var_name in FORBIDDEN_VARIABLES: raise ExpressionForbiddenError( _('Variable "{}" is not allowed for security reasons!').format( var_name)) if project_id is not None: try: project = Project.objects.get(pk=project_id) if qgs_layer_id is not None: try: layer = project.layer_set.get(qgs_layer_id=qgs_layer_id) except Layer.DoesNotExist: raise ExpressionLayerError( _('QGIS layer with id "{}" could not be found!'). format(qgs_layer_id)) expression_contex = QgsExpressionContextUtils.globalProjectLayerScopes( layer.qgis_layer) else: expression_contex = QgsExpressionContextUtils.globalScope() expression_context.appendScope( QgsExpressionContextUtils.projectScope( project.qgis_project)) except Project.DoesNotExist: raise ExpressionProjectError( _('QDjango project with id "{}" could not be found!').format( project_id)) else: expression_contex = QgsExpressionContextUtils.globalScope() if form_data is not None: if layer is None: raise ExpressionLayerError( _('A valid QGIS layer is required to process form data!')) try: # Case by formatter # formatter == 1 : get featureid from layer, usually must be used with formatter form_data # formatter == 0 : default behavior if formatter == 0: fields = layer.qgis_layer.fields() form_feature = QgsJsonUtils.stringToFeatureList( json.dumps(form_data), fields, None)[0] # Set attributes manually because QgsJsonUtils does not respect order for k, v in form_data['properties'].items(): form_feature.setAttribute(k, v) else: qgis_feature_request = QgsFeatureRequest() exp = expression_from_server_fids( [form_data['id']], layer.qgis_layer.dataProvider()) qgis_feature_request.combineFilterExpression(exp) form_feature = get_qgis_features(layer.qgis_layer, qgis_feature_request)[0] expression_context.appendScope( QgsExpressionContextUtils.formScope(form_feature)) expression_context.setFeature(form_feature) except: raise ExpressionFormDataError() valid, errors = expression.checkExpression(expression_text, expression_context) if not valid: raise ExpressionParseError(errors) result = expression.evaluate(expression_context) if expression.hasEvalError(): raise ExpressionEvalError(expression.evalErrorString()) return result