Skip to content

Commit

Permalink
Merge pull request #3931 from nirvn/processing_modeler_picture
Browse files Browse the repository at this point in the history
[FEATURE] Export processing models as PDF/SVG
  • Loading branch information
nirvn committed Jan 2, 2017
2 parents a05096d + f54476c commit 952e6fb
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 117 deletions.
Binary file removed python/plugins/processing/images/delete.png
Binary file not shown.
1 change: 1 addition & 0 deletions python/plugins/processing/images/delete.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed python/plugins/processing/images/edit.png
Binary file not shown.
1 change: 1 addition & 0 deletions python/plugins/processing/images/edit.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion python/plugins/processing/images/input.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion python/plugins/processing/images/minus.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 1 addition & 62 deletions python/plugins/processing/images/output.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion python/plugins/processing/images/plus.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 68 additions & 7 deletions python/plugins/processing/modeler/ModelerDialog.py
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)'))
Expand All @@ -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,
Expand Down Expand Up @@ -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):
Expand Down

0 comments on commit 952e6fb

Please sign in to comment.