I am looking for a way to print a custom feature form created in PyQt Designer for QGIS 2.4 using PyQGIS. My goal is to print/save image as the current extent of the map with the selected feature's attributes of interest on the same page.
I'm experimenting with two different ways:
First, is to use QgsComposition and QPrinter to add and print items to a pdf: including the map, legend, and attributes. My issue here is getting the only the desired attributes to display dynamically changing depending on the active layer. If I could add my feature form as a map item, I would be displaying the attributes added to the custom form.
UPDATE: The following code may be able to display my map with a legend and selective table, but I still have many issues with the map items (no text in the table, positioning, unable to include only desired layer in legend). I've included all the code associated with this print composer:
layer = qgis.utils.iface.activeLayer()
qgis.utils.iface.actionZoomToSelected().trigger()
qgis.utils.iface.mapCanvas().zoomScale(1000)
mapRenderer = iface.mapCanvas().mapRenderer()
c = QgsComposition(mapRenderer)
c.setPlotStyle(QgsComposition.Print)
x, y = 0, 0
w, h = c.paperWidth(), c.paperHeight()
composerMap = QgsComposerMap(c, x,y,w*.75,h)
c.addItem(composerMap)
legend = QgsComposerLegend(c)
c.addComposerLegend(legend)
legend.model().setLayerSet(mapRenderer.layerSet())
legend.setTitle('')
legendModel = QgsLegendModel(c)
legendModel.setLayerSet([layer.id()])
legend.updateLegend()
selected_ids = [f.id() for f in layer.selectedFeatures()]
filter_id_string = ','.join([str(id) for id in selected_ids])
table = QgsComposerAttributeTable(c)
table.setVectorLayer(layer)
table.setMaximumNumberOfFeatures(20)
table.setFeatureFilter("id in (" + filter_id_string + ")")
table.setFilterFeatures(True)
table.setItemPosition(x+50, y+50)
table.applyDefaultSize()
col1 = QgsComposerTableColumn()
col1.setAttribute('Diametre')
col2 = QgsComposerTableColumn()
col2.setAttribute('Nature')
table.setColumns([col1, col2])
c.addItem(table)
printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName('out.pdf')
printer.setPaperSize(QSizeF(c.paperWidth(), c.paperHeight()), QPrinter.Millimeter)
printer.setFullPage(True)
printer.setColorMode(QPrinter.Color)
printer.setResolution(c.printResolution())
pdfPainter = QPainter(printer)
paperRectMM = printer.pageRect(QPrinter.Millimeter)
paperRectPixel = printer.pageRect(QPrinter.DevicePixel)
c.render(pdfPainter, paperRectPixel, paperRectMM)
pdfPainter.end()
Second, is to embed a image of the current extent (using mapCanvas().saveasImage()) using a dynamic QPixMap element on the custom form. This brings me back to the same question as to whether or not the custom feature form could be printed (to pdf, and eventually paper).
Best Answer
Which version of QGIS are you using? If it's 2.4, you can set the columns shown in a QgsComposerAttributeTable by using the setColumns method. This method takes a list of QgsComposerTableColumn. Here's an example
There's a bunch of other things you can set for columns, such as the heading, alignment and sort order (see api docs here). You can even set an expression for a column in place of the attribute for added flexibility.
edit: To show only certain features you can set a filter on the table:
So, to filter a table to only selected features:
update: I missed a character in the filter expression. It should have been "$id in (...". Here's a complete, working version of the code you posted. There was a few simple mistakes (the constructor for QgsLegendModel takes no arguments, there's no applyDefaultSize method for attribute tables, and I've also moved the attribute table setItemPosition line):