def __build_data(self): req = QgsFeatureRequest() if self.__filter_expression is not None: req.setFilterExpression(self.__filter_expression) # Get unit of the first feature if needed if self.__uom is not None and self.__uom.startswith("@"): req2 = QgsFeatureRequest(req) req2.setLimit(1) for f in self.__layer.getFeatures(req): self.__uom = f[self.__uom[1:]] break req.setSubsetOfAttributes([self.__x_fieldname, self.__y_fieldname], self.__layer.fields()) # Do not forget to add an index on this field to speed up ordering req.addOrderBy(self.__x_fieldname) xy_values = [ (f[self.__x_fieldname], f[self.__y_fieldname] if f[self.__y_fieldname] is not None else self.__nodata_value) for f in self.__layer.getFeatures(req) ] self.__x_values = [coord[0] for coord in xy_values] self.__y_values = [coord[1] for coord in xy_values] self.__x_min, self.__x_max = (min(self.__x_values), max( self.__x_values)) if self.__x_values else (None, None) self.__y_min, self.__y_max = (min(self.__y_values), max( self.__y_values)) if self.__y_values else (None, None) self.data_modified.emit()
def print_attribute_table(layer, limit=-1): """Print the attribute table in the console. :param layer: The layer to print. :type layer: QgsVectorLayer :param limit: The limit in the query. :type limit: integer """ if layer.wkbType() == QGis.WKBNoGeometry: geometry = False else: geometry = True headers = [] if geometry: headers.append('geom') headers.extend( [f.name() + ' : ' + str(f.type()) for f in layer.fields().toList()]) request = QgsFeatureRequest() request.setLimit(limit) data = [] for feature in layer.getFeatures(request): attributes = [] if geometry: attributes.append(feature.geometry().type()) attributes.extend(feature.attributes()) data.append(attributes) print pretty_table(data, headers)
def print_attribute_table(layer, limit=-1): """Print the attribute table in the console. :param layer: The layer to print. :type layer: QgsVectorLayer :param limit: The limit in the query. :type limit: integer """ if layer.wkbType() in [ QgsWkbTypes.NullGeometry, QgsWkbTypes.UnknownGeometry ]: geometry = False else: geometry = True headers = [] if geometry: headers.append('geom') headers.extend( [f.name() + ' : ' + str(f.type()) for f in layer.fields().toList()]) request = QgsFeatureRequest() request.setLimit(limit) data = [] for feature in layer.getFeatures(request): attributes = [] if geometry: attributes.append(feature.geometry().type()) attributes.extend(feature.attributes()) data.append(attributes) print((pretty_table(data, headers)))
def observation_exists(layer, feature_id) -> Tuple[bool, Optional[QgsFeature]]: """ Check if the given observation exists. """ request = QgsFeatureRequest() request.setLimit(1) request.setSubsetOfAttributes(['id'], layer.fields()) request.setFilterExpression('"id" = {}'.format(feature_id)) join_feature = QgsFeature() if layer.getFeatures(request).nextFeature(join_feature): return True, join_feature return False, None
def layers(self, feature=None): if feature is None: request = QgsFeatureRequest() request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes(["layers"], self._layer.fields()) request.setLimit(1) feature = next(self._layer.getFeatures(request)) value = feature.attribute("layers") if is_null(value) or value == "": return [] return value.split(",")
def district_name_exists(self, district) -> bool: request = QgsFeatureRequest() request.setFilterExpression(QgsExpression.createFieldEqualityExpression(self.title_field, district)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([]) request.setLimit(1) try: next(self.source_layer.getFeatures(request)) except StopIteration: return False return True
def get_estimated_population(self, electorate_id) -> int: """ Returns the estimated (offline) population for the district :param electorate_id: electorate code/id """ # lookup matching feature request = QgsFeatureRequest() request.setFilterExpression(QgsExpression.createFieldEqualityExpression(self.source_field, electorate_id)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([self.estimated_pop_field_index]) request.setLimit(1) f = next(self.source_layer.getFeatures(request)) return f[self.estimated_pop_field_index]
def get_district_type(self, electorate_id) -> str: """ Returns the district type (GN/GS/M) for the specified district :param electorate_id: electorate id """ # lookup matching feature request = QgsFeatureRequest() request.setFilterExpression(QgsExpression.createFieldEqualityExpression(self.source_field, electorate_id)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([self.type_field_index]) request.setLimit(1) f = next(self.source_layer.getFeatures(request)) return f[self.type_field_index]
def insert_scenario(layer: QgsVectorLayer, name: str) -> int: """ Insert the new scenario and get its ID. """ feature = QgsFeature(layer.fields()) feature.setAttribute('nom', name) with edit(layer): layer.addFeature(feature) request = QgsFeatureRequest() request.setLimit(1) request.addOrderBy('id', False) feature = QgsFeature() layer.getFeatures(request).nextFeature(feature) return feature['id']
def get_district_title(self, district): if self.title_field == self.source_field: return super().get_district_title(district) # lookup matching feature request = QgsFeatureRequest() request.setFilterExpression(QgsExpression.createFieldEqualityExpression(self.source_field, district)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([self.title_field_index]) request.setLimit(1) try: f = next(self.source_layer.getFeatures(request)) except StopIteration: return super().get_district_title(district) return f[self.title_field_index]
def get_code_for_electorate(self, electorate_id): """ Returns the electorate code for a given electorate_id :param electorate_id: electorate id """ code_field_index = self.source_layer.fields().lookupField('code') assert code_field_index >= 0 request = QgsFeatureRequest() request.setFilterFid(electorate_id) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([code_field_index]) request.setLimit(1) f = next(self.source_layer.getFeatures(request)) return f[code_field_index]
def get_quota_for_district_type(self, district_type: str) -> int: """ Returns the quota for the specified district type :param district_type: district type, e.g. "GS" """ quota_field_index = self.quota_layer.fields().lookupField('quota') assert quota_field_index >= 0 request = QgsFeatureRequest() request.setFilterExpression(QgsExpression.createFieldEqualityExpression('type', district_type)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([quota_field_index]) request.setLimit(1) f = next(self.quota_layer.getFeatures(request)) return f[quota_field_index]
def feature_exists(layer, habitat_id, pression_id, scenario_id) -> Tuple[bool, Optional[QgsFeature]]: """ Check if the given feature exists. """ request = QgsFeatureRequest() request.setLimit(1) request.setFilterExpression( '"habitat_id" = {habitat} AND "pression_id" = {pression} AND "scenario_id" = {scenario}'.format( habitat=habitat_id, pression=pression_id, scenario=scenario_id, )) feature = QgsFeature() if layer.getFeatures(request).nextFeature(feature): return True, feature return False, None
def get_scenario(self, scenario) -> QgsFeature: """ Returns the feature corresponding to the given scenario :param scenario: scenario id to get feature for """ # lookup matching feature request = QgsFeatureRequest() request.setFilterExpression( QgsExpression.createFieldEqualityExpression( self.id_field, scenario)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setLimit(1) f = next(self.source_layer.getFeatures(request)) return f
def get_stats_nz_calculations(self, electorate_id) -> dict: """ Returns a dictionary of Stats NZ calculations for the district :param electorate_id: electorate code/id """ # lookup matching feature request = QgsFeatureRequest() request.setFilterExpression(QgsExpression.createFieldEqualityExpression(self.source_field, electorate_id)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes( [self.stats_nz_var_23_field_index, self.stats_nz_var_20_field_index, self.stats_nz_pop_field_index]) request.setLimit(1) f = next(self.source_layer.getFeatures(request)) return {'currentPopulation': f[self.stats_nz_pop_field_index], 'varianceYear1': f[self.stats_nz_var_20_field_index], 'varianceYear2': f[self.stats_nz_var_23_field_index]}
def scenario_exists(self, scenario_id) -> bool: """ Returns true if the given scenario exists :param scenario_id: ID for scenario """ request = QgsFeatureRequest() request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([]) request.setFilterExpression( QgsExpression.createFieldEqualityExpression( self.id_field, scenario_id)) request.setLimit(1) for f in self.source_layer.getFeatures(request): # pylint: disable=unused-variable # found a matching feature return True return False
def get_scenario_name(self, scenario) -> str: """ Returns a user-friendly name corresponding to the given scenario :param scenario: scenario id to get name for """ # lookup matching feature request = QgsFeatureRequest() request.setFilterExpression( QgsExpression.createFieldEqualityExpression( self.id_field, scenario)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([self.name_field_index]) request.setLimit(1) f = next(self.source_layer.getFeatures(request)) return f[self.name_field_index]
def scenario_name_exists(self, new_scenario_name: str) -> bool: """ Returns true if the given scenario name already exists :param new_scenario_name: name of scenario to test """ request = QgsFeatureRequest() request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([]) request.setFilterExpression( QgsExpression.createFieldEqualityExpression( self.name_field, new_scenario_name)) request.setLimit(1) for f in self.source_layer.getFeatures(request): # pylint: disable=unused-variable # found a matching feature return True return False
def runGetFeatureTests(self, source): FeatureSourceTestCase.runGetFeatureTests(self, source) # combination of an uncompilable expression and limit feature = next(self.vl.getFeatures('pk=4')) context = QgsExpressionContext() scope = QgsExpressionContextScope() scope.setVariable('parent', feature) context.appendScope(scope) request = QgsFeatureRequest() request.setExpressionContext(context) request.setFilterExpression('"pk" = attribute(@parent, \'pk\')') request.setLimit(1) values = [f['pk'] for f in self.vl.getFeatures(request)] self.assertEqual(values, [4])
def flag_stats_nz_updating(self, electorate_id): """ Flags an electorate's Statistics NZ api calculations as being currently updated :param electorate_id: electorate to update """ # get feature ID request = QgsFeatureRequest() request.setFilterExpression(QgsExpression.createFieldEqualityExpression(self.source_field, electorate_id)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([]) request.setLimit(1) f = next(self.source_layer.getFeatures(request)) self.source_layer.dataProvider().changeAttributeValues({f.id(): {self.stats_nz_pop_field_index: -1, self.stats_nz_var_20_field_index: NULL, self.stats_nz_var_23_field_index: NULL}})
def __build_data(self): req = QgsFeatureRequest() if self.__filter_expression is not None: req.setFilterExpression(self.__filter_expression) # Get unit of the first feature if needed if self.__uom is not None and self.__uom.startswith("@"): request_unit = QgsFeatureRequest(req) request_unit.setLimit(1) for f in self.__layer.getFeatures(request_unit): self.__uom = f[self.__uom[1:]] break req.setSubsetOfAttributes([self.__x_fieldname, self.__y_fieldname], self.__layer.fields()) # Do not forget to add an index on this field to speed up ordering req.addOrderBy(self.__x_fieldname) def is_null(v): return isinstance(v, QVariant) and v.isNull() if self.__nodata_value is not None: # replace null values by a 'Nodata' value xy_values = [ (f[self.__x_fieldname], f[self.__y_fieldname] if not is_null(f[self.__y_fieldname]) else self.__nodata_value) for f in self.__layer.getFeatures(req) ] else: # do not include null values xy_values = [(f[self.__x_fieldname], f[self.__y_fieldname]) for f in self.__layer.getFeatures(req) if not is_null(f[self.__y_fieldname])] self.__x_values = [coord[0] for coord in xy_values] self.__y_values = [coord[1] for coord in xy_values] self.__x_min, self.__x_max = (min(self.__x_values), max( self.__x_values)) if self.__x_values else (None, None) self.__y_min, self.__y_max = (min(self.__y_values), max( self.__y_values)) if self.__y_values else (None, None) self.data_modified.emit()
def update_stats_nz_values(self, electorate_id, results: dict): """ Updates an electorate's stored Statistics NZ api calculations :param electorate_id: electorate to update :param results: results dictionary from stats API """ # get feature ID request = QgsFeatureRequest() request.setFilterExpression(QgsExpression.createFieldEqualityExpression(self.source_field, electorate_id)) request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([]) request.setLimit(1) f = next(self.source_layer.getFeatures(request)) self.source_layer.dataProvider().changeAttributeValues( {f.id(): {self.stats_nz_pop_field_index: results['currentPopulation'], self.stats_nz_var_20_field_index: results['varianceYear1'], self.stats_nz_var_23_field_index: results['varianceYear2']}})
def search_data_source(self, search_expression, sort_map): """ Searches the data source using the specified search expression. :param search_expression: Search expression either as a string or instance of QgsExpression. :type search_expression: str or QgsExpression :param sort_map: List containing a definition of column sorting. :type sort_map: list :return: Returns a list containing search results consisting of QgsFeature objects. :rtype: list """ results = [] if not self._vector_layer.isValid(): raise FltsSearchException( 'Search cannot be performed, data source is invalid.') if isinstance(search_expression, basestring): search_expression = QgsExpression(search_expression) # Assert if there are errors in the expression if search_expression.hasParserError(): raise FltsSearchException(search_expression.parserErrorString()) fr = QgsFeatureRequest(search_expression) if not self._config.limit: limit = -1 else: limit = self._config.limit fr.setLimit(limit) # Set sorting if specified. if sort_map: for s in sort_map: ascending = True if s[1] == 0 else False fr.addOrderBy(s[0], ascending) feat_iter = self._vector_layer.getFeatures(fr) for f in feat_iter: results.append(f) return results
def limit_features(self, new_feature): feature_count = self.pr.featureCount() if feature_count < self.limit: self.pr.addFeatures([new_feature]) progress = (feature_count * 100) / self.limit self.dlg.streamingPb.setValue(progress) else: self.dlg.streamingPb.setRange(0, 0) feats_request = QgsFeatureRequest() feats_request.addOrderBy('time', ascending=False) feats_request.setLimit(2000) features_iterator = self.pr.getFeatures(feats_request) if not features_iterator.isValid(): return last_feature = next( itertools.islice(features_iterator, feature_count - 1, feature_count)) last_feature_id = last_feature.id() self.startEditing() self.deleteFeature(last_feature_id) self.pr.addFeatures([new_feature])
def search_gpkg(search_text, search_field, echo_search_column, display_fields, extra_expr_columns, layer, limit): wildcarded_search_string = '' for part in search_text.split(): wildcarded_search_string += '%' + part wildcarded_search_string += '%' expr_str = "{0} ILIKE '{1}'".format(search_field, wildcarded_search_string) expr = QgsExpression(expr_str) req = QgsFeatureRequest(expr) limit = limit if is_number(limit) else None if limit: req.setLimit(int(limit)) it = layer.getFeatures(req) result = [] for f in it: feature_info = [] geom = f.geometry().asWkt() epsg = layer.crs().authid() feature_info.append(geom) feature_info.append(epsg) available_fields = [field.name() for field in f.fields()] display_info = [] if echo_search_column: display_info.append(str(f[search_field])) for field_name in display_fields: if f[field_name]: display_info.append(str(f[field_name])) feature_info.append(", ".join(display_info)) for field_name in extra_expr_columns: if field_name in available_fields: feature_info.append(f[field_name]) else: feature_info.append("") result.append(feature_info) return result
def create_widget(self): request = QgsFeatureRequest() request.setLimit(1) feature = next(self.layer.getFeatures(request)) section = PreCourlisFileLine(self.layer).section_from_feature(feature) section.feature = feature widget = GraphWidget(None) model = PointsTableModel(widget) model.set_section(section) sel_model = QtCore.QItemSelectionModel(model, widget) widget.set_selection_model(sel_model) widget.set_sections( layer=self.layer, feature=feature, previous_section=None, current_section=section, next_section=None, ) return widget
def count_qgis_features(qgis_layer, qgis_feature_request=None, bbox_filter=None, attribute_filters=None, search_filter=None, extra_expression=None, extra_subset_string=None, **kwargs): """Returns a list of QgsFeatures from the QGIS vector layer, with optional filter options. The API can be used in two distinct ways (that are not mutually exclusive): 1. pass in a pre-configured QgsFeatureRequest instance 2. pass a series of filter attributes and let this method configure the QgsFeatureRequest. :param qgis_layer: the QGIS vector layer instance :type qgis_layer: QgsVectorLayer :param qgis_feature_request: the QGIS feature request :type qgis_feature_request: QgsFeatureRequest, optional :param bbox_filter: BBOX filter in layer's CRS, defaults to None :type bbox_filter: QgsRectangle, optional :param attribute_filters: dictionary of attribute filters combined with AND, defaults to None :type attribute_filters: dict, optional :param search_filter: string filter for all fields :type search_filter: str, optional :param: exclude_fields: list of fields to exclude from returned data, '__all__' for no attributes :param: extra_expression: extra expression for filtering features :type: extra_expression: str, optional :param: extra_subset_string: extra subset string (provider side WHERE condition) for filtering features :type: extra_subset_string: str, optional :return: list of features :rtype: QgsFeature list """ # Remove no_filters condition because featureCount() # is cached, so it could fail on multi-processes deploy # ------------------------------------------------------ # Fast track for no filters # no_filters = (attribute_filters is None # and (bbox_filter is None or bbox_filter.isEmpty()) and # attribute_filters is None and # extra_expression is None and # extra_subset_string is None) # # if qgis_feature_request is not None: # no_filters = (no_filters and # qgis_feature_request.filterRect().isEmpty() and # qgis_feature_request.filterType() == QgsFeatureRequest.FilterNone) # else: if not qgis_feature_request: qgis_feature_request = QgsFeatureRequest() # if no_filters: # # Try to patch a possible Oracle views QGIS featureCount bug. # qgs_fc = qgis_layer.featureCount() # if qgs_fc != -1: # return qgis_layer.featureCount() qgis_feature_request.setNoAttributes() if qgis_feature_request.limit() != -1: qgis_feature_request = QgsFeatureRequest(qgis_feature_request) qgis_feature_request.setLimit(-1) return len( __get_qgis_features( qgis_layer, qgis_feature_request, bbox_filter, attribute_filters, search_filter, False, #with_geometry, None, #page, None, #page_size, None, #ordering, None, #exclude_fields, extra_expression, extra_subset_string))
def runGetFeatureTests(self, provider): assert len([f for f in provider.getFeatures()]) == 5 self.assert_query(provider, 'name ILIKE \'QGIS\'', []) self.assert_query(provider, '"name" IS NULL', [5]) self.assert_query(provider, '"name" IS NOT NULL', [1, 2, 3, 4]) self.assert_query(provider, '"name" NOT LIKE \'Ap%\'', [1, 3, 4]) self.assert_query(provider, '"name" NOT ILIKE \'QGIS\'', [1, 2, 3, 4]) self.assert_query(provider, '"name" NOT ILIKE \'pEAR\'', [1, 2, 4]) self.assert_query(provider, 'name = \'Apple\'', [2]) self.assert_query(provider, 'name <> \'Apple\'', [1, 3, 4]) self.assert_query(provider, 'name = \'apple\'', []) self.assert_query(provider, '"name" <> \'apple\'', [1, 2, 3, 4]) self.assert_query(provider, '(name = \'Apple\') is not null', [1, 2, 3, 4]) self.assert_query(provider, 'name LIKE \'Apple\'', [2]) self.assert_query(provider, 'name LIKE \'aPple\'', []) self.assert_query(provider, 'name ILIKE \'aPple\'', [2]) self.assert_query(provider, 'name ILIKE \'%pp%\'', [2]) self.assert_query(provider, 'cnt > 0', [1, 2, 3, 4]) self.assert_query(provider, '-cnt > 0', [5]) self.assert_query(provider, 'cnt < 0', [5]) self.assert_query(provider, '-cnt < 0', [1, 2, 3, 4]) self.assert_query(provider, 'cnt >= 100', [1, 2, 3, 4]) self.assert_query(provider, 'cnt <= 100', [1, 5]) self.assert_query(provider, 'pk IN (1, 2, 4, 8)', [1, 2, 4]) self.assert_query(provider, 'cnt = 50 * 2', [1]) self.assert_query(provider, 'cnt = 150 / 1.5', [1]) self.assert_query(provider, 'cnt = 1000 / 10', [1]) self.assert_query(provider, 'cnt = 1000/11+10', []) # checks that provider isn't rounding int/int self.assert_query(provider, 'pk = 9 // 4', [2]) # int division self.assert_query(provider, 'cnt = 99 + 1', [1]) self.assert_query(provider, 'cnt = 101 - 1', [1]) self.assert_query(provider, 'cnt - 1 = 99', [1]) self.assert_query(provider, '-cnt - 1 = -101', [1]) self.assert_query(provider, '-(-cnt) = 100', [1]) self.assert_query(provider, '-(cnt) = -(100)', [1]) self.assert_query(provider, 'cnt + 1 = 101', [1]) self.assert_query(provider, 'cnt = 1100 % 1000', [1]) self.assert_query(provider, '"name" || \' \' || "name" = \'Orange Orange\'', [1]) self.assert_query(provider, '"name" || \' \' || "cnt" = \'Orange 100\'', [1]) self.assert_query(provider, '\'x\' || "name" IS NOT NULL', [1, 2, 3, 4]) self.assert_query(provider, '\'x\' || "name" IS NULL', [5]) self.assert_query(provider, 'cnt = 10 ^ 2', [1]) self.assert_query(provider, '"name" ~ \'[OP]ra[gne]+\'', [1]) self.assert_query(provider, '"name"="name2"', [2, 4]) # mix of matched and non-matched case sensitive names self.assert_query(provider, 'true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'false', []) # Three value logic self.assert_query(provider, 'false and false', []) self.assert_query(provider, 'false and true', []) self.assert_query(provider, 'false and NULL', []) self.assert_query(provider, 'true and false', []) self.assert_query(provider, 'true and true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'true and NULL', []) self.assert_query(provider, 'NULL and false', []) self.assert_query(provider, 'NULL and true', []) self.assert_query(provider, 'NULL and NULL', []) self.assert_query(provider, 'false or false', []) self.assert_query(provider, 'false or true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'false or NULL', []) self.assert_query(provider, 'true or false', [1, 2, 3, 4, 5]) self.assert_query(provider, 'true or true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'true or NULL', [1, 2, 3, 4, 5]) self.assert_query(provider, 'NULL or false', []) self.assert_query(provider, 'NULL or true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'NULL or NULL', []) self.assert_query(provider, 'not true', []) self.assert_query(provider, 'not false', [1, 2, 3, 4, 5]) self.assert_query(provider, 'not null', []) # not self.assert_query(provider, 'not name = \'Apple\'', [1, 3, 4]) self.assert_query(provider, 'not name IS NULL', [1, 2, 3, 4]) self.assert_query(provider, 'not name = \'Apple\' or name = \'Apple\'', [1, 2, 3, 4]) self.assert_query(provider, 'not name = \'Apple\' or not name = \'Apple\'', [1, 3, 4]) self.assert_query(provider, 'not name = \'Apple\' and pk = 4', [4]) self.assert_query(provider, 'not name = \'Apple\' and not pk = 4', [1, 3]) self.assert_query(provider, 'not pk IN (1, 2, 4, 8)', [3, 5]) # type conversion - QGIS expressions do not mind that we are comparing a string # against numeric literals self.assert_query(provider, 'num_char IN (2, 4, 5)', [2, 4, 5]) #function self.assert_query(provider, 'sqrt(pk) >= 2', [4, 5]) self.assert_query(provider, 'radians(cnt) < 2', [1, 5]) self.assert_query(provider, 'degrees(pk) <= 200', [1, 2, 3]) self.assert_query(provider, 'abs(cnt) <= 200', [1, 2, 5]) self.assert_query(provider, 'cos(pk) < 0', [2, 3, 4]) self.assert_query(provider, 'sin(pk) < 0', [4, 5]) self.assert_query(provider, 'tan(pk) < 0', [2, 3, 5]) self.assert_query(provider, 'acos(-1) < pk', [4, 5]) self.assert_query(provider, 'asin(1) < pk', [2, 3, 4, 5]) self.assert_query(provider, 'atan(3.14) < pk', [2, 3, 4, 5]) self.assert_query(provider, 'atan2(3.14, pk) < 1', [3, 4, 5]) self.assert_query(provider, 'exp(pk) < 10', [1, 2]) self.assert_query(provider, 'ln(pk) <= 1', [1, 2]) self.assert_query(provider, 'log(3, pk) <= 1', [1, 2, 3]) self.assert_query(provider, 'log10(pk) < 0.5', [1, 2, 3]) self.assert_query(provider, 'round(3.14) <= pk', [3, 4, 5]) self.assert_query(provider, 'round(0.314,1) * 10 = pk', [3]) self.assert_query(provider, 'floor(3.14) <= pk', [3, 4, 5]) self.assert_query(provider, 'ceil(3.14) <= pk', [4, 5]) self.assert_query(provider, 'pk < pi()', [1, 2, 3]) self.assert_query(provider, 'round(cnt / 66.67) <= 2', [1, 5]) self.assert_query(provider, 'floor(cnt / 66.67) <= 2', [1, 2, 5]) self.assert_query(provider, 'ceil(cnt / 66.67) <= 2', [1, 5]) self.assert_query(provider, 'pk < pi() / 2', [1]) self.assert_query(provider, 'pk = char(51)', [3]) self.assert_query(provider, 'pk = coalesce(NULL,3,4)', [3]) self.assert_query(provider, 'lower(name) = \'apple\'', [2]) self.assert_query(provider, 'upper(name) = \'APPLE\'', [2]) self.assert_query(provider, 'name = trim(\' Apple \')', [2]) # geometry # azimuth and touches tests are deactivated because they do not pass for WFS provider #self.assert_query(provider, 'azimuth($geometry,geom_from_wkt( \'Point (-70 70)\')) < pi()', [1, 5]) self.assert_query(provider, 'x($geometry) < -70', [1, 5]) self.assert_query(provider, 'y($geometry) > 70', [2, 4, 5]) self.assert_query(provider, 'xmin($geometry) < -70', [1, 5]) self.assert_query(provider, 'ymin($geometry) > 70', [2, 4, 5]) self.assert_query(provider, 'xmax($geometry) < -70', [1, 5]) self.assert_query(provider, 'ymax($geometry) > 70', [2, 4, 5]) self.assert_query(provider, 'disjoint($geometry,geom_from_wkt( \'Polygon ((-72.2 66.1, -65.2 66.1, -65.2 72.0, -72.2 72.0, -72.2 66.1))\'))', [4, 5]) self.assert_query(provider, 'intersects($geometry,geom_from_wkt( \'Polygon ((-72.2 66.1, -65.2 66.1, -65.2 72.0, -72.2 72.0, -72.2 66.1))\'))', [1, 2]) #self.assert_query(provider, 'touches($geometry,geom_from_wkt( \'Polygon ((-70.332 66.33, -65.32 66.33, -65.32 78.3, -70.332 78.3, -70.332 66.33))\'))', [1, 4]) self.assert_query(provider, 'contains(geom_from_wkt( \'Polygon ((-72.2 66.1, -65.2 66.1, -65.2 72.0, -72.2 72.0, -72.2 66.1))\'),$geometry)', [1, 2]) self.assert_query(provider, 'distance($geometry,geom_from_wkt( \'Point (-70 70)\')) > 7', [4, 5]) self.assert_query(provider, 'intersects($geometry,geom_from_gml( \'<gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-72.2,66.1 -65.2,66.1 -65.2,72.0 -72.2,72.0 -72.2,66.1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>\'))', [1, 2]) # combination of an uncompilable expression and limit feature = next(self.vl.getFeatures('pk=4')) context = QgsExpressionContext() scope = QgsExpressionContextScope() scope.setVariable('parent', feature) context.appendScope(scope) request = QgsFeatureRequest() request.setExpressionContext(context) request.setFilterExpression('"pk" = attribute(@parent, \'pk\')') request.setLimit(1) values = [f['pk'] for f in self.vl.getFeatures(request)] self.assertEqual(values, [4])
def runGetFeatureTests(self, provider): assert len([f for f in provider.getFeatures()]) == 5 self.assert_query(provider, 'name ILIKE \'QGIS\'', []) self.assert_query(provider, '"name" IS NULL', [5]) self.assert_query(provider, '"name" IS NOT NULL', [1, 2, 3, 4]) self.assert_query(provider, '"name" NOT LIKE \'Ap%\'', [1, 3, 4]) self.assert_query(provider, '"name" NOT ILIKE \'QGIS\'', [1, 2, 3, 4]) self.assert_query(provider, '"name" NOT ILIKE \'pEAR\'', [1, 2, 4]) self.assert_query(provider, 'name = \'Apple\'', [2]) self.assert_query(provider, 'name <> \'Apple\'', [1, 3, 4]) self.assert_query(provider, 'name = \'apple\'', []) self.assert_query(provider, '"name" <> \'apple\'', [1, 2, 3, 4]) self.assert_query(provider, '(name = \'Apple\') is not null', [1, 2, 3, 4]) self.assert_query(provider, 'name LIKE \'Apple\'', [2]) self.assert_query(provider, 'name LIKE \'aPple\'', []) self.assert_query(provider, 'name ILIKE \'aPple\'', [2]) self.assert_query(provider, 'name ILIKE \'%pp%\'', [2]) self.assert_query(provider, 'cnt > 0', [1, 2, 3, 4]) self.assert_query(provider, '-cnt > 0', [5]) self.assert_query(provider, 'cnt < 0', [5]) self.assert_query(provider, '-cnt < 0', [1, 2, 3, 4]) self.assert_query(provider, 'cnt >= 100', [1, 2, 3, 4]) self.assert_query(provider, 'cnt <= 100', [1, 5]) self.assert_query(provider, 'pk IN (1, 2, 4, 8)', [1, 2, 4]) self.assert_query(provider, 'cnt = 50 * 2', [1]) self.assert_query(provider, 'cnt = 99 + 1', [1]) self.assert_query(provider, 'cnt = 101 - 1', [1]) self.assert_query(provider, 'cnt - 1 = 99', [1]) self.assert_query(provider, '-cnt - 1 = -101', [1]) self.assert_query(provider, '-(-cnt) = 100', [1]) self.assert_query(provider, '-(cnt) = -(100)', [1]) self.assert_query(provider, 'cnt + 1 = 101', [1]) self.assert_query(provider, 'cnt = 1100 % 1000', [1]) self.assert_query(provider, '"name" || \' \' || "name" = \'Orange Orange\'', [1]) self.assert_query(provider, '"name" || \' \' || "cnt" = \'Orange 100\'', [1]) self.assert_query(provider, '\'x\' || "name" IS NOT NULL', [1, 2, 3, 4]) self.assert_query(provider, '\'x\' || "name" IS NULL', [5]) self.assert_query(provider, 'cnt = 10 ^ 2', [1]) self.assert_query(provider, '"name" ~ \'[OP]ra[gne]+\'', [1]) self.assert_query( provider, '"name"="name2"', [2, 4]) # mix of matched and non-matched case sensitive names self.assert_query(provider, 'true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'false', []) # Three value logic self.assert_query(provider, 'false and false', []) self.assert_query(provider, 'false and true', []) self.assert_query(provider, 'false and NULL', []) self.assert_query(provider, 'true and false', []) self.assert_query(provider, 'true and true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'true and NULL', []) self.assert_query(provider, 'NULL and false', []) self.assert_query(provider, 'NULL and true', []) self.assert_query(provider, 'NULL and NULL', []) self.assert_query(provider, 'false or false', []) self.assert_query(provider, 'false or true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'false or NULL', []) self.assert_query(provider, 'true or false', [1, 2, 3, 4, 5]) self.assert_query(provider, 'true or true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'true or NULL', [1, 2, 3, 4, 5]) self.assert_query(provider, 'NULL or false', []) self.assert_query(provider, 'NULL or true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'NULL or NULL', []) self.assert_query(provider, 'not true', []) self.assert_query(provider, 'not false', [1, 2, 3, 4, 5]) self.assert_query(provider, 'not null', []) # not self.assert_query(provider, 'not name = \'Apple\'', [1, 3, 4]) self.assert_query(provider, 'not name IS NULL', [1, 2, 3, 4]) self.assert_query(provider, 'not name = \'Apple\' or name = \'Apple\'', [1, 2, 3, 4]) self.assert_query(provider, 'not name = \'Apple\' or not name = \'Apple\'', [1, 3, 4]) self.assert_query(provider, 'not name = \'Apple\' and pk = 4', [4]) self.assert_query(provider, 'not name = \'Apple\' and not pk = 4', [1, 3]) self.assert_query(provider, 'not pk IN (1, 2, 4, 8)', [3, 5]) # type conversion - QGIS expressions do not mind that we are comparing a string # against numeric literals self.assert_query(provider, 'num_char IN (2, 4, 5)', [2, 4, 5]) # geometry self.assert_query( provider, 'intersects($geometry,geom_from_wkt( \'Polygon ((-72.2 66.1, -65.2 66.1, -65.2 72.0, -72.2 72.0, -72.2 66.1))\'))', [1, 2]) # combination of an uncompilable expression and limit feature = next(self.vl.getFeatures('pk=4')) context = QgsExpressionContext() scope = QgsExpressionContextScope() scope.setVariable('parent', feature) context.appendScope(scope) request = QgsFeatureRequest() request.setExpressionContext(context) request.setFilterExpression('"pk" = attribute(@parent, \'pk\')') request.setLimit(1) values = [f['pk'] for f in self.vl.getFeatures(request)] self.assertEqual(values, [4])
def runGetFeatureTests(self, provider): assert len([f for f in provider.getFeatures()]) == 5 self.assert_query(provider, 'name ILIKE \'QGIS\'', []) self.assert_query(provider, '"name" IS NULL', [5]) self.assert_query(provider, '"name" IS NOT NULL', [1, 2, 3, 4]) self.assert_query(provider, '"name" NOT LIKE \'Ap%\'', [1, 3, 4]) self.assert_query(provider, '"name" NOT ILIKE \'QGIS\'', [1, 2, 3, 4]) self.assert_query(provider, '"name" NOT ILIKE \'pEAR\'', [1, 2, 4]) self.assert_query(provider, 'name = \'Apple\'', [2]) self.assert_query(provider, 'name <> \'Apple\'', [1, 3, 4]) self.assert_query(provider, 'name = \'apple\'', []) self.assert_query(provider, '"name" <> \'apple\'', [1, 2, 3, 4]) self.assert_query(provider, '(name = \'Apple\') is not null', [1, 2, 3, 4]) self.assert_query(provider, 'name LIKE \'Apple\'', [2]) self.assert_query(provider, 'name LIKE \'aPple\'', []) self.assert_query(provider, 'name ILIKE \'aPple\'', [2]) self.assert_query(provider, 'name ILIKE \'%pp%\'', [2]) self.assert_query(provider, 'cnt > 0', [1, 2, 3, 4]) self.assert_query(provider, '-cnt > 0', [5]) self.assert_query(provider, 'cnt < 0', [5]) self.assert_query(provider, '-cnt < 0', [1, 2, 3, 4]) self.assert_query(provider, 'cnt >= 100', [1, 2, 3, 4]) self.assert_query(provider, 'cnt <= 100', [1, 5]) self.assert_query(provider, 'pk IN (1, 2, 4, 8)', [1, 2, 4]) self.assert_query(provider, 'cnt = 50 * 2', [1]) self.assert_query(provider, 'cnt = 99 + 1', [1]) self.assert_query(provider, 'cnt = 101 - 1', [1]) self.assert_query(provider, 'cnt - 1 = 99', [1]) self.assert_query(provider, '-cnt - 1 = -101', [1]) self.assert_query(provider, '-(-cnt) = 100', [1]) self.assert_query(provider, '-(cnt) = -(100)', [1]) self.assert_query(provider, 'cnt + 1 = 101', [1]) self.assert_query(provider, 'cnt = 1100 % 1000', [1]) self.assert_query(provider, '"name" || \' \' || "name" = \'Orange Orange\'', [1]) self.assert_query(provider, '"name" || \' \' || "cnt" = \'Orange 100\'', [1]) self.assert_query(provider, '\'x\' || "name" IS NOT NULL', [1, 2, 3, 4]) self.assert_query(provider, '\'x\' || "name" IS NULL', [5]) self.assert_query(provider, 'cnt = 10 ^ 2', [1]) self.assert_query(provider, '"name" ~ \'[OP]ra[gne]+\'', [1]) self.assert_query(provider, '"name"="name2"', [2, 4]) # mix of matched and non-matched case sensitive names self.assert_query(provider, 'true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'false', []) # Three value logic self.assert_query(provider, 'false and false', []) self.assert_query(provider, 'false and true', []) self.assert_query(provider, 'false and NULL', []) self.assert_query(provider, 'true and false', []) self.assert_query(provider, 'true and true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'true and NULL', []) self.assert_query(provider, 'NULL and false', []) self.assert_query(provider, 'NULL and true', []) self.assert_query(provider, 'NULL and NULL', []) self.assert_query(provider, 'false or false', []) self.assert_query(provider, 'false or true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'false or NULL', []) self.assert_query(provider, 'true or false', [1, 2, 3, 4, 5]) self.assert_query(provider, 'true or true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'true or NULL', [1, 2, 3, 4, 5]) self.assert_query(provider, 'NULL or false', []) self.assert_query(provider, 'NULL or true', [1, 2, 3, 4, 5]) self.assert_query(provider, 'NULL or NULL', []) self.assert_query(provider, 'not true', []) self.assert_query(provider, 'not false', [1, 2, 3, 4, 5]) self.assert_query(provider, 'not null', []) # not self.assert_query(provider, 'not name = \'Apple\'', [1, 3, 4]) self.assert_query(provider, 'not name IS NULL', [1, 2, 3, 4]) self.assert_query(provider, 'not name = \'Apple\' or name = \'Apple\'', [1, 2, 3, 4]) self.assert_query(provider, 'not name = \'Apple\' or not name = \'Apple\'', [1, 3, 4]) self.assert_query(provider, 'not name = \'Apple\' and pk = 4', [4]) self.assert_query(provider, 'not name = \'Apple\' and not pk = 4', [1, 3]) self.assert_query(provider, 'not pk IN (1, 2, 4, 8)', [3, 5]) # type conversion - QGIS expressions do not mind that we are comparing a string # against numeric literals self.assert_query(provider, 'num_char IN (2, 4, 5)', [2, 4, 5]) # geometry self.assert_query(provider, 'intersects($geometry,geom_from_wkt( \'Polygon ((-72.2 66.1, -65.2 66.1, -65.2 72.0, -72.2 72.0, -72.2 66.1))\'))', [1, 2]) # combination of an uncompilable expression and limit feature = next(self.vl.getFeatures('pk=4')) context = QgsExpressionContext() scope = QgsExpressionContextScope() scope.setVariable('parent', feature) context.appendScope(scope) request = QgsFeatureRequest() request.setExpressionContext(context) request.setFilterExpression('"pk" = attribute(@parent, \'pk\')') request.setLimit(1) values = [f['pk'] for f in self.vl.getFeatures(request)] self.assertEqual(values, [4])
def testLimit(self): req = QgsFeatureRequest() self.assertEqual(req.limit(), -1) req.setLimit(6) self.assertEqual(req.limit(), 6)
def responseComplete(self): """ Send new response """ self.handler = self.serverIface.requestHandler() params = self.handler.parameterMap() # Check if needed params are passed # If not, do not change QGIS Server response service = params.get('SERVICE') if not service: return if service.lower() != 'wms': return # Check if getprintatlas request. If not, just send the response if 'REQUEST' not in params or params['REQUEST'].lower() not in ['getprintatlas', 'getcapabilitiesatlas']: return # Get capabilities if params['REQUEST'].lower() == 'getcapabilitiesatlas': body = { 'status': 'success', 'metadata': self.metadata } self.setJsonResponse('200', body) return # Check if needed params are set required = ['TEMPLATE', 'EXP_FILTER'] if not all(elem in params for elem in required): body = { 'status': 'fail', 'message': 'Missing parameters: {} are required.'.format(' '.join(required)) } self.setJsonResponse('400', body) return self.project_path = self.serverInterface().configFilePath() self.composer_name = params['TEMPLATE'] self.feature_filter = params['EXP_FILTER'] # check expression expression = QgsExpression(self.feature_filter) if not expression.hasParserError(): feature_request = QgsFeatureRequest(expression) feature_request.setLimit(1) else: body = { 'status': 'fail', 'message': 'An error occurred while parsing the given expression: %s' % expression.parserErrorString() } QgsMessageLog.logMessage('ATLAS - ERROR EXPRESSION: {}'.format(expression.parserErrorString()), 'atlasprint', Qgis.Critical) self.setJsonResponse('400', body) return # noinspection PyBroadException try: pdf = self.print_atlas( project_path=self.project_path, composer_name=self.composer_name, predefined_scales=self.predefined_scales, feature_filter=self.feature_filter ) except Exception: pdf = None if not pdf: body = { 'status': 'fail', 'message': 'ATLAS - Error while generating the PDF' } QgsMessageLog.logMessage("ATLAS - No PDF generated in %s" % pdf, 'atlasprint', Qgis.Critical) self.setJsonResponse('500', body) return # Send PDF self.handler.clear() self.handler.setResponseHeader('Content-type', 'application/pdf') self.handler.setResponseHeader('Status', '200') # noinspection PyBroadException try: with open(pdf, 'rb') as f: loads = f.readlines() ba = QByteArray(b''.join(loads)) self.handler.appendBody(ba) except Exception: body = { 'status': 'fail', 'message': 'Error occured while reading PDF file', } self.setJsonResponse('500', body) finally: os.remove(pdf) return
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}