Skip to content
Permalink
Browse files

[FEATURE] Export processing models as PDF/SVG

  • Loading branch information
nirvn committed Jan 2, 2017
1 parent 4603eb0 commit f54476cddaf70096c585c984c5963fdaf5530931
@@ -31,9 +31,11 @@
import os

from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt, QRectF, QMimeData, QPoint, QPointF, QSettings, QByteArray, QSize, pyqtSignal
from qgis.PyQt.QtCore import Qt, QRectF, QMimeData, QPoint, QPointF, QSettings, QByteArray, QSize, QSizeF, pyqtSignal
from qgis.PyQt.QtWidgets import QGraphicsView, QTreeWidget, QMessageBox, QFileDialog, QTreeWidgetItem, QSizePolicy, QMainWindow
from qgis.PyQt.QtGui import QIcon, QImage, QPainter
from qgis.PyQt.QtSvg import QSvgGenerator
from qgis.PyQt.QtPrintSupport import QPrinter
from qgis.core import QgsApplication
from qgis.gui import QgsMessageBar
from processing.core.ProcessingConfig import ProcessingConfig
@@ -213,6 +215,8 @@ def _mimeDataAlgorithm(items):
self.mActionSave.triggered.connect(self.save)
self.mActionSaveAs.triggered.connect(self.saveAs)
self.mActionExportImage.triggered.connect(self.exportAsImage)
self.mActionExportPdf.triggered.connect(self.exportAsPdf)
self.mActionExportSvg.triggered.connect(self.exportAsSvg)
self.mActionExportPython.triggered.connect(self.exportAsPython)
self.mActionEditHelp.triggered.connect(self.editHelp)
self.mActionRun.triggered.connect(self.runModel)
@@ -287,6 +291,7 @@ def saveAs(self):
self.saveModel(True)

def exportAsImage(self):
self.repaintModel(controls=False)
filename, fileFilter = QFileDialog.getSaveFileName(self,
self.tr('Save Model As Image'), '',
self.tr('PNG files (*.png *.PNG)'))
@@ -296,23 +301,79 @@ def exportAsImage(self):
if not filename.lower().endswith('.png'):
filename += '.png'

totalRect = QRectF(0, 0, 1, 1)
for item in list(self.scene.items()):
totalRect = totalRect.united(item.sceneBoundingRect())
totalRect = self.scene.itemsBoundingRect()
totalRect.adjust(-10, -10, 10, 10)
imgRect = QRectF(0, 0, totalRect.width(), totalRect.height())

img = QImage(totalRect.width(), totalRect.height(),
QImage.Format_ARGB32_Premultiplied)
img.fill(Qt.white)
painter = QPainter()
painter.setRenderHint(QPainter.Antialiasing)
painter.begin(img)
self.scene.render(painter, totalRect, totalRect)
self.scene.render(painter, imgRect, totalRect)
painter.end()

img.save(filename)

self.bar.pushMessage("", "Model was correctly exported as image", level=QgsMessageBar.SUCCESS, duration=5)
self.repaintModel(controls=True)

def exportAsPdf(self):
self.repaintModel(controls=False)
filename, fileFilter = QFileDialog.getSaveFileName(self,
self.tr('Save Model As PDF'), '',
self.tr('SVG files (*.pdf *.PDF)'))
if not filename:
return

if not filename.lower().endswith('.pdf'):
filename += '.pdf'

totalRect = self.scene.itemsBoundingRect()
totalRect.adjust(-10, -10, 10, 10)
printerRect = QRectF(0, 0, totalRect.width(), totalRect.height())

printer = QPrinter()
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName(filename)
printer.setPaperSize(QSizeF(printerRect.width(), printerRect.height()), QPrinter.DevicePixel)
printer.setFullPage(True)

painter = QPainter(printer)
self.scene.render(painter, printerRect, totalRect)
painter.end()

self.bar.pushMessage("", "Model was correctly exported as PDF", level=QgsMessageBar.SUCCESS, duration=5)
self.repaintModel(controls=True)

def exportAsSvg(self):
self.repaintModel(controls=False)
filename, fileFilter = QFileDialog.getSaveFileName(self,
self.tr('Save Model As SVG'), '',
self.tr('SVG files (*.svg *.SVG)'))
if not filename:
return

if not filename.lower().endswith('.svg'):
filename += '.svg'

totalRect = self.scene.itemsBoundingRect()
totalRect.adjust(-10, -10, 10, 10)
svgRect = QRectF(0, 0, totalRect.width(), totalRect.height())

svg = QSvgGenerator()
svg.setFileName(filename)
svg.setSize(QSize(totalRect.width(), totalRect.height()))
svg.setViewBox(svgRect)
svg.setTitle(self.alg.name)

painter = QPainter(svg)
self.scene.render(painter, svgRect, totalRect)
painter.end()

self.bar.pushMessage("", "Model was correctly exported as SVG", level=QgsMessageBar.SUCCESS, duration=5)
self.repaintModel(controls=True)

def exportAsPython(self):
filename, filter = QFileDialog.getSaveFileName(self,
@@ -399,11 +460,11 @@ def openModel(self):
self.tr('The selected model could not be loaded.\n'
'See the log for more information.'))

def repaintModel(self):
def repaintModel(self, controls=True):
self.scene = ModelerScene()
self.scene.setSceneRect(QRectF(0, 0, ModelerAlgorithm.CANVAS_SIZE,
ModelerAlgorithm.CANVAS_SIZE))
self.scene.paintModel(self.alg)
self.scene.paintModel(self.alg, controls)
self.view.setScene(self.scene)

