def make_pdf(): canvas = QgsMapCanvas() # Load our project QgsProject.instance().read(QFileInfo(project_path)) bridge = QgsLayerTreeMapCanvasBridge(QgsProject.instance().layerTreeRoot(), canvas) bridge.setCanvasLayers() template_file = file(template_path) template_content = template_file.read() template_file.close() document = QDomDocument() document.setContent(template_content) composition = QgsComposition(canvas.mapSettings()) # You can use this to replace any string like this [key] # in the template with a new value. e.g. to replace # [date] pass a map like this {'date': '1 Jan 2012'} substitution_map = {'DATE_TIME_START': 'foo', 'DATE_TIME_END': 'bar'} composition.loadFromTemplate(document, substitution_map) # You must set the id in the template map_item = composition.getComposerItemById('map') map_item.setMapCanvas(canvas) map_item.zoomToExtent(canvas.extent()) # You must set the id in the template legend_item = composition.getComposerItemById('legend') legend_item.updateLegend() composition.refreshItems() composition.exportAsPDF('report.pdf') QgsProject.instance().clear()
def make_pdf(): canvas = QgsMapCanvas() # Load our project QgsProject.instance().read(QFileInfo(project_path)) bridge = QgsLayerTreeMapCanvasBridge( QgsProject.instance().layerTreeRoot(), canvas) bridge.setCanvasLayers() if canvas.layerCount() < 1: print 'No layers loaded from this project, exiting.' return print canvas.mapSettings().extent().toString() template_file = file(template_path) template_content = template_file.read() template_file.close() document = QDomDocument() document.setContent(template_content) composition = QgsComposition(canvas.mapSettings()) # You can use this to replace any string like this [key] # in the template with a new value. e.g. to replace # [date] pass a map like this {'date': '1 Jan 2012'} substitution_map = { 'DATE_TIME_START': TIME_START, 'DATE_TIME_END': TIME_STOP} composition.loadFromTemplate(document, substitution_map) # You must set the id in the template map_item = composition.getComposerItemById('map') map_item.setMapCanvas(canvas) map_item.zoomToExtent(canvas.extent()) # You must set the id in the template legend_item = composition.getComposerItemById('legend') legend_item.updateLegend() composition.refreshItems() composition.exportAsPDF( '/home/web/reports/pdf/%s/%s.pdf' % (TIME_SLICE, LABEL)) QgsProject.instance().clear()
def make_pdf(xmin, ymin, xmax, ymax, filter_expression): canvas = QgsMapCanvas() # Load our project QgsProject.instance().read(QFileInfo(project_path)) # Set canvas extent canvas.setExtent(QgsRectangle(xmin, ymin, xmax, ymax)) # Load layers here if they are not already in the project for layer in QgsMapLayerRegistry.instance().mapLayers().values(): if layer.name() == 'data': lyr = layer break lyr.setSubsetString(filter_expression) # bridge used in standalone script: http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/loadproject.html bridge = QgsLayerTreeMapCanvasBridge(QgsProject.instance().layerTreeRoot(), canvas) bridge.setCanvasLayers() # Check data providers load ok print('Provider List') print(QgsProviderRegistry.instance().providerList()) # Print layer validity - I've had some trouble with some wms layers for layer in QgsMapLayerRegistry.instance().mapLayers().values(): print(layer.name()) print(layer.isValid()) template_file = file(template_path) template_content = template_file.read() template_file.close() document = QDomDocument() document.setContent(template_content) composition = QgsComposition(canvas.mapSettings()) # You can use this to replace any string like this [key] # in the template with a new value. e.g. to replace # [date] pass a map like this {'date': '1 Jan 2012'} substitution_map = {'title': 'the title of my map'} composition.loadFromTemplate(document, substitution_map) # You must set the id in the template map_item = composition.getComposerItemById('Main Map') map_item.setMapCanvas(canvas) map_item.zoomToExtent(canvas.extent()) # You must set the id in the template legend_item = composition.getComposerItemById('Legend') legend_item.updateLegend() composition.refreshItems() composition.exportAsPDF('export.pdf') QgsProject.instance().clear()
def export_pdf(self, title=''): ''' Export Composition (map view and checked layers) to PDF ''' title = self.active_scenario.name if self.active_scenario else '' dialog = ExportPDFDialog(title=title, parent=self) result = dialog.exec_() ok = result == QtGui.QDialog.Accepted if not ok: return title = dialog.title date = dialog.date filepath = browse_file(None, 'Export', PDF_FILTER, save=True, parent=self) if not filepath: return bridge = QgsLayerTreeMapCanvasBridge( QgsProject.instance().layerTreeRoot(), self.canvas) bridge.setCanvasLayers() template_file = file(REPORT_TEMPLATE_PATH) template_content = template_file.read() template_file.close() document = QDomDocument() document.setContent(template_content) composition = QgsComposition(self.canvas.mapSettings()) # You can use this to replace any string like this [key] # in the template with a new value. e.g. to replace # [date] pass a map like this {'date': '1 Jan 2012'} substitution_map = { 'TITLE': title, 'DATE_TIME': date} composition.loadFromTemplate(document, substitution_map) # You must set the id in the template map_item = composition.getComposerItemById('map') map_item.setMapCanvas(self.canvas) map_item.zoomToExtent(self.canvas.extent()) # You must set the id in the template legend_item = composition.getComposerItemById('legend') legend_item.updateLegend() composition.refreshItems() composition.exportAsPDF(filepath) if sys.platform.startswith('darwin'): subprocess.call(('open', filepath)) elif os.name == 'nt': os.startfile(filepath) elif os.name == 'posix': subprocess.call(('xdg-open', filepath))
def from_file(cls, filename, canvas, relative_base=None): """ Load a project file from a path. :param filename: The path to the project file. :param canvas: (optional) Passing a canvas will auto add layers to the canvas when the load is loaded. :param relative_base_path: (optional) Relative base path for the project file to load layers from :return: A Project object which wraps QgsProject.instance() """ QgsProject.instance().clear() bridge = None if canvas: bridge = QgsLayerTreeMapCanvasBridge(QgsProject.instance().layerTreeRoot(), canvas) if relative_base is None: relative_base = os.path.dirname(filename) QDir.setCurrent(relative_base) QgsProject.instance().read(QFileInfo(filename)) if bridge: bridge.setCanvasLayers() return cls(bridge)
def export_map(layer, new_extent): """This function changes the map extents and creates a exported map image""" legend = iface.legendInterface() legend.setLayerVisible(layer, False) canvas = iface.mapCanvas() canvas.setExtent(new_extent) canvas.refresh() project_path = os.path.join(gis_files, 'air_tasking_order.qgs') QgsProject.instance().write(QFileInfo(project_path)) #Save with the flight lines QgsProject.instance().read(QFileInfo(project_path)) bridge = QgsLayerTreeMapCanvasBridge( QgsProject.instance().layerTreeRoot(), canvas) bridge.setCanvasLayers() template_file = file(os.path.join(gis_files, 'airborne_survey.qpt')) template_content = template_file.read() template_file.close() document = QDomDocument() document.setContent(template_content) ms = canvas.mapSettings() composition = QgsComposition(ms) composition.loadFromTemplate(document, {}) map_item = composition.getComposerItemById('the_map') map_item.setMapCanvas(canvas) map_item.zoomToExtent(canvas.extent()) map_text_box = '<font face="Arial">%s Tasking <br />%s - %s<br />%s' % ( Requesting_RFC, Survey_Start_Date, Survey_End_Date, Survey_Name) map_text = composition.getComposerItemById('Map_ID_Text') map_text.setText(map_text_box) composition.refreshItems() dpi = 300 dpmm = dpi / 24.4 width = int(dpmm * composition.paperWidth()) height = int(dpmm * composition.paperHeight()) image = QImage(QSize(width, height), QImage.Format_ARGB32) image.setDotsPerMeterX(dpmm * 1000) image.setDotsPerMeterY(dpmm * 1000) imagePainter = QPainter(image) composition.renderPage(imagePainter, 0) imagePainter.end() image.save(Survey_Name + '.png', 'png')
class QgisInterface(QObject): """Class to expose qgis objects and functions to plugins. This class is here for enabling us to run unit tests only, so most methods are simply stubs. """ currentLayerChanged = pyqtSignal(QgsMapCanvasLayer) layerSavedAs = pyqtSignal(QgsMapLayer, str) def __init__(self, canvas): """Constructor :param canvas: """ QObject.__init__(self) self.canvas = canvas self.legend = QgisLegend(canvas) self.message_bar = QgsMessageBar(None) # Set up slots so we can mimic the behaviour of QGIS when layers # are added. LOGGER.debug('Initialising canvas...') # noinspection PyArgumentList QgsMapLayerRegistry.instance().layersAdded.connect(self.addLayers) # noinspection PyArgumentList QgsMapLayerRegistry.instance().layerWasAdded.connect(self.addLayer) # noinspection PyArgumentList QgsMapLayerRegistry.instance().removeAll.connect(self.removeAllLayers) # For processing module self.destCrs = None # For keeping track of which layer is active in the legend. self.active_layer = None # In the next section of code, we are going to do some monkey patching # to make the QGIS processing framework think that this mock QGIS IFACE # instance is the actual one. It will also ensure that the processing # algorithms are nicely loaded and available for use. # Since QGIS > 2.0, the module is moved from QGisLayers to dataobjects # pylint: disable=F0401, E0611 if QGis.QGIS_VERSION_INT > 20001: # noinspection PyUnresolvedReferences from processing.tools import dataobjects else: # noinspection PyUnresolvedReferences from processing.core import QGisLayers as dataobjects # noinspection PyUnresolvedReferences import processing # noinspection PyUnresolvedReferences from processing.core.Processing import Processing # pylint: enable=F0401, E0611 processing.classFactory(self) # We create our own getAlgorithm function below which will will monkey # patch in to the Processing class in QGIS in order to ensure that the # Processing.initialize() call is made before asking for an alg. @staticmethod def mock_getAlgorithm(name): """ Modified version of the original getAlgorithm function. :param name: Name of the algorithm to load. :type name: str :return: An algorithm concrete class. :rtype: QgsAlgorithm ? """ Processing.initialize() for provider in Processing.algs.values(): if name in provider: return provider[name] return None # Now we let the monkey loose! Processing.getAlgorithm = mock_getAlgorithm # We also need to make dataobjects think that this iface is 'the one' # Note. the placement here (after the getAlgorithm monkey patch above) # is significant, so don't move it! dataobjects.iface = self # set up a layer tree bridge so that new added layers appear in legend self.layer_tree_root = QgsProject.instance().layerTreeRoot() self.bridge = QgsLayerTreeMapCanvasBridge(self.layer_tree_root, self.canvas) self.bridge.setCanvasLayers() def __getattr__(self, *args, **kwargs): # It's for processing module def dummy(*a, **kwa): _ = a, kwa return QgisInterface(self.canvas) return dummy def __iter__(self): # It's for processing module return self def next(self): # It's for processing module raise StopIteration def layers(self): # It's for processing module # simulate iface.legendInterface().layers() return QgsMapLayerRegistry.instance().mapLayers().values() @pyqtSlot('QStringList') def addLayers(self, layers): """Handle layers being added to the registry so they show up in canvas. :param layers: list<QgsMapLayer> list of map layers that were added .. note:: The QgsInterface api does not include this method, it is added here as a helper to facilitate testing. """ # LOGGER.debug('addLayers called on qgis_interface') # LOGGER.debug('Number of layers being added: %s' % len(layers)) # LOGGER.debug('Layer Count Before: %s' % len(self.canvas.layers())) current_layers = self.canvas.layers() final_layers = [] # We need to keep the record of the registered layers on our canvas! registered_layers = [] for layer in current_layers: final_layers.append(QgsMapCanvasLayer(layer)) registered_layers.append(layer.id()) for layer in layers: if layer.id() not in registered_layers: final_layers.append(QgsMapCanvasLayer(layer)) self.canvas.setLayerSet(final_layers) # LOGGER.debug('Layer Count After: %s' % len(self.canvas.layers())) @pyqtSlot('QgsMapLayer') def addLayer(self, layer): """Handle a layer being added to the registry so it shows up in canvas. :param layer: list<QgsMapLayer> list of map layers that were added .. note: The QgsInterface api does not include this method, it is added here as a helper to facilitate testing. .. note: The addLayer method was deprecated in QGIS 1.8 so you should not need this method much. """ pass @pyqtSlot() def removeAllLayers(self, ): """Remove layers from the canvas before they get deleted. .. note:: This is NOT part of the QGisInterface API but is needed to support QgsMapLayerRegistry.removeAllLayers(). """ self.canvas.setLayerSet([]) self.active_layer = None def newProject(self): """Create new project.""" # noinspection PyArgumentList QgsMapLayerRegistry.instance().removeAllMapLayers() # ---------------- API Mock for QgsInterface follows ------------------- def zoomFull(self): """Zoom to the map full extent.""" pass def zoomToPrevious(self): """Zoom to previous view extent.""" pass def zoomToNext(self): """Zoom to next view extent.""" pass def zoomToActiveLayer(self): """Zoom to extent of active layer.""" pass def addVectorLayer(self, path, base_name, provider_key): """Add a vector layer. :param path: Path to layer. :type path: str :param base_name: Base name for layer. :type base_name: str :param provider_key: Provider key e.g. 'ogr' :type provider_key: str """ pass def addRasterLayer(self, path, base_name): """Add a raster layer given a raster layer file name :param path: Path to layer. :type path: str :param base_name: Base name for layer. :type base_name: str """ pass def setActiveLayer(self, layer): """Set the currently active layer in the legend. :param layer: Layer to make active. :type layer: QgsMapLayer, QgsVectorLayer, QgsRasterLayer """ self.active_layer = layer def activeLayer(self): """Get pointer to the active layer (layer selected in the legend).""" if self.active_layer is not None: return self.active_layer else: return None def addToolBarIcon(self, action): """Add an icon to the plugins toolbar. :param action: Action to add to the toolbar. :type action: QAction """ pass def removeToolBarIcon(self, action): """Remove an action (icon) from the plugin toolbar. :param action: Action to add to the toolbar. :type action: QAction """ pass def addToolBar(self, name): """Add toolbar with specified name. :param name: Name for the toolbar. :type name: str """ pass def mapCanvas(self): """Return a pointer to the map canvas.""" return self.canvas def mainWindow(self): """Return a pointer to the main window. In case of QGIS it returns an instance of QgisApp. """ pass def addDockWidget(self, area, dock_widget): """Add a dock widget to the main window. :param area: Where in the ui the dock should be placed. :type area: :param dock_widget: A dock widget to add to the UI. :type dock_widget: QDockWidget """ pass def legendInterface(self): """Get the legend. See also discussion at: https://github.com/AIFDR/inasafe/pull/924/ Implementation added for version 3.2. """ return self.legend def messageBar(self): """Get the message bar. .. versionadded:: 3.2 :returns: A QGIS message bar instance :rtype: QgsMessageBar """ return self.message_bar
gui_flag = True app = QgsApplication(sys.argv, True) QgsApplication.setPrefixPath("/usr", True) QgsApplication.initQgis() project_path = 'report_maps.qgs' template_path = 'owner_occupancy.qpt' canvas = QgsMapCanvas() canvas.resize(QSize(1450, 850)) #start = time.time() QgsProject.instance().read(QFileInfo(project_path)) #end = time.time() root = QgsProject.instance().layerTreeRoot() bridge = QgsLayerTreeMapCanvasBridge(root, canvas) bridge.setCanvasLayers() registry = QgsMapLayerRegistry.instance() template_file = file(template_path) template_content = template_file.read() template_file.close() document = QDomDocument() document.setContent(template_content) map_settings = canvas.mapSettings() composition = QgsComposition(map_settings) #start = time.time() composition.loadFromTemplate(document) #end = time.time() #create list of all layers currently in the map map_layers = [lyr for lyr in registry.mapLayers() if root.findLayer(lyr)]
def print_atlas(self, project_path, composer_name, predefined_scales, feature_filter=None, page_name_expression=None): # Get composer from project # in QGIS 2, canno get composers without iface # so we reading project xml and extract composer # in QGIS 3.0, we will use project layoutManager() from xml.etree import ElementTree as ET composer_xml = None with open(project_path, 'r') as f: tree = ET.parse(f) for elem in tree.findall('.//Composer[@title="%s"]' % composer_name): composer_xml = ET.tostring(elem, encoding='utf8', method='xml') if not composer_xml: return document = QDomDocument() document.setContent(composer_xml) # Get canvas, map setting & instantiate composition canvas = QgsMapCanvas() QgsProject.instance().read(QFileInfo(project_path)) bridge = QgsLayerTreeMapCanvasBridge( QgsProject.instance().layerTreeRoot(), canvas) bridge.setCanvasLayers() ms = canvas.mapSettings() composition = QgsComposition(ms) # Load content from XML substitution_map = {} composition.loadFromTemplate(document, substitution_map) # Get atlas for this composition atlas = composition.atlasComposition() atlas.setEnabled(True) atlas_map = composition.getComposerMapById(0) atlas_map.setAtlasScalingMode(QgsComposerMap.Predefined) # get project scales atlas.setPredefinedScales(predefined_scales) atlas.setComposerMap(atlas_map) #on definit le filtre if feature_filter: atlas.setFilterFeatures(True) atlas.setFeatureFilter(feature_filter) if page_name_expression: atlas.setPageNameExpression(page_name_expression) # Set atlas mode composition.setAtlasMode(QgsComposition.ExportAtlas) # Generate atlas atlas.beginRender() uid = uuid4() for i in range(0, atlas.numFeatures()): atlas.prepareForFeature(i) export_path = os.path.join( tempfile.gettempdir(), '%s_%s.pdf' % (atlas.nameForPage(i), uid)) exported = composition.exportAsPDF(export_path) if not exported or not os.path.isfile(export_path): return None break atlas.endRender() return export_path
class QgisInterface(QObject): """Class to expose qgis objects and functions to plugins. This class is here for enabling us to run unit tests only, so most methods are simply stubs. """ currentLayerChanged = pyqtSignal(QgsMapCanvasLayer) layerSavedAs = pyqtSignal(QgsMapLayer, str) def __init__(self, canvas): """Constructor :param canvas: """ QObject.__init__(self) self.canvas = canvas self.legend = QgisLegend(canvas) self.message_bar = QgsMessageBar(None) # Set up slots so we can mimic the behaviour of QGIS when layers # are added. LOGGER.debug("Initialising canvas...") # noinspection PyArgumentList QgsMapLayerRegistry.instance().layersAdded.connect(self.addLayers) # noinspection PyArgumentList QgsMapLayerRegistry.instance().layerWasAdded.connect(self.addLayer) # noinspection PyArgumentList QgsMapLayerRegistry.instance().removeAll.connect(self.removeAllLayers) # For processing module self.destCrs = None # For keeping track of which layer is active in the legend. self.active_layer = None # In the next section of code, we are going to do some monkey patching # to make the QGIS processing framework think that this mock QGIS IFACE # instance is the actual one. It will also ensure that the processing # algorithms are nicely loaded and available for use. # Since QGIS > 2.0, the module is moved from QGisLayers to dataobjects # pylint: disable=F0401, E0611 if QGis.QGIS_VERSION_INT > 20001: # noinspection PyUnresolvedReferences from processing.tools import dataobjects else: # noinspection PyUnresolvedReferences from processing.core import QGisLayers as dataobjects # noinspection PyUnresolvedReferences import processing # noinspection PyUnresolvedReferences from processing.core.Processing import Processing # pylint: enable=F0401, E0611 processing.classFactory(self) # We create our own getAlgorithm function below which will will monkey # patch in to the Processing class in QGIS in order to ensure that the # Processing.initialize() call is made before asking for an alg. @staticmethod def mock_getAlgorithm(name): """ Modified version of the original getAlgorithm function. :param name: Name of the algorithm to load. :type name: str :return: An algorithm concrete class. :rtype: QgsAlgorithm ? """ Processing.initialize() for provider in Processing.algs.values(): if name in provider: return provider[name] return None # Now we let the monkey loose! Processing.getAlgorithm = mock_getAlgorithm # We also need to make dataobjects think that this iface is 'the one' # Note. the placement here (after the getAlgorithm monkey patch above) # is significant, so don't move it! dataobjects.iface = self # set up a layer tree bridge so that new added layers appear in legend self.layer_tree_root = QgsProject.instance().layerTreeRoot() self.bridge = QgsLayerTreeMapCanvasBridge(self.layer_tree_root, self.canvas) self.bridge.setCanvasLayers() def __getattr__(self, *args, **kwargs): # It's for processing module def dummy(*a, **kwa): _ = a, kwa return QgisInterface(self.canvas) return dummy def __iter__(self): # It's for processing module return self def next(self): # It's for processing module raise StopIteration def layers(self): # It's for processing module # simulate iface.legendInterface().layers() return QgsMapLayerRegistry.instance().mapLayers().values() @pyqtSlot("QStringList") def addLayers(self, layers): """Handle layers being added to the registry so they show up in canvas. :param layers: list<QgsMapLayer> list of map layers that were added .. note:: The QgsInterface api does not include this method, it is added here as a helper to facilitate testing. """ # LOGGER.debug('addLayers called on qgis_interface') # LOGGER.debug('Number of layers being added: %s' % len(layers)) # LOGGER.debug('Layer Count Before: %s' % len(self.canvas.layers())) current_layers = self.canvas.layers() final_layers = [] # We need to keep the record of the registered layers on our canvas! registered_layers = [] for layer in current_layers: final_layers.append(QgsMapCanvasLayer(layer)) registered_layers.append(layer.id()) for layer in layers: if layer.id() not in registered_layers: final_layers.append(QgsMapCanvasLayer(layer)) self.canvas.setLayerSet(final_layers) # LOGGER.debug('Layer Count After: %s' % len(self.canvas.layers())) @pyqtSlot("QgsMapLayer") def addLayer(self, layer): """Handle a layer being added to the registry so it shows up in canvas. :param layer: list<QgsMapLayer> list of map layers that were added .. note: The QgsInterface api does not include this method, it is added here as a helper to facilitate testing. .. note: The addLayer method was deprecated in QGIS 1.8 so you should not need this method much. """ pass @pyqtSlot() def removeAllLayers(self,): """Remove layers from the canvas before they get deleted. .. note:: This is NOT part of the QGisInterface API but is needed to support QgsMapLayerRegistry.removeAllLayers(). """ self.canvas.setLayerSet([]) self.active_layer = None def newProject(self): """Create new project.""" # noinspection PyArgumentList QgsMapLayerRegistry.instance().removeAllMapLayers() # ---------------- API Mock for QgsInterface follows ------------------- def zoomFull(self): """Zoom to the map full extent.""" pass def zoomToPrevious(self): """Zoom to previous view extent.""" pass def zoomToNext(self): """Zoom to next view extent.""" pass def zoomToActiveLayer(self): """Zoom to extent of active layer.""" pass def addVectorLayer(self, path, base_name, provider_key): """Add a vector layer. :param path: Path to layer. :type path: str :param base_name: Base name for layer. :type base_name: str :param provider_key: Provider key e.g. 'ogr' :type provider_key: str """ pass def addRasterLayer(self, path, base_name): """Add a raster layer given a raster layer file name :param path: Path to layer. :type path: str :param base_name: Base name for layer. :type base_name: str """ pass def setActiveLayer(self, layer): """Set the currently active layer in the legend. :param layer: Layer to make active. :type layer: QgsMapLayer, QgsVectorLayer, QgsRasterLayer """ self.active_layer = layer def activeLayer(self): """Get pointer to the active layer (layer selected in the legend).""" if self.active_layer is not None: return self.active_layer else: return None def addToolBarIcon(self, action): """Add an icon to the plugins toolbar. :param action: Action to add to the toolbar. :type action: QAction """ pass def removeToolBarIcon(self, action): """Remove an action (icon) from the plugin toolbar. :param action: Action to add to the toolbar. :type action: QAction """ pass def addToolBar(self, name): """Add toolbar with specified name. :param name: Name for the toolbar. :type name: str """ pass def mapCanvas(self): """Return a pointer to the map canvas.""" return self.canvas def mainWindow(self): """Return a pointer to the main window. In case of QGIS it returns an instance of QgisApp. """ pass def addDockWidget(self, area, dock_widget): """Add a dock widget to the main window. :param area: Where in the ui the dock should be placed. :type area: :param dock_widget: A dock widget to add to the UI. :type dock_widget: QDockWidget """ pass def legendInterface(self): """Get the legend. See also discussion at: https://github.com/AIFDR/inasafe/pull/924/ Implementation added for version 3.2. """ return self.legend def messageBar(self): """Get the message bar. .. versionadded:: 3.2 :returns: A QGIS message bar instance :rtype: QgsMessageBar """ return self.message_bar
def print_atlas(project, layout_name, feature_filter, scales=None, scale=None): """Generate an atlas. :param project: The project to render as atlas. :type project: QgsProject :param layout_name: Name of the layout. :type layout_name: basestring :param feature_filter: QGIS Expression to use to select the feature. It can return many features, a multiple pages PDF will be returned. :type feature_filter: basestring :param scale: A scale to force in the atlas context. Default to None. :type scale: int :param scales: A list of predefined list of scales to force in the atlas context. Default to None. :type scales: list :return: Path to the PDF. :rtype: basestring """ canvas = QgsMapCanvas() bridge = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas) bridge.setCanvasLayers() manager = project.layoutManager() master_layout = manager.layoutByName(layout_name) if not master_layout: raise AtlasPrintException('Layout not found') if master_layout.layoutType() != QgsMasterLayoutInterface.PrintLayout: raise AtlasPrintException('The layout is not a print layout') for l in manager.printLayouts(): if l.name() == layout_name: layout = l break else: raise AtlasPrintException('The layout is not found') atlas = layout.atlas() if not atlas.enabled(): raise AtlasPrintException('The layout is not enabled for an atlas') settings = QgsLayoutExporter.PdfExportSettings() if scale: layout.referenceMap().setAtlasScalingMode(QgsLayoutItemMap.Fixed) layout.referenceMap().setScale(scale) if scales: layout.referenceMap().setAtlasScalingMode(QgsLayoutItemMap.Predefined) if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = scales else: layout.reportContext().setPredefinedScales(scales) layer = atlas.coverageLayer() feature_filter = optimize_expression(layer, feature_filter) expression = QgsExpression(feature_filter) if expression.hasParserError(): raise AtlasPrintException( 'Expression is invalid, parser error: {}'.format( expression.parserErrorString())) context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(project)) context.appendScope(QgsExpressionContextUtils.layoutScope(layout)) context.appendScope(QgsExpressionContextUtils.atlasScope(atlas)) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) expression.prepare(context) if expression.hasEvalError(): raise AtlasPrintException( 'Expression is invalid, eval error: {}'.format( expression.evalErrorString())) atlas.setFilterFeatures(True) atlas.setFilterExpression(feature_filter) if not scales and layout.referenceMap().atlasScalingMode( ) == QgsLayoutItemMap.Predefined: if Qgis.QGIS_VERSION_INT >= 30900: use_project = project.useProjectScales() map_scales = project.mapScales() else: map_scales = project_scales(project) use_project = len(map_scales) == 0 if not use_project or len(map_scales) == 0: QgsMessageLog.logMessage( 'Map scales not found in project, fetching predefined map scales in global config', 'atlasprint', Qgis.Info) map_scales = global_scales() if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = map_scales else: layout.reportContext().setPredefinedScales(map_scales) export_path = os.path.join(tempfile.gettempdir(), '{}_{}.pdf'.format(layout_name, uuid4())) exporter = QgsLayoutExporter(layout) result = exporter.exportToPdf(atlas, export_path, settings) if result[0] != QgsLayoutExporter.Success and not os.path.isfile( export_path): raise Exception('export not generated {}'.format(export_path)) return export_path
def print_atlas(project_path, composer_name, predefined_scales, feature_filter, page_name_expression=None): if not feature_filter: QgsMessageLog.logMessage("atlasprint: NO feature_filter provided !", 'atlasprint', Qgis.Critical) return None # Get composer from project # in QGIS 2, we can't get composers without iface # so we reading project xml and extract composer # TODO Since QGIS 3.0, we should be able to use project layoutManager() # noinspection PyPep8Naming from xml.etree import ElementTree as ET composer_xml = None with open(project_path, 'r') as f: tree = ET.parse(f) for elem in tree.findall('.//Composer[@title="%s"]' % composer_name): composer_xml = ET.tostring( elem, encoding='utf8', method='xml' ) if not composer_xml: for elem in tree.findall('.//Layout[@name="%s"]' % composer_name): composer_xml = ET.tostring( elem, encoding='utf8', method='xml' ) if not composer_xml: QgsMessageLog.logMessage("atlasprint: Composer XML not parsed !", 'atlasprint', Qgis.Critical) return None document = QDomDocument() document.setContent(composer_xml) # Get canvas, map setting & instantiate composition canvas = QgsMapCanvas() project = QgsProject() project.read(project_path) bridge = QgsLayerTreeMapCanvasBridge( project.layerTreeRoot(), canvas ) bridge.setCanvasLayers() layout = QgsPrintLayout(project) # Load content from XML layout.loadFromTemplate( document, QgsReadWriteContext(), ) atlas = layout.atlas() atlas.setEnabled(True) atlas_map = layout.referenceMap() atlas_map.setAtlasDriven(True) atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Predefined) layout.reportContext().setPredefinedScales(predefined_scales) if page_name_expression: atlas.setPageNameExpression(page_name_expression) # Filter feature here to avoid QGIS looping through every feature when doing : composition.setAtlasMode(QgsComposition.ExportAtlas) coverage_layer = atlas.coverageLayer() # Filter by FID as QGIS cannot compile expressions with $id or other $ vars # which leads to bad performance for big dataset use_fid = None if '$id' in feature_filter: import re ids = list(map(int, re.findall(r'\d+', feature_filter))) if len(ids) > 0: use_fid = ids[0] if use_fid: qReq = QgsFeatureRequest().setFilterFid(use_fid) else: qReq = QgsFeatureRequest().setFilterExpression(feature_filter) # Change feature_filter in order to improve performance pks = coverage_layer.dataProvider().pkAttributeIndexes() if use_fid and len(pks) == 1: pk = coverage_layer.dataProvider().fields()[pks[0]].name() feature_filter = '"%s" IN (%s)' % (pk, use_fid) QgsMessageLog.logMessage("atlasprint: feature_filter changed into: %s" % feature_filter, 'atlasprint', Qgis.Info) qReq = QgsFeatureRequest().setFilterExpression(feature_filter) atlas.setFilterFeatures(True) atlas.setFilterExpression(feature_filter) uid = uuid4() i = 0 # We use a single page for now. atlas.beginRender() atlas.seekTo(i) # setup settings settings = QgsLayoutExporter.PdfExportSettings() export_path = os.path.join( tempfile.gettempdir(), '%s_%s.pdf' % (atlas.nameForPage(i), uid) ) exporter = QgsLayoutExporter(layout) result = exporter.exportToPdf(export_path, settings) atlas.endRender() if result != QgsLayoutExporter.Success: QgsMessageLog.logMessage("atlasprint: export not generated %s" % export_path, 'atlasprint', Qgis.Critical) return None if not os.path.isfile(export_path): QgsMessageLog.logMessage("atlasprint: export not generated %s" % export_path, 'atlasprint', Qgis.Critical) return None QgsMessageLog.logMessage("atlasprint: path generated %s" % export_path, 'atlasprint', Qgis.Success) return export_path
def print_atlas(self, project_path, composer_name, predefined_scales, feature_filter=None, page_name_expression=None): if not feature_filter: QgsMessageLog.logMessage( "atlasprint: NO feature_filter provided !") return None # Get composer from project # in QGIS 2, canno get composers without iface # so we reading project xml and extract composer # in QGIS 3.0, we will use project layoutManager() from xml.etree import ElementTree as ET composer_xml = None with open(project_path, 'r') as f: tree = ET.parse(f) for elem in tree.findall('.//Composer[@title="%s"]' % composer_name): composer_xml = ET.tostring(elem, encoding='utf8', method='xml') if not composer_xml: QgsMessageLog.logMessage("atlasprint: Composer XML not parsed !") return None document = QDomDocument() document.setContent(composer_xml) # Get canvas, map setting & instantiate composition canvas = QgsMapCanvas() QgsProject.instance().read(QFileInfo(project_path)) bridge = QgsLayerTreeMapCanvasBridge( QgsProject.instance().layerTreeRoot(), canvas) bridge.setCanvasLayers() ms = canvas.mapSettings() composition = QgsComposition(ms) # Load content from XML substitution_map = {} composition.loadFromTemplate(document, substitution_map) # Get atlas for this composition atlas = composition.atlasComposition() atlas.setEnabled(True) atlas_map = composition.getComposerMapById(0) atlas_map.setAtlasScalingMode(QgsComposerMap.Predefined) # get project scales atlas.setPredefinedScales(predefined_scales) atlas_map.setAtlasDriven(True) #atlas.setComposerMap(atlas_map) if page_name_expression: atlas.setPageNameExpression(page_name_expression) # Filter feature here to avoid QGIS looping through every feature when doing : composition.setAtlasMode(QgsComposition.ExportAtlas) coverageLayer = atlas.coverageLayer() # Filter by FID as QGIS cannot compile expressions with $id or other $ vars # which leads to bad perfs for big datasets useFid = None if '$id' in feature_filter: import re ids = map(int, re.findall(r'\d+', feature_filter)) if len(ids) > 0: useFid = ids[0] if useFid: qReq = QgsFeatureRequest().setFilterFid(useFid) else: qReq = QgsFeatureRequest().setFilterExpression(feature_filter) # Change feature_filter in order to improve perfs pks = coverageLayer.dataProvider().pkAttributeIndexes() if useFid and len(pks) == 1: pk = coverageLayer.dataProvider().fields()[pks[0]].name() feature_filter = '"%s" IN (%s)' % (pk, useFid) QgsMessageLog.logMessage( "atlasprint: feature_filter changed into: %s" % feature_filter) qReq = QgsFeatureRequest().setFilterExpression(feature_filter) atlas.setFilterFeatures(True) atlas.setFeatureFilter(feature_filter) uid = uuid4() i = 0 # Set Atlas mode composition.setAtlasMode(QgsComposition.ExportAtlas) atlas.beginRender() for feat in coverageLayer.getFeatures(qReq): atlas.prepareForFeature(feat) export_path = os.path.join( tempfile.gettempdir(), '%s_%s.pdf' % (atlas.nameForPage(i), uid)) exported = composition.exportAsPDF(export_path) if not exported or not os.path.isfile(export_path): QgsMessageLog.logMessage( "atlasprint: An error occured while exporting the atlas !") return None break atlas.endRender() if os.path.isfile(export_path): QgsMessageLog.logMessage("atlasprint: path generated %s" % export_path) return export_path
class see_map(QDialog): #app2 = QgsApplication([], True) #app2.initQgis() def __init__(self, file_name): super().__init__() # Creación del Lienzo / Canvas self.canvas = QgsMapCanvas(self) self.setWindowTitle("Map of Track / Mapa del Recorrido") self.canvas.setCanvasColor(Qt.white) self.initGui() if not file_name == None: vlayer = QgsVectorLayer(file_name, "Track Converted", "ogr") #vlayer.updateExtents() self.project.instance().addMapLayer(vlayer) vlayer.renderer().symbol().setWidth(2) vlayer.renderer().symbol().setColor(QColor.fromRgb(250, 0, 0)) self.view.refreshLayerSymbology(vlayer.id()) uri = 'crs=EPSG:4326&dpiMode=7&format=image/jpeg&layers=IGNBaseTodo&styles=default&tileMatrixSet=EPSG:4326&url=http://www.ign.es/wmts/ign-base' map_spain = QgsRasterLayer(uri, "Spain", "wms") self.root.insertLayer(1, map_spain) self.project.instance().addMapLayer(map_spain) if not map_spain.isValid(): print("Track failed to load! /n" + file_name) else: print("Track Load Correct! " + file_name) else: uri = 'crs=EPSG:4326&dpiMode=7&format=image/jpeg&layers=IGNBaseTodo&styles=default&tileMatrixSet=EPSG:4326&url=http://www.ign.es/wmts/ign-base' map_spain = QgsRasterLayer(uri, "Spain", "wms") self.project.instance().addMapLayer(map_spain) if not map_spain.isValid(): print("Track failed to load! /n" + file_name) else: print("Track Load Correct! " + file_name) def zoomIn(self): self.canvas.setMapTool(self.toolZoomIn) def zoomOut(self): self.canvas.setMapTool(self.toolZoomOut) def pan(self): self.canvas.setMapTool(self.toolPan) def file(self): filename, _ = QFileDialog.getOpenFileName(self, 'Selecciona Fichero GPX', 'c:/', 'QGis (*.qgz)') if filename: self.project.read(filename) def initGui(self): icon = QIcon() icon.addPixmap( QPixmap( "C:/Roberto/Visual_Studio_Code/GisBike/programa/IMG/Qgis.png"), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.setWindowModality(Qt.WindowModal) self.setWindowFlags(Qt.Window | Qt.WindowSystemMenuHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) self.resize(1200, 600) self.verticalLayout_2 = QVBoxLayout(self) self.splitter = QSplitter(self) self.splitter.setOrientation(Qt.Horizontal) self.actionZoomIn = QPushButton("Zoom in", self.splitter) self.actionZoomOut = QPushButton("Zoom out", self.splitter) self.actionPan = QPushButton("Pan", self.splitter) self.actionFile = QPushButton("File", self.splitter) self.project = QgsProject.instance() self.project.read('C:/Users/Fcc/Desktop/QGis/pruebas2.qgz') self.root = QgsProject.instance().layerTreeRoot() self.bridge = QgsLayerTreeMapCanvasBridge(self.root, self.canvas) self.bridge.setCanvasLayers() self.bridge.setAutoSetupOnFirstLayer(True) #https://gis.stackexchange.com/questions/141516/adding-legend-to-canvas-in-standalone-pyqgis-application self.model = QgsLayerTreeModel(self.root) self.model.setFlag(QgsLayerTreeModel.AllowNodeReorder) self.model.setFlag(QgsLayerTreeModel.AllowNodeRename) self.model.setFlag(QgsLayerTreeModel.AllowNodeChangeVisibility) self.model.setFlag(QgsLayerTreeModel.ShowLegend) self.view = QgsLayerTreeView(self.splitter) self.view.setModel(self.model) self.view.setFixedWidth(150) #self.view.resize(150,600) self.widget = QWidget(self.splitter) self.verticalLayout = QVBoxLayout(self.widget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.addWidget(self.actionZoomIn) self.horizontalLayout.addWidget(self.actionZoomOut) self.horizontalLayout.addWidget(self.actionPan) self.horizontalLayout.addWidget(self.actionFile) self.verticalLayout.addLayout(self.horizontalLayout) self.verticalLayout.addWidget(self.canvas) self.verticalLayout_2.addWidget(self.splitter) self.actionZoomIn.clicked.connect(self.zoomIn) self.actionZoomOut.clicked.connect(self.zoomOut) self.actionPan.clicked.connect(self.pan) self.actionFile.clicked.connect(self.file) # create the map tools self.toolPan = QgsMapToolPan(self.canvas) self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # false = in self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # true = out
def print_layout(project, layout_name, feature_filter: str = None, scales=None, scale=None, **kwargs): """Generate a PDF for an atlas or a report. :param project: The QGIS project. :type project: QgsProject :param layout_name: Name of the layout of the atlas or report. :type layout_name: basestring :param feature_filter: QGIS Expression to use to select the feature. It can return many features, a multiple pages PDF will be returned. This is required to print atlas, not report :type feature_filter: basestring :param scale: A scale to force in the atlas context. Default to None. :type scale: int :param scales: A list of predefined list of scales to force in the atlas context. Default to None. :type scales: list :return: Path to the PDF. :rtype: basestring """ canvas = QgsMapCanvas() bridge = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas) bridge.setCanvasLayers() manager = project.layoutManager() master_layout = manager.layoutByName(layout_name) settings = QgsLayoutExporter.PdfExportSettings() atlas = None atlas_layout = None report_layout = None logger = Logger() if not master_layout: raise AtlasPrintException('Layout `{}` not found'.format(layout_name)) if master_layout.layoutType() == QgsMasterLayoutInterface.PrintLayout: for _print_layout in manager.printLayouts(): if _print_layout.name() == layout_name: atlas_layout = _print_layout break atlas = atlas_layout.atlas() if not atlas.enabled(): raise AtlasPrintException('The layout is not enabled for an atlas') layer = atlas.coverageLayer() if feature_filter is None: raise AtlasPrintException( 'EXP_FILTER is mandatory to print an atlas layout') feature_filter = optimize_expression(layer, feature_filter) expression = QgsExpression(feature_filter) if expression.hasParserError(): raise AtlasPrintException( 'Expression is invalid, parser error: {}'.format( expression.parserErrorString())) context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(project)) context.appendScope( QgsExpressionContextUtils.layoutScope(atlas_layout)) context.appendScope(QgsExpressionContextUtils.atlasScope(atlas)) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) expression.prepare(context) if expression.hasEvalError(): raise AtlasPrintException( 'Expression is invalid, eval error: {}'.format( expression.evalErrorString())) atlas.setFilterFeatures(True) atlas.setFilterExpression(feature_filter) if scale: atlas_layout.referenceMap().setAtlasScalingMode( QgsLayoutItemMap.Fixed) atlas_layout.referenceMap().setScale(scale) if scales: atlas_layout.referenceMap().setAtlasScalingMode( QgsLayoutItemMap.Predefined) if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = scales else: atlas_layout.reportContext().setPredefinedScales(scales) if not scales and atlas_layout.referenceMap().atlasScalingMode( ) == QgsLayoutItemMap.Predefined: if Qgis.QGIS_VERSION_INT >= 30900: use_project = project.useProjectScales() map_scales = project.mapScales() else: map_scales = project_scales(project) use_project = len(map_scales) == 0 if not use_project or len(map_scales) == 0: logger.info( 'Map scales not found in project, fetching predefined map scales in global config' ) map_scales = global_scales() if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = map_scales else: atlas_layout.reportContext().setPredefinedScales(map_scales) elif master_layout.layoutType() == QgsMasterLayoutInterface.Report: report_layout = master_layout else: raise AtlasPrintException('The layout is not supported by the plugin') for key, value in kwargs.items(): found = False if atlas_layout: item = atlas_layout.itemById(key.lower()) if isinstance(item, QgsLayoutItemLabel): item.setText(value) found = True logger.info( 'Additional parameters: {} found in layout {}, value {}'.format( key, found, value)) export_path = os.path.join(tempfile.gettempdir(), '{}_{}.pdf'.format(layout_name, uuid4())) result, error = QgsLayoutExporter.exportToPdf(atlas or report_layout, export_path, settings) if result != QgsLayoutExporter.Success and not os.path.isfile(export_path): raise Exception('export not generated {} ({})'.format( export_path, error)) return export_path
print layer.name() #show and set map canvas canvas = QgsMapCanvas() canvas.setCanvasColor(Qt.white) #canvas.setCanvasColor(Qt.red) canvas.enableAntiAliasing(True) # set extent to the extent of our layer canvas.setExtent(baselayer.extent()) # Load our project bridge = QgsLayerTreeMapCanvasBridge(QgsProject.instance().layerTreeRoot(), canvas) #QgsProject.instance().read(QFileInfo(project_path)) bridge.setCanvasLayers() canvas.show() #---------------------------------------------------------------------------------------------------------------------------------------- #Part 2. Select local .shp file and load as vector layer #---------------------- from PyQt4.QtCore import * #PyQt4.QtCore --> QFileInfo from PyQt4.QtGui import * # PyQt4.QtGui --> QApplication import qgis.core #qgis.core --> QgsProject, QgsComposition, QgsApplication, QgsProviderRegistry import qgis.gui #adds additional gui components #qgis.gui --> QgsMapCanvas, QgsLayerTreeMapCanvasBridge from glob import glob
def print_layout( project: QgsProject, layout_name: str, output_format: OutputFormat, feature_filter: str = None, scales: list = None, scale: int = None, **kwargs, ): """Generate a PDF for an atlas or a report. :param project: The QGIS project. :type project: QgsProject :param layout_name: Name of the layout of the atlas or report. :type layout_name: basestring :param feature_filter: QGIS Expression to use to select the feature. It can return many features, a multiple pages PDF will be returned. This is required to print atlas, not report :type feature_filter: basestring :param scale: A scale to force in the atlas context. Default to None. :type scale: int :param scales: A list of predefined list of scales to force in the atlas context. Default to None. :type scales: list :param output_format: The output format, default to PDF if not provided. :return: Path to the PDF. :rtype: basestring """ canvas = QgsMapCanvas() bridge = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas) bridge.setCanvasLayers() manager = project.layoutManager() master_layout = manager.layoutByName(layout_name) if output_format == OutputFormat.Svg: settings = QgsLayoutExporter.SvgExportSettings() elif output_format in (OutputFormat.Png, OutputFormat.Jpeg): settings = QgsLayoutExporter.ImageExportSettings() else: # PDF by default settings = QgsLayoutExporter.PdfExportSettings() atlas = None atlas_layout = None report_layout = None logger = Logger() if not master_layout: raise AtlasPrintException("Layout `{}` not found".format(layout_name)) if master_layout.layoutType() == QgsMasterLayoutInterface.PrintLayout: for _print_layout in manager.printLayouts(): if _print_layout.name() == layout_name: atlas_layout = _print_layout break atlas = atlas_layout.atlas() if not atlas.enabled(): raise AtlasPrintException("The layout is not enabled for an atlas") layer = atlas.coverageLayer() if feature_filter is None: raise AtlasPrintException( "EXP_FILTER is mandatory to print an atlas layout") feature_filter = optimize_expression(layer, feature_filter) expression = QgsExpression(feature_filter) if expression.hasParserError(): raise AtlasPrintException( "Expression is invalid, parser error: {}".format( expression.parserErrorString())) context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(project)) context.appendScope( QgsExpressionContextUtils.layoutScope(atlas_layout)) context.appendScope(QgsExpressionContextUtils.atlasScope(atlas)) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) expression.prepare(context) if expression.hasEvalError(): raise AtlasPrintException( "Expression is invalid, eval error: {}".format( expression.evalErrorString())) atlas.setFilterFeatures(True) atlas.setFilterExpression(feature_filter) atlas.updateFeatures() if scale: atlas_layout.referenceMap().setAtlasScalingMode( QgsLayoutItemMap.Fixed) atlas_layout.referenceMap().setScale(scale) if scales: atlas_layout.referenceMap().setAtlasScalingMode( QgsLayoutItemMap.Predefined) settings.predefinedMapScales = scales if (not scales and atlas_layout.referenceMap().atlasScalingMode() == QgsLayoutItemMap.Predefined): use_project = project.useProjectScales() map_scales = project.mapScales() if not use_project or len(map_scales) == 0: logger.info( "Map scales not found in project, fetching predefined map scales in global config" ) map_scales = global_scales() settings.predefinedMapScales = map_scales elif master_layout.layoutType() == QgsMasterLayoutInterface.Report: report_layout = master_layout else: raise AtlasPrintException("The layout is not supported by the plugin") for key, value in kwargs.items(): found = False if atlas_layout: item = atlas_layout.itemById(key.lower()) if isinstance(item, QgsLayoutItemLabel): item.setText(value) found = True logger.info( 'Additional parameters "{key}" {found} in layout, value "{value}"'. format(key=key, found="found" if found else "not found", value=value)) file_name = "{}_{}.{}".format(clean_string(layout_name), uuid4(), output_format.name.lower()) export_path = Path(tempfile.gettempdir()).joinpath(file_name) Logger().info("Exporting the request in {} using {}".format( export_path, output_format.value)) if output_format in (OutputFormat.Png, OutputFormat.Jpeg): exporter = QgsLayoutExporter(atlas_layout or report_layout) result = exporter.exportToImage(str(export_path), settings) error = result_message(result) elif output_format in (OutputFormat.Svg, ): exporter = QgsLayoutExporter(atlas_layout or report_layout) result = exporter.exportToSvg(str(export_path), settings) error = result_message(result) else: # Default to PDF result, error = QgsLayoutExporter.exportToPdf(atlas or report_layout, str(export_path), settings) # Let's override error message _ = error error = result_message(result) if result != QgsLayoutExporter.Success: raise Exception("Export not generated in QGIS exporter {} : {}".format( export_path, error)) if not export_path.is_file(): logger.warning( "No error from QGIS Exporter, but the file does not exist.\n" "Message from QGIS exporter : {}\n" "File path : {}\n".format(error, export_path)) raise Exception( "Export OK from QGIS, but file not found on the file system : {}". format(export_path)) return export_path
def responseComplete(self): request = self.serverIface.requestHandler() params = request.parameterMap( ) # Check if dynamic layers params are passed # If not, do not change QGIS Server response if params['SERVICE'].lower() != 'dynamiclayers': return # Check if needed params are set if 'DLSOURCELAYER' not in params or 'DLEXPRESSION' not in params: # Change response request.clearHeaders() request.setInfoFormat('text/json') request.setHeader('Status', '200') request.setHeader('Content-type', 'text/json') request.clearBody() body = { 'status': 0, 'message': 'Missing parameters DLSOURCELAYER or DLEXPRESSION', 'childProject': None } request.appendBody( json.dumps( body ) ) return # Get layer and expression player = params['DLSOURCELAYER'] pexp = params['DLEXPRESSION'] #~ QgsMessageLog.logMessage( "DynamicLayers - layer = %s - expression = %s" % ( player, pexp )) # Open project pmap = params['MAP'] self.projectPath = pmap pfile = QFileInfo( pmap ) p = QgsProject.instance() # Define canvas and layer treet root # Needed to write canvas and layer-tree-root in project file canvas = QgsMapCanvas() treeRoot = p.layerTreeRoot() bridge = QgsLayerTreeMapCanvasBridge( treeRoot, canvas ) bridge.setCanvasLayers() canvas.zoomToFullExtent() self.canvas = canvas self.bridge = bridge self.composers = [] self.project = p self.project.readProject.connect( bridge.readProject ) self.project.readProject.connect( self.loadComposersFromProject ) self.project.writeProject.connect( bridge.writeProject ) self.project.writeProject.connect( self.writeOldLegend ) self.project.writeProject.connect( self.writeComposers ) # read project p.read( pfile ) # Get an instance of engine class dle = DynamicLayersEngine() # Set the dynamic layers list dle.setDynamicLayersList() if not dle.dynamicLayers: QgsMessageLog.logMessage( "DynamicLayers - no dynamic layers found") # Change response request.clearHeaders() request.setInfoFormat('text/json') request.setHeader('Status', '200') request.setHeader('Content-type', 'text/json') request.setHeader('Content-Disposition', 'attachment; filename="DynamicLayers.json"') request.clearBody() body = { 'status': 0, 'message': 'No dynamic layers found in parent project', 'childProject': None } request.appendBody( json.dumps( body ) ) return # Set search and replace dictionary lr = QgsMapLayerRegistry.instance() sourceLayerList = [ layer for lname,layer in lr.mapLayers().items() if layer.name() == player ] if len(sourceLayerList ) != 1: QgsMessageLog.logMessage( "DynamicLayers - source layer not in project") # Change response request.clearHeaders() request.setInfoFormat('text/json') request.setHeader('Status', '200') request.setHeader('Content-type', 'text/json') request.setHeader('Content-Disposition', 'attachment; filename="DynamicLayers.json"') request.clearBody() body = { 'status': 0, 'message': 'The source layer cannot be found in the project', 'childProject': None } request.appendBody( json.dumps( body ) ) return sourceLayer = sourceLayerList[0] dle.setSearchAndReplaceDictionaryFromLayer( sourceLayer, pexp ) self.searchAndReplaceDictionary = dle.searchAndReplaceDictionary # Get child name computed path, and check if it is already there or not childPath = self.getChildProjectName( pmap, player, pexp ) self.childPath = childPath if os.path.exists( childPath ): if os.path.getmtime( childPath ) > os.path.getmtime( pmap ): QgsMessageLog.logMessage( 'DynamicLayer - Parent older than child : do not recreate child project') # Change response request.clearHeaders() request.setInfoFormat('text/json') request.setHeader('Status', '200') request.setHeader('Content-type', 'text/json') request.setHeader('Content-Disposition', 'attachment; filename="DynamicLayers.json"') request.clearBody() body = { 'status': 1, 'message': 'Child project is already up-to-date', 'childProject': os.path.basename(childPath) } request.appendBody( json.dumps( body ) ) return else: QgsMessageLog.logMessage( 'DynamicLayer - Must recreate the child project') # Change layers datasource dle.setDynamicLayersDatasourceFromDic( ) # Set project properties dle.setDynamicProjectProperties() # Set extent layer extentLayerIdGet = p.readEntry('PluginDynamicLayers' , 'ExtentLayer') if extentLayerIdGet: extentLayerId = extentLayerIdGet[0] extentLayerList = [ layer for lid,layer in lr.mapLayers().items() if layer.id() == extentLayerId ] if len(extentLayerList) == 1: dle.setExtentLayer( extentLayerList[0] ) # Set extent margin extentMarginGet = p.readEntry('PluginDynamicLayers' , 'ExtentMargin') if extentMarginGet: extentMargin = int( extentMarginGet[0] ) else: extentMargin = 20 dle.setExtentMargin( extentMargin ) # Set new extent newExtent = dle.setProjectExtent() self.extent = newExtent # Zoom to extent Layer if newExtent: self.canvas.setExtent( newExtent ) # Create suffix to append after layers id # prevent cache issues self.layerIdSuffix = int( time.time() ) # Save child project childProject = self.saveChildProject() # Save child project lizmap configuration if os.path.exists( self.projectPath + '.cfg' ): self.writeLizmapChildProjectConfig() if childProject: # Change response request.clearHeaders() request.setInfoFormat('text/json') request.setHeader('Status', '200') request.setHeader('Content-type', 'text/json') request.setHeader('Content-Disposition', 'attachment; filename="DynamicLayers.json"') request.clearBody() body = { 'status': 1, 'message': 'Child project has been updated', 'childProject': os.path.basename(childPath) } request.appendBody( json.dumps( body ) ) else: # Change response request.clearHeaders() request.setInfoFormat('text/json') request.setHeader('Status', '200') request.setHeader('Content-type', 'text/json') request.setHeader('Content-Disposition', 'attachment; filename="DynamicLayers.json"') request.clearBody() body = { 'status': 0, 'message': 'Error while creating child project', 'childProject': None } request.appendBody( json.dumps( body ) ) return