def ExportSVG(self): """ action triggered when user exports current graphics as svg :return: """ newPath = QFileDialog.getSaveFileName(self.centralwidget, "Export .svg", self.homeFolder, "SVG files (*.svg)") if not newPath[0]: return filename = newPath[0] if self.bitmapVisibility: self.ToggleBitmap() generator = QSvgGenerator() generator.setFileName(filename) sceneSize = self.scene.sceneRect().size() generator.setSize(sceneSize.toSize()) generator.setViewBox(QRect(0, 0, sceneSize.width(), sceneSize.height())) generator.setDescription("generated by SVG generator") generator.setTitle(filename) painter = QPainter() painter.begin(generator) self.scene.render(painter) painter.end()
def export(self, file, format): bounds = self.__get_bounds() size = self.get_size(bounds) if format == 'svg': output = QSvgGenerator() output.setFileName(file) output.setSize(size) output.setViewBox(QRect(QPoint(0, 0), size)) if isinstance(self.__diagram_or_selection, Diagram): output.setTitle(self.__diagram_or_selection.get_display_name() or "") elif format == 'pdf': output = QPrinter() output.setOutputFormat(QPrinter.PdfFormat) output.setPaperSize(QSizeF(size), QPrinter.DevicePixel) output.setPageMargins(0, 0, 0, 0, QPrinter.DevicePixel) output.setOutputFileName(file) else: output = QPixmap(size) output.fill(Qt.transparent) self.__draw(bounds, output) if format not in ('svg', 'pdf'): output.save(file, format)
def on_actionSaveGraph_triggered(self): if self.selectedWord: filename = self.selectedWord + "-specificity.png" else: filename = "specificity.png" fileName = QFileDialog.getSaveFileName( self, "Save Graph as png, svg, or pdf", filename, "PNG Image (*.png);;PDF File(*.pdf);;SVG File(*.svg)")[0] if str(fileName).endswith(".png"): #pixMap=QPixmap.grabWidget( self.graphicsView) pixMap = self.graphicsView.grab() pixMap.save(fileName) elif str(fileName).endswith(".pdf"): pdfPrinter = QPrinter() pdfPrinter.setOutputFormat(QPrinter.PdfFormat) pdfPrinter.setPaperSize( QSizeF(self.graphicsView.width(), self.graphicsView.height()), QPrinter.Point) pdfPrinter.setFullPage(True) pdfPrinter.setOutputFileName(fileName) pdfPainter = QPainter() pdfPainter.begin(pdfPrinter) self.graphicsView.render(pdfPainter) pdfPainter.end() elif str(fileName).endswith(".svg"): svgGen = QSvgGenerator() svgGen.setFileName(fileName) svgGen.setSize( QSize(self.graphicsView.width(), self.graphicsView.height())) svgGen.setViewBox( QRect(0, 0, self.graphicsView.width(), self.graphicsView.height())) svgGen.setTitle(filename) svgGen.setDescription("Specificity graph generated by Gromoteur") painter = QPainter(svgGen) self.graphicsView.render(painter) painter.end()
def export_to_svg(self): """ Graph editor's scene rendering & saving to svg-file :return: None """ filename = QFileDialog.getSaveFileName(None, 'Сохранить SVG-граф', "", "svg files (*.svg)") if len(filename[0]) > 4: svg = QSvgGenerator() svg.setFileName(filename[0]) w = self.__graph_editor.get_diagram_scene().width() h = self.__graph_editor.get_diagram_scene().height() svg.setSize(QSize(w, h)) svg.setViewBox(QRect(0, 0, w, h)) svg.setTitle('Semantic Graph') svg.setDescription('File created by RTA') painter = QPainter() painter.begin(svg) self.__graph_editor.get_diagram_scene().render(painter) painter.end()
def save(self, path, filetype=None, title=None, description=None, svg_dpi=SVG_INKSCAPE): if path is None or not isinstance(path, str): logger.error('please provide a valide path to save the image "' + str(path) + '"') return if filetype is None: if path.lower().endswith('.svg'): filetype = 'svg' else: filetype = 'raster' dpi = 72 # 300 # inkscape 96 ? check for illustrator --> check if filetype == 'svg': generator = QSvgGenerator() generator.setFileName(path) if svg_dpi == self.SVG_ILLUSTRATOR: generator.setSize(QSize(595, 842)) generator.setViewBox(QRect(0, 0, 595, 842)) else: generator.setSize(QSize(794, 1123)) generator.setViewBox(QRect(0, 0, 794, 1123)) if title is not None and isinstance(title, str): generator.setTitle(title) if description is not None and isinstance(description, str): generator.setDescription(description) generator.setResolution( svg_dpi ) # fixes issues in inkscape of pt size --> 72 pr illustrator and 96 pr inkscape but need change size painter = QPainter(generator) print(generator.title(), generator.heightMM(), generator.height(), generator.widthMM(), generator.resolution(), generator.description(), generator.logicalDpiX()) else: scaling_factor_dpi = 1 scaling_factor_dpi = self.scaling_factor_to_achieve_DPI(300) image = QtGui.QImage( QSize( self.cm_to_inch(21) * dpi * scaling_factor_dpi, self.cm_to_inch(29.7) * dpi * scaling_factor_dpi), QtGui.QImage.Format_RGB32) painter = QPainter( image) # see what happens in case of rounding of pixels painter.scale(scaling_factor_dpi, scaling_factor_dpi) painter.setRenderHint( QPainter.HighQualityAntialiasing ) # to improve rendering #Antialiasing otherwise or nothing self.paint(painter) painter.end() if filetype != 'svg': image.save(path)
def ExportSVGPerLayer(self): """ action triggered when user exports current graphics as one svg per layer :return: """ newPath = QFileDialog.getSaveFileName(self.centralwidget, "Export .svg per layer", self.homeFolder, "SVG files (*.svg)") if not newPath[0]: return filename = newPath[0] if self.bitmapVisibility: self.ToggleBitmap() # make stuff invisible to avoid sending it to svg for layer_idx in range(self.layersModel.rowCount()): print("*** iteration {0}".format(layer_idx)) layer_filename = "{0}_layer{1}.svg".format( os.path.splitext(filename)[0], layer_idx + 1) for item in self.scene.items(): item.setVisible(True) forceAlwaysInvisible = item.__class__ == QGraphicsPixmapItem forceInvisibleInCurrentLayer = item.__class__ == QGraphicsItemGroup and \ (item != self.layersModel.item(layer_idx).get_graphics_items_group() or \ self.layersModel.item(layer_idx).checkState() != Qt.Checked) if forceAlwaysInvisible or forceInvisibleInCurrentLayer: # ouch print("setting idx to invisible for item {0}".format(item)) item.setVisible(False) if self.layersModel.item(layer_idx).checkState() == Qt.Checked: generator = QSvgGenerator() generator.setFileName(layer_filename) sceneSize = self.scene.sceneRect().size() generator.setSize(sceneSize.toSize()) generator.setViewBox( QRect(0, 0, sceneSize.width(), sceneSize.height())) generator.setDescription("generated by SVG generator") generator.setTitle(layer_filename) painter = QPainter() painter.begin(generator) self.scene.render(painter) painter.end() # restore visibility for layer_idx in range(self.layersModel.rowCount()): for item in self.scene.items(): if item.__class__ == QGraphicsItemGroup and \ self.layersModel.item(layer_idx).checkState() == Qt.Checked: # ouch item.setVisible(True)
def saveSvg(self): path = "save.svg" self.status_update_signal.emit("exporting SVG to %s" % (path)) generator = QSvgGenerator() generator.setFileName(path) w = self.pixmap.size().width() h = self.pixmap.size().height() generator.setSize(QSize(w, h)) generator.setViewBox(QRect(0, 0, w, h)) generator.setTitle("Spiraliser!") qp = QPainter(generator) showImage = self.showImage self.showImage = False self.paint(qp) self.showImage = showImage qp.end() self.saveHPGL()
def create_svg(text, font, rect=None): if not rect: rect = QRect(0, 0, 200, 200) f = tempfile.NamedTemporaryFile() generator = QSvgGenerator() generator.setFileName(f.name) generator.setSize(rect.size()) generator.setViewBox(rect) generator.setTitle("puddletag image") generator.setDescription("just to see") painter = QPainter() painter.begin(generator) painter.fillRect(rect, Qt.GlobalColor.black) painter.setFont(font) painter.setPen(Qt.GlobalColor.white) painter.setBrush(QBrush(Qt.GlobalColor.white)) painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, text) painter.end() svg = open(f.name).read() f.close() return svg
def __save(self): """If AerialWare has been used as a module, emits signal 'done'. Saves user results into SVG and makes report otherwise. """ # Variables for report self.pointsMeridian = "" self.pointsHorizontal = "" # Total lengths of paths. Used in report and methods. self.lenMeridian = 0 self.lenMeridianWithTurns = 0 self.lenHorizontal = 0 self.lenHorizontalWithTurns = 0 # Fields for methods self.pathMeridianPointsPx = [] self.pathMeridianPointsDeg = [] self.pathMeridianLinesPx = [] self.pathMeridianLinesWithTurnsPx = [] self.pathMeridianLinesDeg = [] self.pathMeridianLinesWithTurnsDeg = [] self.pathHorizontalPointsPx = [] self.pathHorizontalPointsDeg = [] self.pathHorizontalLinesPx = [] self.pathHorizontalLinesWithTurnsPx = [] self.pathHorizontalLinesDeg = [] self.pathHorizontalLinesWithTurnsDeg = [] # Process each line def processLines(lines, isMeridian=False): i = 2 # Counter for report isEven = False # If current line is even we must swap it's points. for line in lines: linePx = line.line() p1 = linePx.p1() p2 = linePx.p2() p1Deg = self.pxToDeg(p1.x(), p1.y()) p2Deg = self.pxToDeg(p2.x(), p2.y()) lineDeg = QLineF(p1Deg, p2Deg) lineLength = self.__lenMeters(p1Deg, p2Deg) if isMeridian: self.pathMeridianLinesWithTurnsPx.append(linePx) self.pathMeridianLinesWithTurnsDeg.append(lineDeg) self.lenMeridianWithTurns += lineLength else: self.pathHorizontalLinesWithTurnsPx.append(linePx) self.pathHorizontalLinesWithTurnsDeg.append(lineDeg) self.lenHorizontalWithTurns += lineLength if line.pen().style( ) == Qt.SolidLine: # Check if current line doesn't represent turn if isEven: p1, p2, p1Deg, p2Deg = p2, p1, p2Deg, p1Deg point = f'"{i - 1}","{p1Deg.x()}","{p1Deg.y()}"\n' + f'"{i}","{p2Deg.x()}","{p2Deg.y()}"\n' if isMeridian: self.pointsMeridian += point self.pathMeridianPointsPx.extend([p1, p2]) self.pathMeridianPointsDeg.extend([p1Deg, p2Deg]) self.pathMeridianLinesPx.append(linePx) self.pathMeridianLinesDeg.append(lineDeg) self.lenMeridian += lineLength else: self.pointsHorizontal += point self.pathHorizontalPointsPx.extend([p1, p2]) self.pathHorizontalPointsDeg.extend([p1Deg, p2Deg]) self.pathHorizontalLinesPx.append(linePx) self.pathHorizontalLinesDeg.append(lineDeg) self.lenHorizontal += lineLength isEven = not isEven i += 2 processLines(self.scene.getMeridianLines(), True) processLines(self.scene.getHorizontalLines()) if self.getResultsAfterCompletion: self.done.emit() return self.__disableItems() # Make report pointHeader = f'"{self.lang.repPoint}","{self.lang.lblLatitude}","{self.lang.lblLongitude}"\n' if self.lenHorizontalWithTurns > self.lenMeridianWithTurns: directionWithTurns = self.lang.repFlyMeridians elif self.lenHorizontalWithTurns < self.lenMeridianWithTurns: directionWithTurns = self.lang.repFlyHorizontals else: directionWithTurns = self.lang.repFlyEqual if self.lenHorizontal > self.lenMeridian: directionWithoutTurns = self.lang.repFlyMeridians elif self.lenHorizontal < self.lenMeridian: directionWithoutTurns = self.lang.repFlyHorizontals else: directionWithoutTurns = self.lang.repFlyEqual report = ( f'"{self.lang.repCornersDescription}"\n' f'"{self.lang.lblCorner}","{self.lang.lblLongitude}","{self.lang.lblLatitude}"\n' f'"{self.lang.lblTopLeft}","{self.xTL}","{self.yTL}"\n' f'"{self.lang.lblTopRight}","{self.xTR}","{self.yTR}"\n' f'"{self.lang.lblBottomLeft}","{self.xBL}","{self.yBL}"\n' f'"{self.lang.lblBottomRight}","{self.xBR}","{self.yBR}"\n' f'"{self.lang.lblDelimiters}","{self.xD}","{self.yD}"\n\n' f'"{self.lang.repTotalWithTurns}"\n' f'"{self.lang.repByMeridians}","{self.lenMeridianWithTurns}"\n' f'"{self.lang.repByHorizontals}","{self.lenHorizontalWithTurns}"\n' f'"{self.lang.repBetterFlyBy}","{directionWithTurns}"\n\n' f'"{self.lang.repTotalWithoutTurns}"\n' f'"{self.lang.repByMeridians}","{self.lenMeridian}"\n' f'"{self.lang.repByHorizontals}","{self.lenHorizontal}"\n' f'"{self.lang.repBetterFlyBy}","{directionWithoutTurns}"\n\n' f'"{self.lang.repAerialParams}"\n' f'"{self.lang.repArea}","{self.maxHorizontal}","x","{self.maxVertical}"\n' f'"{self.lang.lblDesiredRes}","{self.camRatio}"\n' f'"{self.lang.lblRes}","{self.camWidth}","x","{self.camHeight}"\n' f'"{self.lang.lblHeight}","{self.flightHeight}"\n' f'"{self.lang.lblFocal}","{self.focalLength}"\n\n' f'"{self.lang.repMeridianPoints}"\n' + pointHeader + self.pointsMeridian + f'\n"{self.lang.repHorizontalPoints}"\n' + pointHeader + self.pointsHorizontal) # Save image self.__disableItems() file = QFileDialog.getSaveFileName(self, self.lang.saveFile, "", self.lang.vectorImage + " (*.svg)")[0] if file == "": self.__enableItems() return # And choose where to save report reportName = "" while reportName == "": reportName = QFileDialog.getSaveFileName( self, self.lang.saveFile, "", self.lang.table + " (*.csv)")[0] if reportName == "": msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setText(self.lang.errSaveBoth) msg.exec_() rect = self.scene.sceneRect() gen = QSvgGenerator() gen.setFileName(file) gen.setSize(rect.size().toSize()) gen.setViewBox(rect) gen.setTitle("Flight paths generated by AerialWare") gen.setDescription(gen.title()) # Notice: painting will temporarily freeze application because QGraphicsScene::render is not thread safe. # Don't try putting this into python's threads and QThread, doesn't work, I've tried, trust me XD painter = QPainter(gen) self.scene.render(painter) painter.end() # Save report reportFile = open(reportName, "w") reportFile.write(report) reportFile.close() self.__enableItems()
def save(self, path, filetype=None, title=None, description=None, svg_dpi=SVG_INKSCAPE): if path is None or not isinstance(path, str): logger.error('please provide a valide path to save the image "' + str(path) + '"') return if filetype is None: if path.lower().endswith('.svg'): filetype = 'svg' else: filetype = os.path.splitext(path)[1] dpi = 72 # 300 # inkscape 96 ? check for illustrator --> check if filetype == 'svg': generator = QSvgGenerator() generator.setFileName(path) if svg_dpi == self.SVG_ILLUSTRATOR: generator.setSize(QSize(595, 842)) generator.setViewBox(QRect(0, 0, 595, 842)) else: generator.setSize(QSize(794, 1123)) generator.setViewBox(QRect(0, 0, 794, 1123)) if title is not None and isinstance(title, str): generator.setTitle(title) if description is not None and isinstance(description, str): generator.setDescription(description) generator.setResolution( svg_dpi) # fixes issues in inkscape of pt size --> 72 pr illustrator and 96 pr inkscape but need change size painter = QPainter(generator) # print(generator.title(), generator.heightMM(), generator.height(), generator.widthMM(), # generator.resolution(), generator.description(), generator.logicalDpiX()) else: scaling_factor_dpi = 1 scaling_factor_dpi = self.scaling_factor_to_achieve_DPI(300) # in fact take actual page size ??? multiplied by factor # just take real image size instead # image = QtGui.QImage(QSize(self.cm_to_inch(21) * dpi * scaling_factor_dpi, self.cm_to_inch(29.7) * dpi * scaling_factor_dpi), QtGui.QImage.Format_RGBA8888) # minor change to support alpha # QtGui.QImage.Format_RGB32) # NB THE FOLLOWING LINES CREATE A WEIRD ERROR WITH WEIRD PIXELS DRAWN some sort of lines NO CLUE WHY img_bounds = self.getBounds() image = QtGui.QImage(QSize(img_bounds.width() * scaling_factor_dpi, img_bounds.height()* scaling_factor_dpi), QtGui.QImage.Format_RGBA8888) # minor change to support alpha # QtGui.QImage.Format_RGB32) # print('size at dpi',QSize(img_bounds.width() * scaling_factor_dpi, img_bounds.height()* scaling_factor_dpi)) # QSize(self.cm_to_inch(0.02646 * img_bounds.width()) # self.cm_to_inch(0.02646 * img_bounds.height()) # need convert pixels to inches # is there a rounding error # force white bg for non jpg try: # print(filetype.lower()) # the tif and png file formats support alpha if not filetype.lower() == '.png' and not filetype.lower() == '.tif' and not filetype.lower() == '.tiff': image.fill(QColor.fromRgbF(1,1,1)) else: # image.fill(QColor.fromRgbF(1, 1, 1, alpha=1)) # image.fill(QColor.fromRgbF(1, 1, 1, alpha=1)) # TODO KEEP in fact image need BE FILLED WITH TRANSPARENT OTHERWISE GETS WEIRD DRAWING ERRORS # TODO KEEP SEE https://stackoverflow.com/questions/13464627/qt-empty-transparent-qimage-has-noise # image.fill(qRgba(0, 0, 0, 0)) image.fill(QColor.fromRgbF(0,0,0,0)) except: pass painter = QPainter(image) # see what happens in case of rounding of pixels # painter.begin() painter.scale(scaling_factor_dpi, scaling_factor_dpi) painter.setRenderHint(QPainter.HighQualityAntialiasing) # to improve rendering quality self.paint(painter) painter.end() if filetype != 'svg': image.save(path)