def testSubstitutionMap(self): """Test that we can use degree symbols in substitutions. """ # Create a point and convert it to text containing a degree symbol. myPoint = QgsPoint(12.3, -33.33) myCoordinates = myPoint.toDegreesMinutesSeconds(2) myTokens = myCoordinates.split(',') myLongitude = myTokens[0] myLatitude = myTokens[1] myText = 'Latitude: %s, Longitude: %s' % (myLatitude, myLongitude) # Load the composition with the substitutions myComposition = QgsComposition(QgsProject.instance()) mySubstitutionMap = {'replace-me': myText} myFile = os.path.join(TEST_DATA_DIR, 'template-for-substitution.qpt') with open(myFile) as f: myTemplateContent = f.read() myDocument = QDomDocument() myDocument.setContent(myTemplateContent) myComposition.loadFromTemplate(myDocument, mySubstitutionMap) # We should be able to get map0 myMap = myComposition.getComposerMapById(0) myMessage = ('Map 0 could not be found in template %s', myFile) assert myMap is not None, myMessage
def testSubstitutionMap(self): """Test that we can use degree symbols in substitutions. """ # Create a point and convert it to text containing a degree symbol. myPoint = QgsPoint(12.3, -33.33) myCoordinates = myPoint.toDegreesMinutesSeconds(2) myTokens = myCoordinates.split(',') myLongitude = myTokens[0] myLatitude = myTokens[1] myText = 'Latitude: %s, Longitude: %s' % (myLatitude, myLongitude) # Load the composition with the substitutions myComposition = QgsComposition(self.iface.mapCanvas().mapRenderer()) mySubstitutionMap = {'replace-me': myText} myFile = os.path.join(TEST_DATA_DIR, 'template-for-substitution.qpt') myTemplateFile = file(myFile, 'rt') myTemplateContent = myTemplateFile.read() myTemplateFile.close() myDocument = QDomDocument() myDocument.setContent(myTemplateContent) myComposition.loadFromTemplate(myDocument, mySubstitutionMap) # We should be able to get map0 myMap = myComposition.getComposerMapById(0) myMessage = ('Map 0 could not be found in template %s', myFile) assert myMap is not None, myMessage
def testPrintMapFromTemplate(self): """Test that we can get a map to render in the template.""" myPath = os.path.join(TEST_DATA_DIR, 'landsat.tif') myFileInfo = QFileInfo(myPath) myRasterLayer = QgsRasterLayer(myFileInfo.filePath(), myFileInfo.completeBaseName()) myRenderer = QgsMultiBandColorRenderer( myRasterLayer.dataProvider(), 2, 3, 4 ) #mRasterLayer.setRenderer( rasterRenderer ) myPipe = myRasterLayer.pipe() assert myPipe.set(myRenderer), "Cannot set pipe renderer" QgsMapLayerRegistry.instance().addMapLayers([myRasterLayer]) myMapRenderer = QgsMapRenderer() myLayerStringList = [] myLayerStringList.append(myRasterLayer.id()) myMapRenderer.setLayerSet(myLayerStringList) myMapRenderer.setProjectionsEnabled(False) myComposition = QgsComposition(myMapRenderer) myFile = os.path.join(TEST_DATA_DIR, 'template-for-substitution.qpt') myTemplateFile = file(myFile, 'rt') myTemplateContent = myTemplateFile.read() myTemplateFile.close() myDocument = QDomDocument() myDocument.setContent(myTemplateContent) myComposition.loadFromTemplate(myDocument) # now render the map, first zooming to the raster extents myMap = myComposition.getComposerMapById(0) myMessage = ('Map 0 could not be found in template %s', myFile) assert myMap is not None, myMessage myExtent = myRasterLayer.extent() myMap.setNewExtent(myExtent) myImagePath = os.path.join(str(QDir.tempPath()), 'template_map_render_python.png') myPageNumber = 0 myImage = myComposition.printPageAsRaster(myPageNumber) myImage.save(myImagePath) assert os.path.exists(myImagePath), 'Map render was not created.' # Not sure if this is a predictable way to test but its quicker than # rendering. myFileSize = QFileInfo(myImagePath).size() myExpectedFileSize = 100000 myMessage = ('Expected file size to be greater than %s, got %s' ' for %s' % (myExpectedFileSize, myFileSize, myImagePath)) assert myFileSize > myExpectedFileSize, myMessage
def testPrintMapFromTemplate(self): """Test that we can get a map to render in the template.""" myPath = os.path.join(TEST_DATA_DIR, 'landsat.tif') myFileInfo = QFileInfo(myPath) myRasterLayer = QgsRasterLayer(myFileInfo.filePath(), myFileInfo.completeBaseName()) myRenderer = QgsMultiBandColorRenderer( myRasterLayer.dataProvider(), 2, 3, 4 ) #mRasterLayer.setRenderer( rasterRenderer ) myPipe = myRasterLayer.pipe() assert myPipe.set( myRenderer ), "Cannot set pipe renderer" QgsMapLayerRegistry.instance().addMapLayers([myRasterLayer]) myMapRenderer = QgsMapRenderer() myLayerStringList = [] myLayerStringList.append(myRasterLayer.id()) myMapRenderer.setLayerSet(myLayerStringList) myMapRenderer.setProjectionsEnabled(False) myComposition = QgsComposition(myMapRenderer) myFile = os.path.join(TEST_DATA_DIR, 'template-for-substitution.qpt') myTemplateFile = file(myFile, 'rt') myTemplateContent = myTemplateFile.read() myTemplateFile.close() myDocument = QDomDocument() myDocument.setContent(myTemplateContent) myComposition.loadFromTemplate(myDocument) # now render the map, first zooming to the raster extents myMap = myComposition.getComposerMapById(0) myMessage = ('Map 0 could not be found in template %s', myFile) assert myMap is not None, myMessage myExtent = myRasterLayer.extent() myMap.setNewExtent(myExtent) myImagePath = os.path.join(str(QDir.tempPath()), 'template_map_render_python.png') myPageNumber = 0 myImage = myComposition.printPageAsRaster(myPageNumber) myImage.save(myImagePath) assert os.path.exists(myImagePath), 'Map render was not created.' # Not sure if this is a predictable way to test but its quicker than # rendering. myFileSize = QFileInfo(myImagePath).size() myExpectedFileSize = 100000 myMessage = ('Expected file size to be greater than %s, got %s' ' for %s' % (myExpectedFileSize, myFileSize, myImagePath)) assert myFileSize > myExpectedFileSize, myMessage
def testNoSubstitutionMap(self): """Test that we can get a map if we use no text substitutions.""" myComposition = QgsComposition(QgsProject.instance()) myFile = os.path.join(TEST_DATA_DIR, 'template-for-substitution.qpt') with open(myFile) as f: myTemplateContent = f.read() myDocument = QDomDocument() myDocument.setContent(myTemplateContent) myComposition.loadFromTemplate(myDocument) # We should be able to get map0 myMap = myComposition.getComposerMapById(0) myMessage = ('Map 0 could not be found in template %s', myFile) assert myMap is not None, myMessage
def testNoSubstitutionMap(self): """Test that we can get a map if we use no text substitutions.""" myComposition = QgsComposition(self.iface.mapCanvas().mapRenderer()) myFile = os.path.join(TEST_DATA_DIR, 'template-for-substitution.qpt') with open(myFile) as f: myTemplateContent = f.read() myDocument = QDomDocument() myDocument.setContent(myTemplateContent) myComposition.loadFromTemplate(myDocument) # We should be able to get map0 myMap = myComposition.getComposerMapById(0) myMessage = ('Map 0 could not be found in template %s', myFile) assert myMap is not None, myMessage
def testNoSubstitutionMap(self): """Test that we can get a map if we use no text substitutions.""" myComposition = QgsComposition(CANVAS.mapRenderer()) myFile = os.path.join(TEST_DATA_DIR, 'template-for-substitution.qpt') myTemplateFile = file(myFile, 'rt') myTemplateContent = myTemplateFile.read() myTemplateFile.close() myDocument = QDomDocument() myDocument.setContent(myTemplateContent) myComposition.loadFromTemplate(myDocument) # We should be able to get map0 myMap = myComposition.getComposerMapById(0) myMessage = ('Map 0 could not be found in template %s', myFile) assert myMap is not None, myMessage
def export_view(self): ''' Export current view to PDF ''' # Load template from file s = QSettings() f = s.value("cadastre/composerTemplateFile", '', type=str) if not os.path.exists(f): f = '%s/composers/paysage_a4.qpt' % os.path.dirname(__file__) s.setValue("cadastre/composerTemplateFile", f) QApplication.setOverrideCursor(Qt.WaitCursor) tf = file(f, 'rt') tc= tf.read() tf.close() d= QDomDocument() d.setContent(tc) # Create composition ms = self.iface.mapCanvas().mapSettings() c = QgsComposition(ms) c.loadFromTemplate(d) c.setPlotStyle(QgsComposition.Print) #c.setPrintResolution(300) # Set map canvas = self.iface.mapCanvas() cm = c.getComposerMapById(0) extent = canvas.extent() scale = canvas.scale() cm.setMapCanvas(canvas) if extent: cm.zoomToExtent(extent) if scale: cm.setNewScale(scale) # Export tempDir = s.value("cadastre/tempDir", '%s' % tempfile.gettempdir(), type=str) self.targetDir = tempfile.mkdtemp('', 'cad_export_', tempDir) temp = int(time()*100) temppath = os.path.join(tempDir, 'export_cadastre_%s.pdf' % temp) c.exportAsPDF(temppath) QApplication.restoreOverrideCursor() if os.path.exists(temppath): cadastre_common.openFile(temppath)
def printToPdf(self, params): self.check_required_params(params) with change_directory(self.project_root): crs = QgsCoordinateReferenceSystem() crs.createFromSrid(params.get('srs')) mapRenderer = QgsMapRenderer() mapUnits = crs.mapUnits() mapRenderer.setMapUnits(mapUnits) mapExtent = QgsRectangle(*params.get('bbox')) mapRenderer.setExtent(mapExtent) le = QgsPalLabeling() mapRenderer.setLabelingEngine(le) layers = params.get('layers') self.setTransparencies(layers, params.get('transparencies')) mapRenderer.setLayerSet(layers) composer = ( self.getLayoutbyName(params['layout']) .firstChildElement('Composition') ) comp = QgsComposition(mapRenderer) comp.setPlotStyle(QgsComposition.Print) comp.readXML(composer, self.doc) # read composition elements comp.addItemsFromXML(composer, self.doc) comp.setPrintResolution(90) # set bbox for the first Map in the layout comp_map = comp.getComposerMapById(0) comp_map.setNewExtent(QgsRectangle(*params.get('bbox'))) # comp_map.setNewScale(10000) # comp_map.setLayerSet(layers) # comp_map.setKeepLayerSet(True) # save the file comp.exportAsPDF(params['tmpFile'] + '.pdf')
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
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) ms = canvas.mapSettings() composition = QgsComposition(ms) composition.loadFromTemplate(document, {}) # You must set the id in the template #map_item = composition.getComposerItemById('map') map_item = composition.getComposerMapById(1) #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() dpmm = dpi / 25.4 #width = int(dpmm * composition.paperWidth()) width = int(1400) print(width) #height = int(dpmm * 141) height = int(1000) print(height)
def exportToPdf(self, print_context, targetFile=None): self.iface.mapCanvas().setDestinationCrs( self.settings_instance.projection.crs()) myComposition = QgsComposition(self.iface.mapCanvas().mapSettings()) template = self.env.get_template(print_context['template']) custom_qpt = template.render(CONTEXT=print_context) myDocument = QDomDocument() myDocument.setContent(custom_qpt) myComposition.loadFromTemplate(myDocument) suggestedFile = os.path.join( self.settings_instance.projectFolderPath.text(), print_context['title'] + ".pdf") if not targetFile: targetFile = QFileDialog.getSaveFileName( None, "Export " + print_context['job'], suggestedFile, "*.pdf") interactive = True if not targetFile: return else: interactive = None outputDir = tempfile.gettempdir() with open(os.path.join(targetFile + '.qpt'), "wb") as qpt_file: qpt_file.write(custom_qpt) if print_context['type'] == 'report': myComposition.exportAsPDF(targetFile) elif print_context['type'] == 'map': print myComposition.getComposerMapById(0) print myComposition.getComposerItemById('5') for composer_map in myComposition.composerMapItems(): print composer_map, composer_map.id() fdtm_extent = None for layer in [ self.settings_instance.EPpLayer, self.settings_instance.EApLayer, self.settings_instance.WRLayer, self.settings_instance.WDSLayer ]: if layer.featureCount() > 0: if fdtm_extent: fdtm_extent.combineExtentWith(layer.extent()) else: fdtm_extent = layer.extent() fdtm_extent.scale(1.1) composer_map.zoomToExtent(fdtm_extent) composer_map.updateItem() myComposition.refreshItems() myComposition.exportAsPDF(targetFile) elif print_context['type'] == 'mapppp': print print_context myComposition = QgsComposition( self.iface.mapCanvas().mapSettings()) myComposition.setPlotStyle(QgsComposition.Print) myComposition.setPaperSize(297, 210) composer_map = QgsComposerMap(myComposition, 10, 10, 190, 190) fdtm_extent = self.settings_instance.EPpLayer.extent() for layer in [ self.settings_instance.EApLayer, self.settings_instance.WRLayer, self.settings_instance.WDSLayer ]: fdtm_extent.combineExtentWith(layer.extent()) composer_map.zoomToExtent(fdtm_extent) composer_map.updateItem() myComposition.addItem(composer_map) table = QgsComposerAttributeTable(myComposition) table.setItemPosition(205, 170) table.setVectorLayer(QgsMapLayerRegistry.instance().mapLayer( print_context['id'])) table.setMaximumNumberOfFeatures(20) table.setFilterFeatures(True) col1 = QgsComposerTableColumn() col1.setAttribute('types') col1.setHeading("types") col2 = QgsComposerTableColumn() col2.setAttribute('project units') col2.setHeading("project units") col3 = QgsComposerTableColumn() col3.setAttribute('Areas') col3.setHeading("Areas") col4 = QgsComposerTableColumn() col4.setAttribute('Lengths') col4.setHeading("Lengths") col5 = QgsComposerTableColumn() col5.setAttribute('Cost') col5.setHeading("Cost") table.setColumns([col1, col2, col3, col4, col5]) myComposition.addItem(table) myComposition.exportAsPDF(targetFile) elif print_context['type'] == 'atlas': myComposition.setAtlasMode(QgsComposition.ExportAtlas) for composer_map in myComposition.composerMapItems(): print composer_map, composer_map.id() atlas = myComposition.atlasComposition() atlas.setComposerMap(composer_map) #DEPRECATED atlas.setPredefinedScales(self.PREDEFINED_SCALES) composer_map.setAtlasDriven(True) composer_map.setAtlasScalingMode(QgsComposerMap.Predefined) atlas.beginRender() rendered_pdf = [] progress = progressBar(self, "exporting " + print_context['job'], atlas.numFeatures()) for i in range(0, atlas.numFeatures()): atlas.prepareForFeature(i) current_filename = atlas.currentFilename() file_name = '_'.join(current_filename.split()) file_path = '%s.pdf' % file_name path = os.path.join(outputDir, file_path) myComposition.exportAsPDF(path) rendered_pdf.append(path) progress.setStep(i) progress.stop(print_context['job'] + "exported to " + targetFile) atlas.endRender() merge_pdfs(rendered_pdf, targetFile) if interactive: open_file(targetFile) return targetFile
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