Explorar o código

Merged in marius_stanciu/flatcam_beta/Beta (pull request #263)

Beta - update
Marius Stanciu %!s(int64=6) %!d(string=hai) anos
pai
achega
ab87531a09
Modificáronse 5 ficheiros con 86 adicións e 44 borrados
  1. 8 18
      FlatCAMApp.py
  2. 7 1
      FlatCAMObj.py
  3. 6 0
      README.md
  4. 27 22
      camlib.py
  5. 38 3
      flatcamEditors/FlatCAMTextEditor.py

+ 8 - 18
FlatCAMApp.py

@@ -9975,11 +9975,11 @@ class App(QtCore.QObject):
 
 
         flt = "All Files (*.*)"
         flt = "All Files (*.*)"
         if obj.kind == 'gerber':
         if obj.kind == 'gerber':
-            flt = "Gerber Files (*.GBR);;All Files (*.*)"
+            flt = "Gerber Files (*.GBR);;PDF Files (*.PDF);;All Files (*.*)"
         elif obj.kind == 'excellon':
         elif obj.kind == 'excellon':
-            flt = "Excellon Files (*.DRL);;All Files (*.*)"
+            flt = "Excellon Files (*.DRL);;PDF Files (*.PDF);;All Files (*.*)"
         elif obj.kind == 'cncjob':
         elif obj.kind == 'cncjob':
-            "GCode Files (*.NC);;All Files (*.*)"
+            flt = "GCode Files (*.NC);;PDF Files (*.PDF);;All Files (*.*)"
 
 
         self.source_editor_tab = TextEditor(app=self, plain_text=True)
         self.source_editor_tab = TextEditor(app=self, plain_text=True)
 
 
@@ -10254,13 +10254,6 @@ class App(QtCore.QObject):
             self.inform.emit('[WARNING_NOTCL] %s' % _("Save Project cancelled."))
             self.inform.emit('[WARNING_NOTCL] %s' % _("Save Project cancelled."))
             return
             return
 
 
-        try:
-            f = open(filename, 'r')
-            f.close()
-        except IOError:
-            self.inform.emit('[ERROR_NOTCL] %s' % _("The object is used by another application."))
-            return
-
         if use_thread is True:
         if use_thread is True:
             self.worker_task.emit({'fcn': self.save_project,
             self.worker_task.emit({'fcn': self.save_project,
                                    'params': [filename, quit_action]})
                                    'params': [filename, quit_action]})
@@ -12167,14 +12160,14 @@ class App(QtCore.QObject):
                     g = json.dumps(d, default=to_dict, indent=2, sort_keys=True).encode('utf-8')
                     g = json.dumps(d, default=to_dict, indent=2, sort_keys=True).encode('utf-8')
                     # # Write
                     # # Write
                     f.write(g)
                     f.write(g)
-                self.inform.emit('[success] %s: %s' %
-                                 (_("Project saved to"), filename))
+                self.inform.emit('[success] %s: %s' % (_("Project saved to"), filename))
             else:
             else:
                 # Open file
                 # Open file
                 try:
                 try:
                     f = open(filename, 'w')
                     f = open(filename, 'w')
                 except IOError:
                 except IOError:
                     App.log.error("Failed to open file for saving: %s", filename)
                     App.log.error("Failed to open file for saving: %s", filename)
+                    self.inform.emit('[ERROR_NOTCL] %s' % _("The object is used by another application."))
                     return
                     return
 
 
                 # Write
                 # Write
@@ -12188,8 +12181,7 @@ class App(QtCore.QObject):
                 except IOError:
                 except IOError:
                     if silent is False:
                     if silent is False:
                         self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
                         self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
-                                         (_("Failed to verify project file"), filename, _("Retry to save it."))
-                                         )
+                                         (_("Failed to verify project file"), filename, _("Retry to save it.")))
                     return
                     return
 
 
                 try:
                 try:
@@ -12197,8 +12189,7 @@ class App(QtCore.QObject):
                 except Exception:
                 except Exception:
                     if silent is False:
                     if silent is False:
                         self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
                         self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
-                                         (_("Failed to parse saved project file"), filename, _("Retry to save it."))
-                                         )
+                                         (_("Failed to parse saved project file"), filename, _("Retry to save it.")))
                     f.close()
                     f.close()
                     return
                     return
                 saved_f.close()
                 saved_f.close()
