1

I am trying to code a standalone QGIS application that is able to print a composed map that zooms in the same layer every time I call it. The feature that have to be zoomed in change its location when is regenerated so my map application has to zoom in to a different place when I call it. I have been preparing an Atlas composer but when I call the print Python function it keeps the same area, it does not zoom to the chosen Atlas Layer. Another possibility is to zoom in to my layer every time I call the mapper, but I can't achieve it. I am adapting a code I found in the following Git repo without success: https://github.com/rjspiers/qgis-standalone-map-export

from qgis.core import *
import sys

print 'Hello from QGIS'

from qgis.core import (QgsProject, QgsComposition, QgsApplication, QgsProviderRegistry)
from qgis.gui import QgsMapCanvas, QgsLayerTreeMapCanvasBridge
from PyQt4.QtCore import QFileInfo, QObject
from PyQt4.QtXml import QDomDocument


gui_flag = True
app = QgsApplication(sys.argv, gui_flag)

# Make sure QGIS_PREFIX_PATH is set in your env if needed!
app.initQgis()

# project.qgs
project_path = r'D:\Fmesalessimulation\Simulator\qgis-standalone-map-export-master\smartfee_map.qgs'  # absolute filepath example: 'C:/folder/subfolder/project.qgs'

# template.qpt
template_path = r'D:\Fmesalessimulation\Simulator\qgis-standalone-map-export-master\smartfee_maptemplate.qpt'

#LayerIds
unused = 'BOUGHT_PAYS_DIFF20170130111140143'
sailedthrough = 'BOUGHT_UNITS20170130111140159'
optimalunits = 'PAYS_UNITS20170130111140165'
boundingbox = 'BOUNDING_BOX20170130111140161'


def make_pdf():
    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() == 'BOUNDING_BOX':
            lyr = layer
            break
    # lyr.setSubsetString(filter_expression)
    #################
    list_layers = []
    for f in lyr.getFeatures():
        if f['unit_name'] != '':
            list_layers.append(f.id())
    print list_layers
    lyr.setSelectedFeatures(list_layers)
    box = lyr.boundingBoxOfSelected()
    lyr.setSelectedFeatures([])
    canvas.setExtent(box)
    canvas.refresh()
    canvas.show()
    #################
    # 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': 'PyQGIS test'}
    # substitution_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(r'D:\Fmesalessimulation\Simulator\OUTPUT\JPG\PaysComparison.pdf')
    QgsProject.instance().clear()

make_pdf()

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.