Skip to content
Permalink
Browse files

Merge pull request #3931 from nirvn/processing_modeler_picture

[FEATURE] Export processing models as PDF/SVG
  • Loading branch information
nirvn committed Jan 2, 2017
2 parents a05096d + f54476c commit 952e6fb17cbdc400d25f670529d2f75317176b6d
Binary file not shown.
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M11.023 2.707L8 5.73 4.974 2.708 2.707 4.975 5.732 8l-3.025 3.023 2.268 2.27L8 10.266l3.023 3.025 2.27-2.27L10.265 8l3.024-3.025z" fill-opacity=".059" stroke="#000" stroke-opacity=".435"/></svg>
Binary file not shown.
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><circle cx="4" cy="12" r="1.5" fill-opacity=".059" stroke="#000" stroke-linecap="round" stroke-opacity=".435"/><circle cx="8" cy="12" r="1.5" fill-opacity=".059" stroke="#000" stroke-linecap="round" stroke-opacity=".435"/><circle cx="12" cy="12" r="1.5" fill-opacity=".059" stroke="#000" stroke-linecap="round" stroke-opacity=".435"/></svg>
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M6.5 2.5v4h-4v3h4v4h3v-4h4v-3h-4v-4h-3z" fill="#87add9" stroke="#4673ad"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><g stroke="#5a8c5a" stroke-width=".265"><path d="M5.5 1.5v4h-4v5h4v4h5v-4h4v-5h-4v-4z" fill="#fff" stroke-width="1.00157545"/><path d="M3.5 8.5v-1h9v1z" fill="#5a8c5a" stroke-width="1.00157545"/><path d="M7.5 3.5h1v9h-1z" fill="#5a8c5a" stroke-width="1.00157545"/></g></svg>
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 11" width="11" height="11"><path fill="#fff" d="M0 0h11v11H0z"/><path fill="none" stroke="#f0f3f2" stroke-linecap="square" d="M1.5 1.5h8v8h-8z"/><path d="M3.5 5.5h4" fill="none" stroke="#000" stroke-linecap="round"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 11" width="11" height="11"><path d="M1 1h9v9H1z" fill="#fff" fill-opacity=".6"/><path fill="none" stroke="#f0f3f2" stroke-linecap="square" d="M1.5 1.5h8v8h-8z"/><path d="M3.5 5.5h4" fill="none" stroke="#000" stroke-linecap="round"/></svg>
@@ -1,62 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="0.91 r13725"
version="1.1"
id="svg2"
viewBox="0 0 16 16"
width="16"
height="16"
sodipodi:docname="output.svg">
<sodipodi:namedview
inkscape:current-layer="svg2"
inkscape:window-maximized="1"
inkscape:window-y="24"
inkscape:window-x="55"
inkscape:cy="11.016124"
inkscape:cx="10.378316"
inkscape:zoom="7.4749867"
units="px"
showgrid="true"
id="namedview6"
inkscape:window-height="1056"
inkscape:window-width="1865"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff">
<inkscape:grid
type="xygrid"
id="grid3195" />
</sodipodi:namedview>
<defs
id="defs8" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<path
style="fill:#87add9;fill-opacity:1;stroke:#4673ad;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 9 1.7070312 L 8.5 2.2070312 L 8.5 5.5 L 0.5 5.5 L 0.5 10.5 L 8.5 10.5 L 8.5 13.792969 L 9 14.292969 L 15.292969 8 L 9 1.7070312 z "
id="rect3204" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M0 5h8V0l8 8-8 8v-5H0z" fill="#5a8c5a"/><path d="M1 10V6h8V2.5L14.5 8 9 13.5V10z" fill="#fff"/><path d="M2 7v2h8v2l3.3-3L10 5v2z" fill="#5a8c5a"/></svg>
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 11" width="11" height="11"><path fill="#fff" d="M0 0h11v11H0z"/><path fill="none" stroke="#f0f3f2" stroke-linecap="square" d="M1.5 1.5h8v8h-8z"/><path d="M3.5 5.5h4M5.5 3.5v4" fill="none" stroke="#000" stroke-linecap="round"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 11" width="11" height="11"><path d="M1 1h9v9H1z" fill="#fff" fill-opacity=".6"/><path d="M1.5 1.5h8v8h-8z" fill="none" stroke="#f0f3f2" stroke-linecap="square"/><path d="M3.5 5.5h4m-2-2v4" fill="none" stroke="#000" stroke-linecap="round"/></svg>
@@ -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):

0 comments on commit 952e6fb

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