@@ -12209,8 +12200,7 @@ class App(QtCore.QObject):
                                          (_("Project saved to"), filename))
                                          (_("Project saved to"), filename))
                     else:
                     else:
                         self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
                         self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
-                                         (_("Failed to parse saved project file"), filename, _("Retry to save it."))
-                                         )
+                                         (_("Failed to parse saved project file"), filename, _("Retry to save it.")))
 
 
                 tb_settings = QSettings("Open Source", "FlatCAM")
                 tb_settings = QSettings("Open Source", "FlatCAM")
                 lock_state = self.ui.lock_action.isChecked()
                 lock_state = self.ui.lock_action.isChecked()

+ 7 - 1
FlatCAMObj.py

@@ -1288,6 +1288,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
             def iso_init(geo_obj, app_obj):
             def iso_init(geo_obj, app_obj):
                 # Propagate options
                 # Propagate options
                 geo_obj.options["cnctooldia"] = str(self.options["isotooldia"])
                 geo_obj.options["cnctooldia"] = str(self.options["isotooldia"])
+                geo_obj.tool_type = self.ui.tool_type_radio.get_value().upper()
+
                 geo_obj.solid_geometry = []
                 geo_obj.solid_geometry = []
                 for i in range(passes):
                 for i in range(passes):
                     iso_offset = dia * ((2 * i + 1) / 2.0) - (i * (overlap / 100) * dia)
                     iso_offset = dia * ((2 * i + 1) / 2.0) - (i * (overlap / 100) * dia)
@@ -1417,6 +1419,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                 def iso_init(geo_obj, app_obj):
                 def iso_init(geo_obj, app_obj):
                     # Propagate options
                     # Propagate options
                     geo_obj.options["cnctooldia"] = str(self.options["isotooldia"])
                     geo_obj.options["cnctooldia"] = str(self.options["isotooldia"])
+                    geo_obj.tool_type = self.ui.tool_type_radio.get_value().upper()
 
 
                     # if milling type is climb then the move is counter-clockwise around features
                     # if milling type is climb then the move is counter-clockwise around features
                     mill_t = 1 if milling_type == 'cl' else 0
                     mill_t = 1 if milling_type == 'cl' else 0
@@ -3603,6 +3606,9 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         self.old_toolchangeg_state = self.app.defaults["geometry_toolchange"]
         self.old_toolchangeg_state = self.app.defaults["geometry_toolchange"]
         self.units_found = self.app.defaults['units']
         self.units_found = self.app.defaults['units']
 
 
+        # this variable can be updated by the Object that generates the geometry
+        self.tool_type = 'C1'
+
         # Attributes to be included in serialization
         # Attributes to be included in serialization
         # Always append to it because it carries contents
         # Always append to it because it carries contents
         # from predecessors.
         # from predecessors.
@@ -3859,7 +3865,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                         'offset': 'Path',
                         'offset': 'Path',
                         'offset_value': 0.0,
                         'offset_value': 0.0,
                         'type': _('Rough'),
                         'type': _('Rough'),
-                        'tool_type': 'C1',
+                        'tool_type': self.tool_type,
                         'data': new_data,
                         'data': new_data,
                         'solid_geometry': self.solid_geometry
                         'solid_geometry': self.solid_geometry
                     }
                     }

+ 6 - 0
README.md

@@ -15,6 +15,12 @@ CAD program, and create G-Code for Isolation routing.
 - optimizations in Paint Tool
 - optimizations in Paint Tool
 - maximum range for Cut Z is now zero to deal with the situation when using V-shape with tip-dia same value with cut width
 - maximum range for Cut Z is now zero to deal with the situation when using V-shape with tip-dia same value with cut width
 - modified QValidator in FCDoubleSpinner() GUI element to allow entering the minus sign when the range maximum is set as 0.0; also for positive numbers allowed entering the symbol plus
 - modified QValidator in FCDoubleSpinner() GUI element to allow entering the minus sign when the range maximum is set as 0.0; also for positive numbers allowed entering the symbol plus
+- made sure that if in Gerber UI the isolation is made with a V-Shape tool then the tool type is automatically updated on the generated Geometry Object
+- added ability to save the Source File as PDF (still have to adjust the page size)
+- fixed the generate_from_geometry_2() method to use the default values in case the parameters are None
+- added ability to save the Source File as PDF - fixed page size and added line breaks
+- more mods to generate_from_geometry_2() method
+- fixed bug saving the FlatCAM project saying the file is used by another application
 
 
 16.12.2019
 16.12.2019
 
 