def addInput(self):
@@ -45,8 +45,9 @@ class ModelerGraphicItem(QGraphicsItem):
BOX_HEIGHT = 30
BOX_WIDTH = 200

def __init__(self, element, model):
def __init__(self, element, model, controls):
super(ModelerGraphicItem, self).__init__(None)
self.controls = controls
self.model = model
self.element = element
if isinstance(element, ModelerParameter):
@@ -73,7 +74,7 @@ def __init__(self, element, model):
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
self.setZValue(1000)

if not isinstance(element, ModelerOutput):
if not isinstance(element, ModelerOutput) and controls:
svg = QSvgRenderer(os.path.join(pluginPath, 'images', 'edit.svg'))
picture = QPicture()
painter = QPainter(picture)
@@ -101,13 +102,15 @@ def __init__(self, element, model):
if alg.parameters:
pt = self.getLinkPointForParameter(-1)
pt = QPointF(0, pt.y())
self.inButton = FoldButtonGraphicItem(pt, self.foldInput, self.element.paramsFolded)
self.inButton.setParentItem(self)
if controls:
self.inButton = FoldButtonGraphicItem(pt, self.foldInput, self.element.paramsFolded)
self.inButton.setParentItem(self)
if alg.outputs:
pt = self.getLinkPointForOutput(-1)
pt = QPointF(0, pt.y())
self.outButton = FoldButtonGraphicItem(pt, self.foldOutput, self.element.outputsFolded)
self.outButton.setParentItem(self)
if controls:
self.outButton = FoldButtonGraphicItem(pt, self.foldOutput, self.element.outputsFolded)
self.outButton.setParentItem(self)

def foldInput(self, folded):
self.element.paramsFolded = folded
@@ -237,12 +240,15 @@ def paint(self, painter, option, widget=None):
ModelerGraphicItem.BOX_HEIGHT + 2)
color = QColor(172, 196, 114)
outline = QColor(90, 140, 90)
selected = QColor(90, 140, 90)
if isinstance(self.element, ModelerParameter):
color = QColor(238, 242, 131)
outline = QColor(234, 226, 118)
selected = QColor(151, 153, 83)
elif isinstance(self.element, Algorithm):
color = Qt.white
outline = Qt.gray
selected = Qt.gray
painter.setPen(QPen(outline, 1))
painter.setBrush(QBrush(color, Qt.SolidPattern))
painter.drawRect(rect)
@@ -255,7 +261,7 @@ def paint(self, painter, option, widget=None):
painter.setPen(QPen(Qt.gray))
text = text + "\n(deactivated)"
elif self.isSelected():
painter.setPen(QPen(outline))
painter.setPen(QPen(selected))
fm = QFontMetricsF(font)
text = self.getAdjustedText(self.text)
h = fm.ascent()
@@ -379,7 +385,7 @@ def paint(self, painter, option, widget=None):
rect = QRectF(pt.x(), pt.y(), self.WIDTH, self.HEIGHT)
if self.isIn:
painter.setPen(QPen(Qt.transparent, 1))
painter.setBrush(QBrush(Qt.lightGray,
painter.setBrush(QBrush(QColor(55, 55, 55, 33),
Qt.SolidPattern))
else:
painter.setPen(QPen(Qt.transparent, 1))
@@ -78,11 +78,11 @@ def getItemsFromParamValue(self, value):
items.append((self.algItems[value.alg], i))
return items

def paintModel(self, model):
def paintModel(self, model, controls=True):
self.model = model
# Inputs
for inp in list(model.inputs.values()):
item = ModelerGraphicItem(inp, model)
item = ModelerGraphicItem(inp, model, controls)
item.setFlag(QGraphicsItem.ItemIsMovable, True)
item.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.addItem(item)
@@ -91,7 +91,7 @@ def paintModel(self, model):

# We add the algs
for alg in list(model.algs.values()):
item = ModelerGraphicItem(alg, model)
item = ModelerGraphicItem(alg, model, controls)
item.setFlag(QGraphicsItem.ItemIsMovable, True)
item.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.addItem(item)
@@ -131,7 +131,7 @@ def paintModel(self, model):
for key in outputs:
out = outputs[key]
if out is not None:
item = ModelerGraphicItem(out, model)
item = ModelerGraphicItem(out, model, controls)
item.setFlag(QGraphicsItem.ItemIsMovable, True)
item.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.addItem(item)
@@ -310,6 +310,8 @@
<addaction name="mActionSaveAs"/>
<addaction name="separator"/>
<addaction name="mActionExportImage"/>
<addaction name="mActionExportPdf"/>
<addaction name="mActionExportSvg"/>
<addaction name="mActionExportPython"/>
<addaction name="separator"/>
<addaction name="mActionEditHelp"/>
@@ -373,6 +375,30 @@
<string>Export as image</string>
</property>
</action>
<action name="mActionExportPdf">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionSaveAsPDF.svg</normaloff>:/images/themes/default/mActionSaveAsPDF.svg</iconset>
</property>
<property name="text">
<string>Export as PDF...</string>
</property>
<property name="toolTip">
<string>Export as PDF</string>
</property>
</action>
<action name="mActionExportSvg">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionSaveAsSVG.svg</normaloff>:/images/themes/default/mActionSaveAsSVG.svg</iconset>
</property>
<property name="text">
<string>Export as SVG...</string>
</property>
<property name="toolTip">
<string>Export as SVG</string>
</property>
</action>
<action name="mActionExportPython">
<property name="icon">
<iconset resource="../../images/images.qrc">

0 comments on commit f54476c

Please sign in to comment.
You can’t perform that action at this time.