From 6d826fa14383d959fbddacf1a8408a1a0e82a3bf Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Thu, 12 Dec 2019 03:18:52 +0200 Subject: [PATCH] - added option to save objects as PDF files in File -> Save menu --- FlatCAMApp.py | 60 ++++++++++++++++++++++++++++++--- README.md | 1 + camlib.py | 2 +- flatcamGUI/FlatCAMGUI.py | 7 ++++ flatcamTools/ToolCalibration.py | 7 ++++ flatcamTools/ToolFilm.py | 28 ++++++++++----- 6 files changed, 90 insertions(+), 15 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 9e238489..de090bc2 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -23,8 +23,14 @@ from stat import S_IREAD, S_IRGRP, S_IROTH import subprocess import ctypes -import tkinter as tk -from PyQt5 import QtPrintSupport +# import tkinter as tk +# from PyQt5 import QtPrintSupport + +from reportlab.graphics import renderPDF +from reportlab.pdfgen import canvas +from reportlab.graphics import renderPM +from reportlab.lib.units import inch, mm +from reportlab.lib.pagesizes import landscape, portrait from contextlib import contextmanager import gc @@ -1776,6 +1782,7 @@ class App(QtCore.QObject): self.ui.menufilesaveproject.triggered.connect(self.on_file_saveproject) self.ui.menufilesaveprojectas.triggered.connect(self.on_file_saveprojectas) self.ui.menufilesaveprojectcopy.triggered.connect(lambda: self.on_file_saveprojectas(make_copy=True)) + self.ui.menufilesave_object_pdf.triggered.connect(self.on_file_save_object_pdf) self.ui.menufilesavedefaults.triggered.connect(self.on_file_savedefaults) self.ui.menufileexportpref.triggered.connect(self.on_export_preferences) @@ -10127,15 +10134,15 @@ class App(QtCore.QObject): filename = str(filename) if filename == '': - self.inform.emit('[WARNING_NOTCL] %s' % - _("Save Project cancelled.")) + self.inform.emit('[WARNING_NOTCL] %s' % _("Save Project cancelled.")) return try: f = open(filename, 'r') f.close() except IOError: - pass + self.inform.emit('[ERROR_NOTCL] %s' % _("The object is used by another application.")) + return if use_thread is True: self.worker_task.emit({'fcn': self.save_project, @@ -10154,6 +10161,49 @@ class App(QtCore.QObject): self.set_ui_title(name=self.project_filename) self.should_we_save = False + def on_file_save_object_pdf(self, use_thread=True): + self.date = str(datetime.today()).rpartition('.')[0] + self.date = ''.join(c for c in self.date if c not in ':-') + self.date = self.date.replace(' ', '_') + + try: + obj_active = self.collection.get_active() + obj_name = obj_active.options['name'] + except AttributeError as err: + log.debug("App.on_file_save_object_pdf() --> %s" % str(err)) + self.inform.emit('[ERROR_NOTCL] %s' % _("No object selected.")) + return + + filter_ = "PDF File (*.PDF);; All Files (*.*)" + try: + filename, _f = QtWidgets.QFileDialog.getSaveFileName( + caption=_("Save Object as PDF ..."), + directory=_('{l_save}/{obj_name}_{date}').format(l_save=str(self.get_last_save_folder()), + obj_name=obj_name, + date=self.date), + filter=filter_) + except TypeError: + filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Save Object as PDF ..."), filter=filter_) + + filename = str(filename) + + if filename == '': + self.inform.emit('[WARNING_NOTCL] %s' % _("Save Object PDF cancelled.")) + return + + if use_thread is True: + self.worker_task.emit({'fcn': self.save_pdf, 'params': [filename, obj_name]}) + else: + self.save_pdf(filename, obj_name) + + # self.save_project(filename) + if self.defaults["global_open_style"] is False: + self.file_opened.emit("pdf", filename) + self.file_saved.emit("pdf", filename) + + def save_pdf(self, file_name, obj_name): + self.film_tool.export_positive(obj_name=obj_name, box_name=obj_name, filename=file_name, ftype='pdf') + def export_svg(self, obj_name, filename, scale_stroke_factor=0.00): """ Exports a Geometry Object to an SVG file. diff --git a/README.md b/README.md index 83cbab6c..011135de 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ CAD program, and create G-Code for Isolation routing. - finished the Calibration Tool - changed the Scale Entry in Object UI to FCEntry() GUI element in order to allow expressions to be entered. E.g: 1/25.4 - some small changes in the Scale button handler in FlatCAMObj() class +- added option to save objects as PDF files in File -> Save menu 11.12.2019 diff --git a/camlib.py b/camlib.py index 0ac35ff4..8da7052e 100644 --- a/camlib.py +++ b/camlib.py @@ -1824,7 +1824,7 @@ class Geometry(object): """ # Make sure we see a Shapely Geometry class and not a list - if str(type(self)) == "": + if self.kind.lower() == 'geometry': flat_geo = [] if self.multigeo: for tool in self.tools: diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 678b727c..5a951e87 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -250,6 +250,13 @@ class FlatCAMGUI(QtWidgets.QMainWindow): _('Save Project C&opy ...'), self) self.menufile_save.addAction(self.menufilesaveprojectcopy) + self.menufile_save.addSeparator() + + # Save Object PDF + self.menufilesave_object_pdf = QtWidgets.QAction(QtGui.QIcon('share/pdf32.png'), + _('Save Object as PDF ...'), self) + self.menufile_save.addAction(self.menufilesave_object_pdf) + # Separator self.menufile.addSeparator() diff --git a/flatcamTools/ToolCalibration.py b/flatcamTools/ToolCalibration.py index 3a045783..7faaae34 100644 --- a/flatcamTools/ToolCalibration.py +++ b/flatcamTools/ToolCalibration.py @@ -197,6 +197,9 @@ class ToolCalibration(FlatCAMTool): self.obj_type_combo.addItem(_("Excellon")) self.obj_type_combo.setCurrentIndex(1) + self.obj_type_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png")) + self.obj_type_combo.setItemIcon(1, QtGui.QIcon("share/drill16.png")) + grid_lay.addWidget(self.obj_type_label, 12, 0) grid_lay.addWidget(self.obj_type_combo, 12, 1, 1, 2) @@ -631,6 +634,10 @@ class ToolCalibration(FlatCAMTool): self.adj_object_type_combo.addItems([_("Gerber"), _("Excellon"), _("Geometry")]) self.adj_object_type_combo.setCurrentIndex(0) + self.adj_object_type_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png")) + self.adj_object_type_combo.setItemIcon(1, QtGui.QIcon("share/drill16.png")) + self.adj_object_type_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png")) + self.adj_object_type_label = QtWidgets.QLabel("%s:" % _("Adjusted object type")) self.adj_object_type_label.setToolTip( _("Type of the FlatCAM Object to be adjusted.") diff --git a/flatcamTools/ToolFilm.py b/flatcamTools/ToolFilm.py index c26656b1..ba44c211 100644 --- a/flatcamTools/ToolFilm.py +++ b/flatcamTools/ToolFilm.py @@ -19,7 +19,7 @@ from reportlab.graphics import renderPDF from reportlab.pdfgen import canvas from reportlab.graphics import renderPM from reportlab.lib.units import inch, mm -from reportlab.lib.pagesizes import landscape, portrait, A4 +from reportlab.lib.pagesizes import landscape, portrait from svglib.svglib import svg2rlg from xml.dom.minidom import parseString as parse_xml_string @@ -742,12 +742,18 @@ class Film(FlatCAMTool): self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export positive film cancelled.")) return else: + pagesize = self.pagesize_combo.get_value() + orientation = self.orientation_radio.get_value() + color = self.app.defaults['tools_film_color'] + self.export_positive(name, boxname, filename, scale_stroke_factor=factor, scale_factor_x=scale_factor_x, scale_factor_y=scale_factor_y, skew_factor_x=skew_factor_x, skew_factor_y=skew_factor_y, skew_reference=skew_reference, - mirror=mirror, ftype=ftype + mirror=mirror, + pagesize=pagesize, orientation=orientation, color=color, opacity=1.0, + ftype=ftype ) def generate_positive_punched_film(self, name, boxname, source, factor, ftype='svg'): @@ -1072,7 +1078,7 @@ class Film(FlatCAMTool): scale_stroke_factor=0.00, scale_factor_x=None, scale_factor_y=None, skew_factor_x=None, skew_factor_y=None, skew_reference='center', - mirror=None, + mirror=None, orientation='p', pagesize='A4', color='black', opacity=1.0, use_thread=True, ftype='svg'): """ Exports a Geometry Object to an SVG file in positive black. @@ -1116,6 +1122,11 @@ class Film(FlatCAMTool): self.inform.emit('[WARNING_NOTCL] %s: %s' % (_("No object Box. Using instead"), obj)) box = obj + p_size = pagesize + orientation = orientation + color = color + transparency_level = opacity + def make_positive_film(): log.debug("FilmTool.export_positive().make_positive_film()") @@ -1131,9 +1142,9 @@ class Film(FlatCAMTool): # We set the colour to WHITE root = ET.fromstring(exported_svg) for child in root: - child.set('fill', str(self.app.defaults['tools_film_color'])) - child.set('opacity', '1.0') - child.set('stroke', str(self.app.defaults['tools_film_color'])) + child.set('fill', str(color)) + child.set('opacity', str(transparency_level)) + child.set('stroke', str(color)) exported_svg = ET.tostring(root) @@ -1194,7 +1205,7 @@ class Film(FlatCAMTool): return 'fail' else: try: - if self.units == 'INCH': + if self.units == 'IN': unit = inch else: unit = mm @@ -1202,11 +1213,10 @@ class Film(FlatCAMTool): doc_final = StringIO(doc_final) drawing = svg2rlg(doc_final) - p_size = self.pagesize_combo.get_value() if p_size == 'Bounds': renderPDF.drawToFile(drawing, filename) else: - if self.orientation_radio.get_value() == 'p': + if orientation == 'p': page_size = portrait(self.pagesize[p_size]) else: page_size = landscape(self.pagesize[p_size])