+ 27 - 22
camlib.py

@@ -3304,14 +3304,12 @@ class CNCjob(Geometry):
         return self.gcode
         return self.gcode
 
 
     def generate_from_geometry_2(
     def generate_from_geometry_2(
-            self, geometry, append=True,
-            tooldia=None, offset=0.0, tolerance=0,
-            z_cut=1.0, z_move=2.0,
-            feedrate=2.0, feedrate_z=2.0, feedrate_rapid=30,
-            spindlespeed=None, spindledir='CW', dwell=False, dwelltime=1.0,
+            self, geometry, append=True, tooldia=None, offset=0.0, tolerance=0, z_cut=None, z_move=None,
+            feedrate=None, feedrate_z=None, feedrate_rapid=None,
+            spindlespeed=None, spindledir='CW', dwell=False, dwelltime=None,
             multidepth=False, depthpercut=None,
             multidepth=False, depthpercut=None,
-            toolchange=False, toolchangez=1.0, toolchangexy="0.0, 0.0",
-            extracut=False, extracut_length=0.1, startz=None, endz=2.0,
+            toolchange=False, toolchangez=None, toolchangexy="0.0, 0.0",
+            extracut=False, extracut_length=None, startz=None, endz=None,
             pp_geometry_name=None, tool_no=1):
             pp_geometry_name=None, tool_no=1):
         """
         """
         Second algorithm to generate from Geometry.
         Second algorithm to generate from Geometry.
@@ -3406,27 +3404,31 @@ class CNCjob(Geometry):
         log.debug("%d paths" % len(flat_geometry))
         log.debug("%d paths" % len(flat_geometry))
 
 
         try:
         try:
-            self.tooldia = float(tooldia) if tooldia else None
+            self.tooldia = float(tooldia) if tooldia else self.app.defaults["geometry_cnctooldia"]
         except ValueError:
         except ValueError:
-            self.tooldia = [float(el) for el in tooldia.split(',') if el != ''] if tooldia else None
+            self.tooldia = [float(el) for el in tooldia.split(',') if el != ''] if tooldia is not None else \
+                self.app.defaults["geometry_cnctooldia"]
 
 
-        self.z_cut = float(z_cut) if z_cut is not None else None
-        self.z_move = float(z_move) if z_move is not None else None
+        self.z_cut = float(z_cut) if z_cut is not None else self.app.defaults["geometry_cutz"]
+        self.z_move = float(z_move) if z_move is not None else self.app.defaults["geometry_travelz"]
 
 
-        self.feedrate = float(feedrate) if feedrate else None
-        self.z_feedrate = float(feedrate_z) if feedrate_z is not None else None
-        self.feedrate_rapid = float(feedrate_rapid) if feedrate_rapid else None
+        self.feedrate = float(feedrate) if feedrate is not None else self.app.defaults["geometry_feedrate"]
+        self.z_feedrate = float(feedrate_z) if feedrate_z is not None else self.app.defaults["geometry_feedrate_z"]
+        self.feedrate_rapid = float(feedrate_rapid) if feedrate_rapid is not None else \
+            self.app.defaults["geometry_feedrate_rapid"]
 
 
         self.spindlespeed = int(spindlespeed) if spindlespeed != 0 else None
         self.spindlespeed = int(spindlespeed) if spindlespeed != 0 else None
         self.spindledir = spindledir
         self.spindledir = spindledir
         self.dwell = dwell
         self.dwell = dwell
-        self.dwelltime = float(dwelltime) if dwelltime else None
+        self.dwelltime = float(dwelltime) if dwelltime is not None else self.app.defaults["geometry_dwelltime"]
 
 
-        self.startz = float(startz) if startz is not None else None
-        self.z_end = float(endz) if endz is not None else None
-        self.z_depthpercut = float(depthpercut) if depthpercut else None
+        self.startz = float(startz) if startz is not None else self.app.defaults["geometry_startz"]
+        self.z_end = float(endz) if endz is not None else self.app.defaults["geometry_endz"]
+        self.z_depthpercut = float(depthpercut) if depthpercut is not None else 0.0
         self.multidepth = multidepth
         self.multidepth = multidepth
-        self.z_toolchange = float(toolchangez) if toolchangez is not None else None
+        self.z_toolchange = float(toolchangez) if toolchangez is not None else self.app.defaults["geometry_toolchangez"]
+        self.extracut_length = float(extracut_length) if extracut_length is not None else \
+            self.app.defaults["geometry_extracut_length"]
 
 
         try:
         try:
             if toolchangexy == '':
             if toolchangexy == '':
