def getExtentForLocate(self, sourceRow): surfaceLayers = QgisHelper.getSurfaceLayers(self.surfaceType) rect = QgsRectangle() rect.setMinimal() for sfLayer in surfaceLayers: rect.combineExtentWith(sfLayer.extent()) return rect
def groupify(self): with self.groupAssignmentLock: self.layersToBeGrouped = len(self.layerList) self.getGeneratedGroup() registryAddedLayers = QgsProject.instance().addMapLayers( self.layerList, False) for item in registryAddedLayers: if item not in self.layerList: #print("****WARNING: A LAYER WAS NOT ADDED TO THE REGISTRY: "+str(item)+" --- ID : "+item.id()) self.errorCount = self.errorCount + 1 pass self.correctlyRegisteredLayers = sorted( self.layerList, key=lambda layer: layer.name()) for layer in self.correctlyRegisteredLayers: self.generatedGroup.addLayer(layer) #iface.legendInterface().setLayerVisible(layer, False) QgsProject.instance().layerTreeRoot().findLayer( layer.id()).setItemVisibilityChecked(True) #equally on play. extent = QgsRectangle() extent.setMinimal() for child in self.generatedGroup.children(): if isinstance(child, QgsLayerTreeLayer): extent.combineExtentWith(child.layer().extent()) iface.mapCanvas().setExtent(extent) iface.mapCanvas().refresh() if self.errorCount > 0: self.errorsFound.emit(self.errorCount)
def zoom_to_group(self, group_name, buffer=10): """ Make zoom to extent of the received group :param group_name: Group name where to zoom :param buffer: Space left between the group zoom and the canvas (integer) :return: False if don't find the group """ extent = QgsRectangle() extent.setMinimal() # Iterate through layers from certain group and combine their extent root = QgsProject.instance().layerTreeRoot() group = root.findGroup( group_name) # Adjust this to fit your group's name if not group: return False for child in group.children(): if isinstance(child, QgsLayerTreeLayer): extent.combineExtentWith(child.layer().extent()) xmax = extent.xMaximum() + buffer xmin = extent.xMinimum() - buffer ymax = extent.yMaximum() + buffer ymin = extent.yMinimum() - buffer extent.set(xmin, ymin, xmax, ymax) self.iface.mapCanvas().setExtent(extent) self.iface.mapCanvas().refresh()
def addResultToLayer(self, layer, result, lyrDefault, mode): if len(result) > 0: layer.startEditing() feats = [] if lyrDefault is True: bbox = QgsRectangle() bbox.setMinimal() for res in result: feat = QgsFeature() if mode == 'web': feat.setGeometry( QgsGeometry.fromMultiPolygonXY(res["geom"])) else: feat.setGeometry(QgsGeometry.fromWkt(res["wkt"])) feat.setAttributes([ res["id"], res["partido"], res["partida"], res["nomenclatura"], res["codigo"], res["layer"] ]) feats.append(feat) if lyrDefault is True: bbox.combineExtentWith(feat.geometry().boundingBox()) layer.dataProvider().addFeatures(feats) layer.commitChanges() layer.updateExtents() if lyrDefault is True: self.canvas.setExtent(self.setBboxMap(bbox, layer)) else: self.canvas.setExtent(self.setBboxMap(layer.extent(), layer))
def getFeatureByAttributtes(self, layer, pdo_or_omencla, pda=None): try: if pda != None: result = layer.getFeatures( QgsFeatureRequest( QgsExpression( '"partido" = {} and "partida" = {}'.format( pdo_or_omencla, pda)))) result = list(result) if len(result) == 0: return False else: result = layer.getFeatures( QgsFeatureRequest( QgsExpression( '"codigo" = \'{}\''.format(pdo_or_omencla)))) result = list(result) if len(result) == 0: return False bbox = QgsRectangle() bbox.setMinimal() for feat in result: bbox.combineExtentWith(feat.geometry().boundingBox()) layer.updateExtents() self.canvas.setExtent(self.setBboxMap(bbox, layer)) layer.triggerRepaint() #canvas.refresh() return True except Exception as e: #en caso que la capa haya sido eliminada # fix_print_with_import print(str(e)) return False
def zoom_to_group(group): extent = QgsRectangle() extent.setMinimal() # Iterate through layers from group and combine their extent for child in group.children(): if isinstance(child, QgsLayerTreeLayer): extent.combineExtentWith(child.layer().extent()) iface.mapCanvas().setExtent(extent) iface.mapCanvas().refresh()
def set_margin(layer, margin): extent = QgsRectangle() extent.setMinimal() extent.combineExtentWith(layer.extent()) xmax = extent.xMaximum() + margin xmin = extent.xMinimum() - margin ymax = extent.yMaximum() + margin ymin = extent.yMinimum() - margin extent.set(xmin, ymin, xmax, ymax) global_vars.iface.mapCanvas().setExtent(extent) global_vars.iface.mapCanvas().refresh()
def getExtentForLocate(self, sourceRow): surfaceType = self.source.item(sourceRow, self.IndexSurface).text() surfaceLayers = QgisHelper.getSurfaceLayers(self.surfaceType) rect = QgsRectangle() rect.setMinimal() for sfLayer in surfaceLayers: features = sfLayer.getFeatures() for feature in features: surfaceString = feature.attribute("surface").toString() if surfaceString == surfaceType: geom = feature.geometry() rect.combineExtentWith(geom.boundingBox()) return rect
def add_resource_as_wfs_layers(wfs_resource, return_extent=False): if not isinstance(wfs_resource, NGWWfsService): raise NGWError('Resource type is not WfsService!') #Extent stuff if return_extent: summary_extent = QgsRectangle() summary_extent.setMinimal() #Add group toc_root = QgsProject.instance().layerTreeRoot() layers_group = toc_root.insertGroup(0, wfs_resource.common.display_name) #Add layers for wfs_layer in wfs_resource.wfs.layers: url = wfs_resource.get_wfs_url( wfs_layer.keyname ) + '&srsname=EPSG:3857&VERSION=1.0.0&REQUEST=GetFeature' qgs_wfs_layer = QgsVectorLayer(url, wfs_layer.display_name, 'WFS') ngw_vector_layer = wfs_resource.get_source_layer(wfs_layer.resource_id) # Add vector style. Select the first QGIS style if several. ngw_style_res = None vec_layer_children = ngw_vector_layer.get_children() for child in vec_layer_children: if isinstance(child, NGWQGISStyle): ngw_style_res = child break if not ngw_style_res is None: loop = QEventLoop() nam = QNetworkAccessManager() nam.finished.connect(loop.quit) reply = nam.get( QNetworkRequest(QUrl(ngw_style_res.download_qml_url()))) loop.exec_() tmpfile = QTemporaryFile() if tmpfile.open(QIODevice.WriteOnly): tmpfile.write(reply.readAll()) tmpfile.close() qgs_wfs_layer.loadNamedStyle(tmpfile.fileName()) _add_aliases(qgs_wfs_layer, ngw_vector_layer) #summarize extent if return_extent: _summ_extent(summary_extent, qgs_wfs_layer) CompatQgis.layers_registry().addMapLayer(qgs_wfs_layer, False) layers_group.insertLayer(0, qgs_wfs_layer) if return_extent: return summary_extent
def set_margin(layer, margin): """ Generates a margin around the layer so that it is fully visible on the canvas """ if layer.extent().isNull(): return extent = QgsRectangle() extent.setMinimal() extent.combineExtentWith(layer.extent()) xmin = extent.xMinimum() - margin ymin = extent.yMinimum() - margin xmax = extent.xMaximum() + margin ymax = extent.yMaximum() + margin extent.set(xmin, ymin, xmax, ymax) iface.mapCanvas().setExtent(extent) iface.mapCanvas().refresh()
def add_resource(self): sel_index = self.trvResources.selectionModel().currentIndex() if sel_index.isValid(): #extent for_zoom summary_extent = QgsRectangle() summary_extent.setMinimal() self.hide() #hack ngw_resource = sel_index.data(Qt.UserRole) if ngw_resource.common.cls == NGWFoclProject.type_id: for child in ngw_resource.get_children(): self._append_resource_to_map(child, ngw_resource, summary_extent) else: parent_resource = sel_index.parent().data(Qt.UserRole) self._append_resource_to_map(ngw_resource, parent_resource, summary_extent) self.zoom_to_extent(summary_extent) self.close()
def zoomToExtent(self): self.addLayers(self.proj.readEntry("QGYF", "dataPath")[0], [ "research_area", "ground_areas", "point_object", "line_object", "polygon_object", ]) extent = QgsRectangle() extent.setMinimal() root = self.proj.layerTreeRoot() ground_layer = self.proj.mapLayersByName('Grundytor') extent.combineExtentWith(ground_layer[0].extent()) group = root.findGroup("Klassificering") for child in group.children(): extent.combineExtentWith(child.layer().extent()) self.iface.mapCanvas().setExtent(extent) self.iface.mapCanvas().refresh()
def add_resource_as_wfs_layers(wfs_resource, return_extent=False): if not isinstance(wfs_resource, NGWWfsService): raise NGWError('Resource type is not WfsService!') #Extent stuff if return_extent: summary_extent = QgsRectangle() summary_extent.setMinimal() #Add group toc_root = QgsProject.instance().layerTreeRoot() layers_group = toc_root.insertGroup(0, wfs_resource.common.display_name) #Add layers for wfs_layer in wfs_resource.wfs.layers: url = wfs_resource.get_wfs_url(wfs_layer.keyname) + '&srsname=EPSG:3857&VERSION=1.0.0&REQUEST=GetFeature' qgs_wfs_layer = QgsVectorLayer(url, wfs_layer.display_name, 'WFS') #summarize extent if return_extent: _summ_extent(summary_extent, qgs_wfs_layer) QgsMapLayerRegistry.instance().addMapLayer(qgs_wfs_layer, False) layers_group.insertLayer(0, qgs_wfs_layer) if return_extent: return summary_extent
def groupify(self): print "Inside groupify" with self.groupAssignmentLock: self.layersToBeGrouped = len(self.layerList) self.getGeneratedGroup() registryAddedLayers = QgsMapLayerRegistry.instance().addMapLayers(self.layerList, False) for item in registryAddedLayers: if item not in self.layerList: print("****WARNING: A LAYER WAS NOT ADDED TO THE REGISTRY: "+str(item)+" --- ID : "+item.id()) self.errorCount = self.errorCount + 1 pass self.correctlyRegisteredLayers = sorted(self.layerList, key=lambda layer: layer.name()) for layer in self.correctlyRegisteredLayers: self.generatedGroup.addLayer(layer) print "set visible layer identifier" print type(self.canvas) print type(self.parent) print (layer) #QgsProject.instance().layerTreeRoot().findLayer(layer.id()).setVisible(Qt.Unchecked) # self.canvas.legendInterface().setLayerVisible(layer, False) print "set visible layer ok" #We combine the group extents so all the layers are zoomed #equally on play. extent = QgsRectangle() extent.setMinimal() for child in self.generatedGroup.children(): if isinstance(child, QgsLayerTreeLayer): extent.combineExtentWith( child.layer().extent() ) self.canvas.setExtent( extent ) self.canvas.refresh() print "extend ok" #iface.mapCanvas().setExtent( extent ) #iface.mapCanvas().refresh() if self.errorCount > 0: self.errorsFound.emit(self.errorCount)
def add_resource_as_wfs_layers(wfs_resource, return_extent=False): if not isinstance(wfs_resource, NGWWfsService): raise NGWError('Resource type is not WfsService!') #Extent stuff if return_extent: summary_extent = QgsRectangle() summary_extent.setMinimal() #Add group toc_root = QgsProject.instance().layerTreeRoot() layers_group = toc_root.insertGroup(0, wfs_resource.common.display_name) #Add layers for wfs_layer in wfs_resource.wfs.layers: url = wfs_resource.get_wfs_url( wfs_layer.keyname ) + '&srsname=EPSG:3857&VERSION=1.0.0&REQUEST=GetFeature' qgs_wfs_layer = QgsVectorLayer(url, wfs_layer.display_name, 'WFS') #summarize extent if return_extent: _summ_extent(summary_extent, qgs_wfs_layer) QgsMapLayerRegistry.instance().addMapLayer(qgs_wfs_layer, False) layers_group.insertLayer(0, qgs_wfs_layer) if return_extent: return summary_extent
def qgis_composer_renderer(impact_report, component): """Default Map Report Renderer using QGIS Composer. Render using qgis composer for a given impact_report data and component context. :param impact_report: ImpactReport contains data about the report that is going to be generated. :type impact_report: safe.report.impact_report.ImpactReport :param component: Contains the component metadata and context for rendering the output. :type component: safe.report.report_metadata.QgisComposerComponentsMetadata :return: Whatever type of output the component should be. .. versionadded:: 4.0 """ context = component.context """:type: safe.report.extractors.composer.QGISComposerContext""" qgis_composition_context = impact_report.qgis_composition_context # load composition object composition = QgsComposition(qgis_composition_context.map_settings) # load template main_template_folder = impact_report.metadata.template_folder # we do this condition in case custom template was found if component.template.startswith('../qgis-composer-templates/'): template_path = os.path.join(main_template_folder, component.template) else: template_path = component.template with open(template_path) as template_file: template_content = template_file.read() document = QtXml.QDomDocument() document.setContent(template_content) load_status = composition.loadFromTemplate( document, context.substitution_map) if not load_status: raise TemplateLoadingError( tr('Error loading template: %s') % template_path) # replace image path for img in context.image_elements: item_id = img.get('id') path = img.get('path') image = composition_item(composition, item_id, QgsComposerPicture) """:type: qgis.core.QgsComposerPicture""" if image and path: image.setPicturePath(path) # replace html frame for html_el in context.html_frame_elements: item_id = html_el.get('id') mode = html_el.get('mode') composer_item = composition.getComposerItemById(item_id) try: html_element = composition.getComposerHtmlByItem(composer_item) except: pass """:type: qgis.core.QgsComposerHtml""" if html_element: if mode == 'text': text = html_el.get('text') text = text if text else '' html_element.setContentMode(QgsComposerHtml.ManualHtml) html_element.setHtml(text) html_element.loadHtml() elif mode == 'url': url = html_el.get('url') html_element.setContentMode(QgsComposerHtml.Url) qurl = QUrl.fromLocalFile(url) html_element.setUrl(qurl) original_crs = impact_report.impact_function.crs destination_crs = qgis_composition_context.map_settings.destinationCrs() coord_transform = QgsCoordinateTransform(original_crs, destination_crs) # resize map extent for map_el in context.map_elements: item_id = map_el.get('id') split_count = map_el.get('grid_split_count') layers = [ layer for layer in map_el.get('layers') if isinstance( layer, QgsMapLayer) ] map_extent_option = map_el.get('extent') composer_map = composition_item(composition, item_id, QgsComposerMap) for index, layer in enumerate(layers): # we need to check whether the layer is registered or not registered_layer = ( QgsMapLayerRegistry.instance().mapLayer(layer.id())) if registered_layer: if not registered_layer == layer: layers[index] = registered_layer else: QgsMapLayerRegistry.instance().addMapLayer(layer) """:type: qgis.core.QgsComposerMap""" if composer_map: # Search for specified map extent in the template. min_x = composer_map.extent().xMinimum() if ( impact_report.use_template_extent) else None min_y = composer_map.extent().yMinimum() if ( impact_report.use_template_extent) else None max_x = composer_map.extent().xMaximum() if ( impact_report.use_template_extent) else None max_y = composer_map.extent().yMaximum() if ( impact_report.use_template_extent) else None composer_map.setKeepLayerSet(True) layer_set = [l.id() for l in layers if isinstance(l, QgsMapLayer)] composer_map.setLayerSet(layer_set) map_overview_extent = None if map_extent_option and isinstance( map_extent_option, QgsRectangle): # use provided map extent extent = coord_transform.transform(map_extent_option) for l in [layer for layer in layers if isinstance(layer, QgsMapLayer)]: layer_extent = coord_transform.transform(l.extent()) if l.name() == map_overview['id']: map_overview_extent = layer_extent else: # if map extent not provided, try to calculate extent # from list of given layers. Combine it so all layers were # shown properly extent = QgsRectangle() extent.setMinimal() for l in [layer for layer in layers if isinstance(layer, QgsMapLayer)]: # combine extent if different layer is provided. layer_extent = coord_transform.transform(l.extent()) extent.combineExtentWith(layer_extent) if l.name() == map_overview['id']: map_overview_extent = layer_extent width = extent.width() height = extent.height() longest_width = width if width > height else height half_length = longest_width / 2 margin = half_length / 5 center = extent.center() min_x = min_x or (center.x() - half_length - margin) max_x = max_x or (center.x() + half_length + margin) min_y = min_y or (center.y() - half_length - margin) max_y = max_y or (center.y() + half_length + margin) # noinspection PyCallingNonCallable square_extent = QgsRectangle(min_x, min_y, max_x, max_y) if component.key == 'population-infographic' and ( map_overview_extent): square_extent = map_overview_extent composer_map.zoomToExtent(square_extent) composer_map.renderModeUpdateCachedImage() actual_extent = composer_map.extent() # calculate intervals for grid x_interval = actual_extent.width() / split_count composer_map.grid().setIntervalX(x_interval) y_interval = actual_extent.height() / split_count composer_map.grid().setIntervalY(y_interval) # calculate legend element for leg_el in context.map_legends: item_id = leg_el.get('id') title = leg_el.get('title') layers = [ layer for layer in leg_el.get('layers') if isinstance( layer, QgsMapLayer) ] symbol_count = leg_el.get('symbol_count') column_count = leg_el.get('column_count') legend = composition_item(composition, item_id, QgsComposerLegend) """:type: qgis.core.QgsComposerLegend""" if legend: # set column count if column_count: legend.setColumnCount(column_count) elif symbol_count <= 7: legend.setColumnCount(1) else: legend.setColumnCount(symbol_count / 7 + 1) # set legend title if title is not None and not impact_report.legend_layers: legend.setTitle(title) # set legend root_group = legend.modelV2().rootGroup() for layer in layers: # we need to check whether the layer is registered or not registered_layer = ( QgsMapLayerRegistry.instance().mapLayer(layer.id())) if registered_layer: if not registered_layer == layer: layer = registered_layer else: QgsMapLayerRegistry.instance().addMapLayer(layer) # used for customizations tree_layer = root_group.addLayer(layer) if impact_report.legend_layers or ( not impact_report.multi_exposure_impact_function): QgsLegendRenderer.setNodeLegendStyle( tree_layer, QgsComposerLegendStyle.Hidden) legend.synchronizeWithModel() # process to output # in case output folder not specified if impact_report.output_folder is None: impact_report.output_folder = mkdtemp(dir=temp_dir()) output_format = component.output_format component_output_path = impact_report.component_absolute_output_path( component.key) component_output = None doc_format = QgisComposerComponentsMetadata.OutputFormat.DOC_OUTPUT template_format = QgisComposerComponentsMetadata.OutputFormat.QPT if isinstance(output_format, list): component_output = [] for i in range(len(output_format)): each_format = output_format[i] each_path = component_output_path[i] if each_format in doc_format: result_path = create_qgis_pdf_output( impact_report, each_path, composition, each_format, component) component_output.append(result_path) elif each_format == template_format: result_path = create_qgis_template_output( each_path, composition) component_output.append(result_path) elif isinstance(output_format, dict): component_output = {} for key, each_format in output_format.iteritems(): each_path = component_output_path[key] if each_format in doc_format: result_path = create_qgis_pdf_output( impact_report, each_path, composition, each_format, component) component_output[key] = result_path elif each_format == template_format: result_path = create_qgis_template_output( each_path, composition) component_output[key] = result_path elif (output_format in QgisComposerComponentsMetadata.OutputFormat.SUPPORTED_OUTPUT): component_output = None if output_format in doc_format: result_path = create_qgis_pdf_output( impact_report, component_output_path, composition, output_format, component) component_output = result_path elif output_format == template_format: result_path = create_qgis_template_output( component_output_path, composition) component_output = result_path component.output = component_output return component.output
class ROSVectorProvider(QgsVectorDataProvider): fieldsUpdated = pyqtSignal() @classmethod def providerKey(cls): return 'rosvectorprovider' @classmethod def description(cls): return 'ROS Vector Provider' @classmethod def createProvider(cls, uri, providerOptions): return ROSVectorProvider(uri, providerOptions) def __init__(self, uri='', providerOptions=QgsDataProvider.ProviderOptions()): '''Set up the Data Provider. uri contains the topic name, topic type. Example uri: 'foo/my_pose?type=geometry_msgs/PoseStamped' ''' try: self._topic, argString = uri.split('?') except IndexError: raise ValueError( 'uri Cannot be parsed. Is it valid? uri: {}'.format(uri)) # Parse string of arguments into dict of python types. args = parseUrlArgs(argString) super().__init__(uri) self._translator = TranslatorRegistry.instance().get(args['type']) # There's no source for a reasonable collection of native types so we just steal from another provider. mlayer = QgsVectorLayer('Polygon?crs=epsg:4326', 'ml', 'memory') # Wrong url but doesn't matter. nativeTypes = mlayer.dataProvider().nativeTypes() self.setNativeTypes(nativeTypes) self._uri = uri self._fields = QgsFields() self._wkbType = self._translator.geomType # TODO: if unknown, infer it. self._features = {} self._extent = QgsRectangle() self._extent.setMinimal() self._subset_string = '' self._spatialindex = None self._provider_options = providerOptions self.next_feature_id = 0 # TODO: Consider a generator for a better numbering approach. self._lock = RLock() self._subscriber = None self.keepOlderMessages = args.get('keepOlderMessages', False) self._handledMessageCount = 0 self.sampleInterval = int(args.get('sampleInterval', 1)) if args.get('index'): self.createSpatialIndex() if args.get('subscribe'): self._subscriber = rospy.Subscriber(self._topic, self._translator.messageType, self._handleMessage) else: msg = rospy.wait_for_message(self._topic, self._translator.messageType, timeout=5) self._handleMessage(msg) def _handleMessage(self, msg): self._handledMessageCount += 1 # Skip message if not on interval. if (self._handledMessageCount - 1 ) % self.sampleInterval: # -1 so that first message is handled. return features = self._translator.translate(msg) qgsFeatures, fields = featuresToQgs(features) # TODO: check if fields changed and emit a signal only then. self._fields = fields self.fieldsUpdated.emit() # If we're not accumulating history, clear features first. if not self.keepOlderMessages: self.next_feature_id = 0 self._features = {} # Clear features. try: self._setFeatures(qgsFeatures) except RuntimeError: self._cleanup() # Throttle data update to avoid over-stressing QGIS runtime. Consider alleviating this. global last_global_refresh now = rospy.get_time() if now - last_global_refresh > DATA_UPDATE_THROTTLE: last_global_refresh = now self.dataChanged.emit( ) # TODO: remove occasional flicker when this happens. def _cleanup(self): ''' Clean up ROS subscriber connection. The provider is owned by the QgsVectorLayer, which is owned by QGIS internals (layer registry) When a layer is removed, it gets deleted and cleaned up. However, there's no clean way to perform cleanup activities on the Python side before the underlying C++ object is deleted, thus making this object unstable. A RuntimeError is raised when this is detected. We'll perform cleanup at that point. ''' if self._subscriber: self._subscriber.unregister() self._subscriber = None def featureSource(self): with self._lock: return ROSVectorFeatureSource(self) def dataSourceUri(self, expandAuthConfig=True): return self._uri def storageType(self): return "ROS Topic" def getFeatures(self, request=QgsFeatureRequest()): with self._lock: return QgsFeatureIterator( ROSVectorFeatureIterator(ROSVectorFeatureSource(self), request)) def uniqueValues(self, fieldIndex, limit=1): with self._lock: results = set() if fieldIndex >= 0 and fieldIndex < self._fields.count(): req = QgsFeatureRequest() req.setFlags(QgsFeatureRequest.NoGeometry) req.setSubsetOfAttributes([fieldIndex]) for f in self.getFeatures(req): results.add(f.attributes()[fieldIndex]) return results def wkbType(self): return self._wkbType def featureCount(self): with self._lock: if not self.subsetString(): return len(self._features) else: req = QgsFeatureRequest() req.setFlags(QgsFeatureRequest.NoGeometry) req.setSubsetOfAttributes([]) return len([f for f in self.getFeatures(req)]) def fields(self): with self._lock: return self._fields def _setFeatures(self, flist, flags=None): with self._lock: added = False f_added = [] if self._spatialindex is not None: for f in self._features.values(): self._spatialindex.deleteFeature(f) for _f in flist: self._features[self.next_feature_id] = _f _f.setId(self.next_feature_id) self.next_feature_id += 1 added = True f_added.append(_f) if self._spatialindex is not None: self._spatialindex.insertFeature(_f) if f_added: self.clearMinMaxCache() self.updateExtents() return added, f_added def allFeatureIds(self): with self._lock: return list(self._features.keys()) def subsetString(self): return self._subset_string def setSubsetString(self, subsetString): if subsetString == self._subset_string: return True self._subset_string = subsetString self.updateExtents() self.clearMinMaxCache() self.dataChanged.emit() return True def supportsSubsetString(self): return True def createSpatialIndex(self): if self._spatialindex is None: self._spatialindex = QgsSpatialIndex() for f in self._features.values(): self._spatialindex.insertFeature(f) return True def capabilities(self): return QgsVectorDataProvider.SelectAtId | QgsVectorDataProvider.CreateSpatialIndex def name(self): return self.providerKey() def extent(self): if self._extent.isEmpty() and self._features: self._extent.setMinimal() if not self._subset_string: # fast way - iterate through all features for feat in self._features.values(): if feat.hasGeometry(): self._extent.combineExtentWith( feat.geometry().boundingBox()) else: for f in self.getFeatures( QgsFeatureRequest().setSubsetOfAttributes([])): if f.hasGeometry(): self._extent.combineExtentWith( f.geometry().boundingBox()) elif not self._features: self._extent.setMinimal() return QgsRectangle(self._extent) def updateExtents(self): self._extent.setMinimal() def isValid(self): return True def crs(self): return simpleCrs
def init_layers(self, scenario): ''' initialize the layers in layer-window for given scenario including adding groups and background-layers and setting the editability of the institutional layers ''' if not scenario: return scen_group = get_group(scenario.name, add_at_index=0) # just for the right initial order get_group('Filter', scen_group) cat_group = get_group('Einrichtungen', scen_group) get_group('Erreichbarkeiten PKW', scen_group) get_group(u'Erreichbarkeiten ÖPNV') border_group = get_group('Verwaltungsgrenzen') self.add_wms_background_map(group=get_group('Hintergrundkarte', add_at_index=-1)) self.add_xml_background_map(GOOGLE_XML, group=get_group('Hintergrundkarte'), visible=False) for name, tablename in [('Gemeinden', 'gemeinden_20161231'), ('Verwaltungsgemeinschaften', 'vwg_20161231'), ('Kreise', 'kreis_20161231')]: border_style = self.borders[name] symbology = SimpleFillSymbology(border_style=border_style) self.add_db_layer(name, 'verwaltungsgrenzen', tablename, 'geom', group=border_group, visible=False, symbology=symbology) self.canvas.refresh() ### SET THE EDITABILITY OF INSTITUTIONAL LAYER-FIELDS### columns = ['spalte', 'editierbar', 'nur_auswahl_zulassen', 'auswahlmoeglichkeiten', 'alias', 'auto_vervollst', 'typ', 'min', 'max'] for category, filter_tree in self.categories.iteritems(): table = filter_tree.tablename symbology = SimpleSymbology(self.colors[category]) layer = self.add_db_layer(category, SCHEMA, table, 'geom_gk', symbology, group=cat_group, zoom=False, where='szenario_id={}'.format(scenario.id)) rows = get_values('editierbare_spalten', columns, self.db_conn, schema='einrichtungen', where="tabelle='{}'".format(table), order_by='reihenfolge') editable_columns = [r.spalte for r in rows] #if not rows: #continue for i, f in enumerate(layer.fields()): if f.name() == 'szenario_id': layer.setEditorWidgetV2(i, 'Hidden') layer.setDefaultValueExpression(i, str(scenario.id)) continue try: idx = editable_columns.index(f.name()) except: layer.setEditorWidgetV2(i, 'Hidden') continue col, is_ed, is_sel, selections, alias, auto_complete, typ, min_value, max_value = rows[idx] if alias: layer.addAttributeAlias(i, alias) if not is_ed: layer.setEditorWidgetV2(i, 'Hidden') continue # type range (integers) if typ == 'range': layer.setEditorWidgetV2(i, 'Range') layer.setEditorWidgetV2Config( i, {'AllowNull': False, 'Min': min_value, 'Max': max_value}) # auto complete: take all existing unique values of field, # text will can be auto completed to one of those in UI if auto_complete: layer.setEditorWidgetV2(i, 'UniqueValues') layer.setEditorWidgetV2Config(i, {u'Editable': True}) # selectable values are predefined in database elif is_sel and selections: layer.setEditorWidgetV2(i, 'ValueMap') sel = [] for s in selections: try: s = s.decode('utf-8') except: pass sel.append(s) d = dict([(s, s) for s in sel]) layer.setEditorWidgetV2Config(i, d) elif is_sel: layer.setEditorWidgetV2(i, 'UniqueValues') # zoom to extent extent = QgsRectangle() extent.setMinimal() for child in cat_group.children(): if isinstance(child, QgsLayerTreeLayer): #print child.layer().extent() extent.combineExtentWith(child.layer().extent()) self.canvas.setExtent(extent) self.canvas.refresh()
##MM=group ##r.series_directory=name ##Select_directory=Folder ##output=output raster import glob, os from PyQt4.QtCore import QFileInfo from qgis.core import QgsRasterLayer, QgsRectangle os.chdir(Select_directory) rlist = [] extent = QgsRectangle() extent.setMinimal() for raster in glob.glob("*.tif"): fileInfo = QFileInfo(raster) baseName = fileInfo.baseName() rlayer = QgsRasterLayer(raster, baseName) # Combine raster layers to list rlist.append(rlayer) # Combine raster extents extent.combineExtentWith(rlayer.extent()) # Get extent xmin = extent.xMinimum() xmax = extent.xMaximum() ymin = extent.yMinimum() ymax = extent.yMaximum() # Run algorithm and set relevant parameters processing.runalg( "grass:r.series", { "input": rlist,
class DjangoProvider(QgsVectorDataProvider): @classmethod def providerKey(cls): return 'django' @classmethod def description(cls): return 'Django vector provider' @classmethod def createProvider(cls, uri, providerOptions): return DjangoProvider(uri, providerOptions) def __init__(self, uri='', providerOptions=QgsDataProvider.ProviderOptions()): """ :param uri: <app>.<model>[?geofield=<name>] :param providerOptions: """ super().__init__(uri) self._is_valid = False self.setNativeTypes(( # TODO QgsVectorDataProvider.NativeType('Integer', 'integer', QVariant.Int, -1, -1, 0, 0), QgsVectorDataProvider.NativeType('Text', 'text', QVariant.String, -1, -1, -1, -1), )) self._uri = uri url = QUrl(uri) url_query = QUrlQuery(url) self._full_model_name = url.path() self._app_label, self._model_name = self._full_model_name.split('.') self._model = apps.get_model(self._app_label, self._model_name) # Django model self._meta = self._model._meta self._qgis_fields = QgsFields() self._django_fields = [] # Django fields represented by provider in the same order as QgsFields for django_field in self._meta.get_fields(): # TODO: more field types qgis_field = self._get_qgis_field_from_django_field(django_field) if qgis_field: self._qgis_fields.append(qgis_field) self._django_fields.append(django_field) self._geo_field_name = url_query.queryItemValue('geofield') self._geo_field = None # Django geometry field if self._geo_field_name: self._meta.get_field(self._geo_field_name) else: # If geometry field was not specified in uri, use the first one if any. for field in self._meta.get_fields(): if isinstance(field, models.GeometryField): self._geo_field = field self._geo_field_name = field.name break self._wkbType = QgsWkbTypes.NoGeometry if self._geo_field: for geo_field_class in wkb_types.keys(): if isinstance(self._geo_field, geo_field_class): self._wkbType = wkb_types[geo_field_class] break self._extent = QgsRectangle() self._crs = None if self._geo_field: self._crs = QgsCoordinateReferenceSystem.fromEpsgId(self._geo_field.srid) self._provider_options = providerOptions self._is_valid = True def featureSource(self): return DjangoFeatureSource(self._model, self._qgis_fields, self._django_fields, self._geo_field, self._crs) def dataSourceUri(self, expandAuthConfig=True): return self._uri def storageType(self): return "Django" def getFeatures(self, request=QgsFeatureRequest()): return QgsFeatureIterator(self.featureSource().getFeatures(request)) def uniqueValues(self, fieldIndex, limit=-1): if fieldIndex < 0 or fieldIndex >= self.fields().count(): return set() dj_field = self._django_fields[fieldIndex] values = self._model.objects.get_queryset().order_by(dj_field.name).values_list(dj_field.name, flat=True).distinct() if limit >= 0: values = values[:limit] return set(values) def wkbType(self): return self._wkbType def featureCount(self): return self._model.objects.get_queryset().count() def fields(self): return self._qgis_fields def addFeatures(self, features, flags=None): # TODO return False def deleteFeatures(self, ids): # TODO return False def addAttributes(self, attrs): return False def renameAttributes(self, renamedAttributes): return False def deleteAttributes(self, attributes): return False def changeAttributeValues(self, attr_map): # TODO for feature_id, attrs in attr_map.items(): pass self.clearMinMaxCache() return True def changeGeometryValues(self, geometry_map): # TODO for feature_id, geometry in geometry_map.items(): pass self.updateExtents() return True def allFeatureIds(self): return list(self._model.objects.get_queryset().values_list(self._meta.pk.name, flat=True)) def subsetString(self): return None def setSubsetString(self, subsetString): return False def supportsSubsetString(self): return False def createSpatialIndex(self): return False def capabilities(self): # TODO: QgsVectorDataProvider.AddFeatures | QgsVectorDataProvider.DeleteFeatures | QgsVectorDataProvider.ChangeGeometries | QgsVectorDataProvider.ChangeAttributeValues # TODO: TransactionSupport return QgsVectorDataProvider.SelectAtId # ---------------------------- functions from QgsDataProvider ---------------------------- def name(self): return self.providerKey() def extent(self): # TODO return QgsRectangle(-20037508.34, -20037508.34, 20037508.34, 20037508.34) if self._extent.isEmpty() and self._geo_field: box = list(self._model.objects.get_queryset().aggregate(models.Extent(self._geo_field_name)).values())[0] self._extent = QgsRectangle(box[0], box[0], box[0], box[0]) return QgsRectangle(self._extent) def updateExtents(self): self._extent.setMinimal() def isValid(self): return self._is_valid def crs(self): return self._crs # -------------------------------- Private methods -------------------------------- def _get_django_field(self, field_index): return self._django_fields[field_index] @staticmethod def _get_qgis_field_from_django_field(django_field): # IS it OK to take class name? name = django_field.name type_name = type(django_field).__name__.replace('Field', '').lower() comment = django_field.verbose_name # boolean if isinstance(django_field, models.BooleanField): return QgsField(name, QVariant.Bool, type_name, -1, -1, comment) elif isinstance(django_field, models.NullBooleanField): return QgsField(name, QVariant.Bool, type_name, -1, -1, comment) # integer elif isinstance(django_field, models.SmallIntegerField): return QgsField(name, QVariant.Int, type_name, -1, 0, comment) elif isinstance(django_field, models.IntegerField): return QgsField(name, QVariant.Int, type_name, -1, 0, comment) elif isinstance(django_field, models.BigIntegerField): return QgsField(name, QVariant.LongLong, type_name, -1, 0, comment) # float elif isinstance(django_field, models.FloatField): return QgsField(name, QVariant.Double, type_name, -1, -1, comment) elif isinstance(django_field, models.DecimalField): return QgsField(name, QVariant.Double, type_name, django_field.max_digits, django_field.decimal_places, comment) # char elif isinstance(django_field, models.CharField): return QgsField(name, QVariant.String, type_name, django_field.max_length, -1, comment) elif isinstance(django_field, models.TextField): return QgsField(name, QVariant.String, type_name, -1, -1, comment) # datetime elif isinstance(django_field, models.DateField): return QgsField(name, QVariant.Date, type_name, -1, -1, comment) elif isinstance(django_field, models.TimeField): return QgsField(name, QVariant.Time, type_name, -1, -1, comment) elif isinstance(django_field, models.DateTimeField): return QgsField(name, QVariant.DateTime, type_name, -1, -1, comment) return None
def qgis_composer_renderer(impact_report, component): """Default Map Report Renderer using QGIS Composer. Render using qgis composer for a given impact_report data and component context :param impact_report: ImpactReport contains data about the report that is going to be generated :type impact_report: safe.report.impact_report.ImpactReport :param component: Contains the component metadata and context for rendering the output :type component: safe.report.report_metadata.QgisComposerComponentsMetadata :return: whatever type of output the component should be .. versionadded:: 4.0 """ context = component.context """:type: safe.report.extractors.composer.QGISComposerContext""" qgis_composition_context = impact_report.qgis_composition_context inasafe_context = impact_report.inasafe_context # load composition object composition = QgsComposition(qgis_composition_context.map_settings) # load template main_template_folder = impact_report.metadata.template_folder template_path = os.path.join(main_template_folder, component.template) with open(template_path) as template_file: template_content = template_file.read() document = QtXml.QDomDocument() document.setContent(template_content) load_status = composition.loadFromTemplate( document, context.substitution_map) if not load_status: raise TemplateLoadingError( tr('Error loading template: %s') % template_path) # replace image path for img in context.image_elements: item_id = img.get('id') path = img.get('path') image = composition.getComposerItemById(item_id) """:type: qgis.core.QgsComposerPicture""" if image is not None and path is not None: try: image.setPicturePath(path) except: pass # replace html frame for html_el in context.html_frame_elements: item_id = html_el.get('id') mode = html_el.get('mode') html_element = composition.getComposerItemById(item_id) """:type: qgis.core.QgsComposerHtml""" if html_element: if mode == 'text': text = html_el.get('text') text = text if text else '' html_element.setContentMode(QgsComposerHtml.ManualHtml) html_element.setHtml(text) html_element.loadHtml() elif mode == 'url': url = html_el.get('url') html_element.setContentMode(QgsComposerHtml.Url) qurl = QUrl.fromLocalFile(url) html_element.setUrl(qurl) # resize map extent for map_el in context.map_elements: item_id = map_el.get('id') split_count = map_el.get('grid_split_count') layers = map_el.get('layers') map_extent_option = map_el.get('extent') composer_map = composition.getComposerItemById(item_id) """:type: qgis.core.QgsComposerMap""" if isinstance(composer_map, QgsComposerMap): composer_map.setKeepLayerSet(True) layer_set = [l.id() for l in layers if isinstance(l, QgsMapLayer)] composer_map.setLayerSet(layer_set) if map_extent_option and isinstance( map_extent_option, QgsRectangle): # use provided map extent extent = map_extent_option else: # if map extent not provided, try to calculate extent # from list of given layers. Combine it so all layers were # shown properly extent = QgsRectangle() extent.setMinimal() for l in layers: # combine extent if different layer is provided. extent.combineExtentWith(l.extent()) width = extent.width() height = extent.height() longest_width = width if width > height else height half_length = longest_width / 2 margin = half_length / 5 center = extent.center() min_x = center.x() - half_length - margin max_x = center.x() + half_length + margin min_y = center.y() - half_length - margin max_y = center.y() + half_length + margin # noinspection PyCallingNonCallable square_extent = QgsRectangle(min_x, min_y, max_x, max_y) composer_map.zoomToExtent(square_extent) composer_map.renderModeUpdateCachedImage() actual_extent = composer_map.extent() # calculate intervals for grid x_interval = actual_extent.width() / split_count composer_map.grid().setIntervalX(x_interval) y_interval = actual_extent.height() / split_count composer_map.grid().setIntervalY(y_interval) # calculate legend element for leg_el in context.map_legends: item_id = leg_el.get('id') title = leg_el.get('title') layers = leg_el.get('layers') symbol_count = leg_el.get('symbol_count') column_count = leg_el.get('column_count') legend = composition.getComposerItemById(item_id) """:type: qgis.core.QgsComposerLegend""" if isinstance(legend, QgsComposerLegend): # set column count if column_count: legend.setColumnCount(column_count) elif symbol_count <= 5: legend.setColumnCount(1) else: legend.setColumnCount(symbol_count / 5 + 1) # set legend title if title is not None: legend.setTitle(title) # set legend root_group = legend.modelV2().rootGroup() for l in layers: # used for customizations tree_layer = root_group.addLayer(l) QgsLegendRenderer.setNodeLegendStyle( tree_layer, QgsComposerLegendStyle.Hidden) legend.synchronizeWithModel() # process to output # in case output folder not specified if impact_report.output_folder is None: impact_report.output_folder = mkdtemp(dir=temp_dir()) output_format = component.output_format component_output_path = impact_report.component_absolute_output_path( component.key) component_output = None doc_format = QgisComposerComponentsMetadata.OutputFormat.DOC_OUTPUT template_format = QgisComposerComponentsMetadata.OutputFormat.QPT if isinstance(output_format, list): component_output = [] for i in range(len(output_format)): each_format = output_format[i] each_path = component_output_path[i] if each_format in doc_format: result_path = create_qgis_pdf_output( each_path, composition, impact_report.qgis_composition_context, each_format, component) component_output.append(result_path) elif each_format == template_format: result_path = create_qgis_template_output( each_path, composition) component_output.append(result_path) elif isinstance(output_format, dict): component_output = {} for key, each_format in output_format.iteritems(): each_path = component_output_path[key] if each_format in doc_format: result_path = create_qgis_pdf_output( each_path, composition, impact_report.qgis_composition_context, each_format, component) component_output[key] = result_path elif each_format == template_format: result_path = create_qgis_template_output( each_path, composition) component_output[key] = result_path elif (output_format in QgisComposerComponentsMetadata.OutputFormat.SUPPORTED_OUTPUT): component_output = None if output_format in doc_format: result_path = create_qgis_pdf_output( component_output_path, composition, impact_report.qgis_composition_context, output_format, component) component_output = result_path elif output_format == template_format: result_path = create_qgis_template_output( component_output_path, composition) component_output = result_path component.output = component_output return component.output
class PyProvider(QgsVectorDataProvider): next_feature_id = 1 @classmethod def providerKey(cls): """Returns the memory provider key""" return 'pythonprovider' @classmethod def description(cls): """Returns the memory provider description""" return 'Python Test Provider' @classmethod def createProvider(cls, uri, providerOptions): return PyProvider(uri, providerOptions) # Implementation of functions from QgsVectorDataProvider def __init__(self, uri='', providerOptions=QgsDataProvider.ProviderOptions()): super().__init__(uri) # Use the memory layer to parse the uri mlayer = QgsVectorLayer(uri, 'ml', 'memory') self.setNativeTypes(mlayer.dataProvider().nativeTypes()) self._uri = uri self._fields = mlayer.fields() self._wkbType = mlayer.wkbType() self._features = {} self._extent = QgsRectangle() self._extent.setMinimal() self._subset_string = '' self._crs = mlayer.crs() self._spatialindex = None self._provider_options = providerOptions if 'index=yes'in self._uri: self.createSpatialIndex() def featureSource(self): return PyFeatureSource(self) def dataSourceUri(self, expandAuthConfig=True): return self._uri def storageType(self): return "Python test memory storage" def getFeatures(self, request=QgsFeatureRequest()): return QgsFeatureIterator(PyFeatureIterator(PyFeatureSource(self), request)) def uniqueValues(self, fieldIndex, limit=1): results = set() if fieldIndex >= 0 and fieldIndex < self.fields().count(): req = QgsFeatureRequest() req.setFlags(QgsFeatureRequest.NoGeometry) req.setSubsetOfAttributes([fieldIndex]) for f in self.getFeatures(req): results.add(f.attributes()[fieldIndex]) return results def wkbType(self): return self._wkbType def featureCount(self): if not self.subsetString(): return len(self._features) else: req = QgsFeatureRequest() req.setFlags(QgsFeatureRequest.NoGeometry) req.setSubsetOfAttributes([]) return len([f for f in self.getFeatures(req)]) def fields(self): return self._fields def addFeatures(self, flist, flags=None): added = False f_added = [] for f in flist: if f.hasGeometry() and (f.geometry().wkbType() != self.wkbType()): return added, f_added for f in flist: _f = QgsFeature(self.fields()) _f.setGeometry(f.geometry()) attrs = [None for i in range(_f.fields().count())] for i in range(min(len(attrs), len(f.attributes()))): attrs[i] = f.attributes()[i] _f.setAttributes(attrs) _f.setId(self.next_feature_id) self._features[self.next_feature_id] = _f self.next_feature_id += 1 added = True f_added.append(_f) if self._spatialindex is not None: self._spatialindex.insertFeature(_f) if len(f_added): self.clearMinMaxCache() self.updateExtents() return added, f_added def deleteFeatures(self, ids): if not ids: return True removed = False for id in ids: if id in self._features: if self._spatialindex is not None: self._spatialindex.deleteFeature(self._features[id]) del self._features[id] removed = True if removed: self.clearMinMaxCache() self.updateExtents() return removed def addAttributes(self, attrs): try: for new_f in attrs: if new_f.type() not in (QVariant.Int, QVariant.Double, QVariant.String, QVariant.Date, QVariant.Time, QVariant.DateTime, QVariant.LongLong, QVariant.StringList, QVariant.List): continue self._fields.append(new_f) for f in self._features.values(): old_attrs = f.attributes() old_attrs.append(None) f.setAttributes(old_attrs) self.clearMinMaxCache() return True except Exception: return False def renameAttributes(self, renamedAttributes): result = True # We need to replace all fields because python bindings return a copy from [] and at() new_fields = [self._fields.at(i) for i in range(self._fields.count())] for fieldIndex, new_name in renamedAttributes.items(): if fieldIndex < 0 or fieldIndex >= self._fields.count(): result = False continue if self._fields.indexFromName(new_name) >= 0: #field name already in use result = False continue new_fields[fieldIndex].setName(new_name) if result: self._fields = QgsFields() for i in range(len(new_fields)): self._fields.append(new_fields[i]) return result def deleteAttributes(self, attributes): attrIdx = sorted(attributes, reverse=True) # delete attributes one-by-one with decreasing index for idx in attrIdx: self._fields.remove(idx) for f in self._features.values(): attr = f.attributes() del(attr[idx]) f.setAttributes(attr) self.clearMinMaxCache() return True def changeAttributeValues(self, attr_map): for feature_id, attrs in attr_map.items(): try: f = self._features[feature_id] except KeyError: continue for k, v in attrs.items(): f.setAttribute(k, v) self.clearMinMaxCache() return True def changeGeometryValues(self, geometry_map): for feature_id, geometry in geometry_map.items(): try: f = self._features[feature_id] f.setGeometry(geometry) except KeyError: continue self.updateExtents() return True def allFeatureIds(self): return list(self._features.keys()) def subsetString(self): return self._subset_string def setSubsetString(self, subsetString): if subsetString == self._subset_string: return True self._subset_string = subsetString self.updateExtents() self.clearMinMaxCache() self.dataChanged.emit() return True def supportsSubsetString(self): return True def createSpatialIndex(self): if self._spatialindex is None: self._spatialindex = QgsSpatialIndex() for f in self._features.values(): self._spatialindex.insertFeature(f) return True def capabilities(self): return QgsVectorDataProvider.AddFeatures | QgsVectorDataProvider.DeleteFeatures | QgsVectorDataProvider.CreateSpatialIndex | QgsVectorDataProvider.ChangeGeometries | QgsVectorDataProvider.ChangeAttributeValues | QgsVectorDataProvider.AddAttributes | QgsVectorDataProvider.DeleteAttributes | QgsVectorDataProvider.RenameAttributes | QgsVectorDataProvider.SelectAtId | QgsVectorDataProvider. CircularGeometries #/* Implementation of functions from QgsDataProvider */ def name(self): return self.providerKey() def extent(self): if self._extent.isEmpty() and self._features: self._extent.setMinimal() if not self._subset_string: # fast way - iterate through all features for feat in self._features.values(): if feat.hasGeometry(): self._extent.combineExtentWith(feat.geometry().boundingBox()) else: for f in self.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([])): if f.hasGeometry(): self._extent.combineExtentWith(f.geometry().boundingBox()) elif not self._features: self._extent.setMinimal() return QgsRectangle(self._extent) def updateExtents(self): self._extent.setMinimal() def isValid(self): return True def crs(self): return self._crs
def qgis_composer_renderer(impact_report, component): """Default Map Report Renderer using QGIS Composer. Render using qgis composer for a given impact_report data and component context. :param impact_report: ImpactReport contains data about the report that is going to be generated. :type impact_report: safe.report.impact_report.ImpactReport :param component: Contains the component metadata and context for rendering the output. :type component: safe.report.report_metadata.QgisComposerComponentsMetadata :return: Whatever type of output the component should be. .. versionadded:: 4.0 """ context = component.context qgis_composition_context = impact_report.qgis_composition_context # load composition object layout = QgsPrintLayout(QgsProject.instance()) # load template main_template_folder = impact_report.metadata.template_folder # we do this condition in case custom template was found if component.template.startswith('../qgis-composer-templates/'): template_path = os.path.join(main_template_folder, component.template) else: template_path = component.template with open(template_path) as template_file: template_content = template_file.read() document = QtXml.QDomDocument() # Replace for k, v in context.substitution_map.items(): template_content = template_content.replace('[{}]'.format(k), v) document.setContent(template_content) rwcontext = QgsReadWriteContext() load_status = layout.loadFromTemplate( document, rwcontext) if not load_status: raise TemplateLoadingError( tr('Error loading template: %s') % template_path) # replace image path for img in context.image_elements: item_id = img.get('id') path = img.get('path') image = layout_item(layout, item_id, QgsLayoutItemPicture) if image and path: image.setPicturePath(path) # replace html frame for html_el in context.html_frame_elements: item_id = html_el.get('id') mode = html_el.get('mode') html_element = layout_item(layout, item_id, QgsLayoutItemHtml) if html_element: if mode == 'text': text = html_el.get('text') text = text if text else '' html_element.setContentMode(QgsLayoutItemHtml.ManualHtml) html_element.setHtml(text) html_element.loadHtml() elif mode == 'url': url = html_el.get('url') html_element.setContentMode(QgsLayoutItemHtml.Url) qurl = QUrl.fromLocalFile(url) html_element.setUrl(qurl) original_crs = impact_report.impact_function.crs destination_crs = qgis_composition_context.map_settings.destinationCrs() coord_transform = QgsCoordinateTransform(original_crs, destination_crs, QgsProject.instance()) # resize map extent for map_el in context.map_elements: item_id = map_el.get('id') split_count = map_el.get('grid_split_count') layers = [ layer for layer in map_el.get('layers') if isinstance( layer, QgsMapLayer) ] map_extent_option = map_el.get('extent') composer_map = layout_item(layout, item_id, QgsLayoutItemMap) for index, layer in enumerate(layers): # we need to check whether the layer is registered or not registered_layer = ( QgsProject.instance().mapLayer(layer.id())) if registered_layer: if not registered_layer == layer: layers[index] = registered_layer else: QgsProject.instance().addMapLayer(layer) """:type: qgis.core.QgsLayoutItemMap""" if composer_map: # Search for specified map extent in the template. min_x = composer_map.extent().xMinimum() if ( impact_report.use_template_extent) else None min_y = composer_map.extent().yMinimum() if ( impact_report.use_template_extent) else None max_x = composer_map.extent().xMaximum() if ( impact_report.use_template_extent) else None max_y = composer_map.extent().yMaximum() if ( impact_report.use_template_extent) else None composer_map.setKeepLayerSet(True) layer_set = [l for l in layers if isinstance(l, QgsMapLayer)] composer_map.setLayers(layer_set) map_overview_extent = None if map_extent_option and isinstance( map_extent_option, QgsRectangle): # use provided map extent extent = coord_transform.transform(map_extent_option) for l in [layer for layer in layers if isinstance(layer, QgsMapLayer)]: layer_extent = coord_transform.transform(l.extent()) if l.name() == map_overview['id']: map_overview_extent = layer_extent else: # if map extent not provided, try to calculate extent # from list of given layers. Combine it so all layers were # shown properly extent = QgsRectangle() extent.setMinimal() for l in [layer for layer in layers if isinstance(layer, QgsMapLayer)]: # combine extent if different layer is provided. layer_extent = coord_transform.transform(l.extent()) extent.combineExtentWith(layer_extent) if l.name() == map_overview['id']: map_overview_extent = layer_extent width = extent.width() height = extent.height() longest_width = width if width > height else height half_length = longest_width / 2 margin = half_length / 5 center = extent.center() min_x = min_x or (center.x() - half_length - margin) max_x = max_x or (center.x() + half_length + margin) min_y = min_y or (center.y() - half_length - margin) max_y = max_y or (center.y() + half_length + margin) # noinspection PyCallingNonCallable square_extent = QgsRectangle(min_x, min_y, max_x, max_y) if component.key == 'population-infographic' and ( map_overview_extent): square_extent = map_overview_extent composer_map.zoomToExtent(square_extent) composer_map.invalidateCache() actual_extent = composer_map.extent() # calculate intervals for grid x_interval = actual_extent.width() / split_count composer_map.grid().setIntervalX(x_interval) y_interval = actual_extent.height() / split_count composer_map.grid().setIntervalY(y_interval) # calculate legend element for leg_el in context.map_legends: item_id = leg_el.get('id') title = leg_el.get('title') layers = [ layer for layer in leg_el.get('layers') if isinstance( layer, QgsMapLayer) ] symbol_count = leg_el.get('symbol_count') column_count = leg_el.get('column_count') legend = layout_item(layout, item_id, QgsLayoutItemLegend) """:type: qgis.core.QgsLayoutItemLegend""" if legend: # set column count if column_count: legend.setColumnCount(column_count) elif symbol_count <= 7: legend.setColumnCount(1) else: legend.setColumnCount(symbol_count / 7 + 1) # set legend title if title is not None and not impact_report.legend_layers: legend.setTitle(title) # set legend root_group = legend.model().rootGroup() for layer in layers: # we need to check whether the layer is registered or not registered_layer = ( QgsProject.instance().mapLayer(layer.id())) if registered_layer: if not registered_layer == layer: layer = registered_layer else: QgsProject.instance().addMapLayer(layer) # used for customizations tree_layer = root_group.addLayer(layer) if impact_report.legend_layers or ( not impact_report.multi_exposure_impact_function): QgsLegendRenderer.setNodeLegendStyle( tree_layer, QgsLegendStyle.Hidden) legend.adjustBoxSize() legend.updateFilterByMap(False) # process to output # in case output folder not specified if impact_report.output_folder is None: impact_report.output_folder = mkdtemp(dir=temp_dir()) output_format = component.output_format component_output_path = impact_report.component_absolute_output_path( component.key) component_output = None doc_format = QgisComposerComponentsMetadata.OutputFormat.DOC_OUTPUT template_format = QgisComposerComponentsMetadata.OutputFormat.QPT if isinstance(output_format, list): component_output = [] for i in range(len(output_format)): each_format = output_format[i] each_path = component_output_path[i] if each_format in doc_format: result_path = create_qgis_pdf_output( impact_report, each_path, layout, each_format, component) component_output.append(result_path) elif each_format == template_format: result_path = create_qgis_template_output( each_path, layout) component_output.append(result_path) elif isinstance(output_format, dict): component_output = {} for key, each_format in list(output_format.items()): each_path = component_output_path[key] if each_format in doc_format: result_path = create_qgis_pdf_output( impact_report, each_path, layout, each_format, component) component_output[key] = result_path elif each_format == template_format: result_path = create_qgis_template_output( each_path, layout) component_output[key] = result_path elif (output_format in QgisComposerComponentsMetadata.OutputFormat.SUPPORTED_OUTPUT): component_output = None if output_format in doc_format: result_path = create_qgis_pdf_output( impact_report, component_output_path, layout, output_format, component) component_output = result_path elif output_format == template_format: result_path = create_qgis_template_output( component_output_path, layout) component_output = result_path component.output = component_output return component.output
def _on_set_schematisation(self, something, filename=""): """Method is called when schematisation setting is changed in datasource model. Args: something: filename: Returns: None """ self.init_references_from_layer_tree() tracer = dict([(ref, ident) for ident, ref in self.tracer_mapping]) if filename == "": if self.model_layergroup is not None: self.model_layergroup.removeAllChildren() return split = os.path.split(filename) split_dir = os.path.split(split[0]) name = self.model_layergroup_basename + "/".join( (split_dir[-1], split[-1])) # adjust spatialite for correct visualization of layers threedi_db = ThreediDatabase({"db_path": filename}) threedi_db.create_views() threedi_db.fix_spatial_indices() if self.model_layergroup is None: # todo: see if we can set 'tracer' as custom property to identify # group later on root = QgsProject.instance().layerTreeRoot() self.model_layergroup = root.insertGroup(2, name) self._mark(self.model_layergroup, tracer["model_layergroup"]) else: self.model_layergroup.setName(name) if self.schematisation_layergroup is None: self.schematisation_layergroup = self.model_layergroup.insertGroup( 1, self.schematisation_group_name) self._mark(self.schematisation_layergroup, tracer["schematisation_layergroup"]) else: self.schematisation_layergroup.removeAllChildren() self.schematisation_layergroup.insertGroup( 0, self.schematisation_advanced_settings_group_name) # schematisation_inflow_group_name = 'inflow' # inflow_imp_surface_subgroup_name = 'impervious_surface' # inflow_surface_subgroup_name = 'surface' self.inflow_root = self.schematisation_layergroup.insertGroup( 1, self.schematisation_inflow_group_name) self.inflow_root.addGroup(self.inflow_imp_surface_subgroup_name) self.inflow_root.addGroup(self.inflow_surface_subgroup_name) self.schematisation_layergroup.insertGroup( 0, self.schematisation_grid_refinement_group_name) self.schematisation_layergroup.insertGroup( 0, self.schematisation_obstacle_group_name) self.schematisation_layergroup.insertGroup( 0, self.schematisation_additional_oned_group_name) self.schematisation_layergroup.insertGroup( 0, self.schematisation_oned_group_name) self.schematisation_layergroup.insertGroup( 0, self.schematisation_lateral_group_name) self.schematisation_layergroup.insertGroup( 0, self.schematisation_boundary_group_name) self.schematisation_layergroup.insertGroup( 0, self.schematisation_settings_group_name) # add_schematisation layers self._add_model_schematisation_layers(filename) # zoom to model extent: extent = QgsRectangle() extent.setMinimal() tree_layer = None for tree_layer in self.schematisation_layergroup.findLayers(): extent.combineExtentWith(tree_layer.layer().extent()) extent.scale(1.1) if not tree_layer: return transform = QgsCoordinateTransform(tree_layer.layer().crs(), QgsProject.instance().crs(), QgsProject.instance()) self.iface.mapCanvas().setExtent(transform.transform(extent)) return