@@ -3486,7 +3488,10 @@ class CNCjob(Geometry):
                 return 'fail'
                 return 'fail'
 
 
         # made sure that depth_per_cut is no more then the z_cut
         # made sure that depth_per_cut is no more then the z_cut
-        if abs(self.z_cut) < self.z_depthpercut:
+        try:
+            if abs(self.z_cut) < self.z_depthpercut:
+                self.z_depthpercut = abs(self.z_cut)
+        except TypeError:
             self.z_depthpercut = abs(self.z_cut)
             self.z_depthpercut = abs(self.z_cut)
 
 
         # ## Index first and last points in paths
         # ## Index first and last points in paths
@@ -3601,7 +3606,7 @@ class CNCjob(Geometry):
                 if not multidepth:
                 if not multidepth:
                     # calculate the cut distance
                     # calculate the cut distance
                     total_cut += geo.length
                     total_cut += geo.length
-                    self.gcode += self.create_gcode_single_pass(geo, extracut, extracut_length, tolerance,
+                    self.gcode += self.create_gcode_single_pass(geo, extracut, self.extracut_length, tolerance,
                                                                 old_point=current_pt)
                                                                 old_point=current_pt)
 
 
                 # --------- Multi-pass ---------
                 # --------- Multi-pass ---------
@@ -3616,7 +3621,7 @@ class CNCjob(Geometry):
 
 
                     total_cut += (geo.length * nr_cuts)
                     total_cut += (geo.length * nr_cuts)
 
 
-                    self.gcode += self.create_gcode_multi_pass(geo, extracut, extracut_length, tolerance,
+                    self.gcode += self.create_gcode_multi_pass(geo, extracut, self.extracut_length, tolerance,
                                                                postproc=p, old_point=current_pt)
                                                                postproc=p, old_point=current_pt)
 
 
                 # calculate the travel distance
                 # calculate the travel distance

+ 38 - 3
flatcamEditors/FlatCAMTextEditor.py

@@ -8,6 +8,12 @@
 from flatcamGUI.GUIElements import *
 from flatcamGUI.GUIElements import *
 from PyQt5 import QtPrintSupport
 from PyQt5 import QtPrintSupport
 
 
+from reportlab.platypus import SimpleDocTemplate, Paragraph
+from reportlab.lib.styles import getSampleStyleSheet
+from reportlab.lib.units import inch, mm
+
+from io import StringIO
+
 import gettext
 import gettext
 import FlatCAMTranslation as fcTranslate
 import FlatCAMTranslation as fcTranslate
 import builtins
 import builtins
@@ -217,9 +223,38 @@ class TextEditor(QtWidgets.QWidget):
         else:
         else:
             try:
             try:
                 my_gcode = self.code_editor.toPlainText()
                 my_gcode = self.code_editor.toPlainText()
-                with open(filename, 'w') as f:
-                    for line in my_gcode:
-                        f.write(line)
+                if filename.rpartition('.')[2].lower() == 'pdf':
+                    page_size = (
+                        self.app.plotcanvas.pagesize_dict[self.app.defaults['global_workspaceT']][0] * mm,
+                        self.app.plotcanvas.pagesize_dict[self.app.defaults['global_workspaceT']][1] * mm
+                    )
+
+                    # add new line after each line
+                    lined_gcode = my_gcode.replace("\n", "<br />")
+
+                    styles = getSampleStyleSheet()
+                    styleN = styles['Normal']
+                    styleH = styles['Heading1']
+                    story = []
+
+                    doc = SimpleDocTemplate(
+                        filename,
+                        pagesize=page_size,
+                        bottomMargin=0.4 * inch,
+                        topMargin=0.6 * inch,
+                        rightMargin=0.8 * inch,
+                        leftMargin=0.8 * inch)
+
+                    P = Paragraph(lined_gcode, styleN)
+                    story.append(P)
+
+                    doc.build(
+                        story,
+                    )
+                else:
+                    with open(filename, 'w') as f:
+                        for line in my_gcode:
+                            f.write(line)
             except FileNotFoundError:
             except FileNotFoundError:
                 self.app.inform.emit('[WARNING] %s' % _("No such file or directory"))
                 self.app.inform.emit('[WARNING] %s' % _("No such file or directory"))
                 return
                 return