Ver Fonte

- wip in the GCode Editor

Marius Stanciu há 5 anos atrás
pai
commit
cf78211a6f

+ 1 - 0
CHANGELOG.md

@@ -10,6 +10,7 @@ CHANGELOG for FlatCAM beta
 22.07.2020
 
 - working on a proper GCode Editor
+- wip in the GCode Editor
 
 21.07.2020
 

+ 1 - 1
appEditors/AppExcEditor.py

@@ -2569,7 +2569,7 @@ class AppExcEditor(QtCore.QObject):
 
         self.set_ui()
 
-        # now that we hava data, create the appGUI interface and add it to the Tool Tab
+        # now that we have data, create the appGUI interface and add it to the Tool Tab
         self.build_ui(first_run=True)
 
         # we activate this after the initial build as we don't need to see the tool been populated

+ 140 - 66
appEditors/appGCodeEditor.py

@@ -6,8 +6,8 @@
 # ##########################################################
 
 from appEditors.AppTextEditor import AppTextEditor
-from appObjects import FlatCAMCNCJob
-from appGUI.GUIElements import FCFileSaveDialog, FCEntry, FCTextAreaExtended, FCTextAreaLineNumber, FCButton
+from appObjects.FlatCAMCNCJob import CNCJobObject
+from appGUI.GUIElements import FCTextArea, FCEntry, FCButton
 from PyQt5 import QtWidgets, QtCore, QtGui
 
 # from io import StringIO
@@ -25,7 +25,7 @@ if '_' not in builtins.__dict__:
 log = logging.getLogger('base')
 
 
-class appGCodeEditor(QtCore.QObject):
+class AppGCodeEditor(QtCore.QObject):
 
     def __init__(self, app, parent=None):
         super().__init__(parent=parent)
@@ -34,7 +34,7 @@ class appGCodeEditor(QtCore.QObject):
         self.plain_text = ''
         self.callback = lambda x: None
 
-        self.ui = appGCodeEditorUI(app=self.app)
+        self.ui = AppGCodeEditorUI(app=self.app)
 
         # #################################################################################
         # ################### SIGNALS #####################################################
@@ -44,10 +44,44 @@ class appGCodeEditor(QtCore.QObject):
         self.code_edited = ''
 
     def set_ui(self):
-        pass
+        # #############################################################################################################
+        # ############# ADD a new TAB in the PLot Tab Area
+        # #############################################################################################################
+        self.ui.gcode_editor_tab = AppTextEditor(app=self.app, plain_text=True)
+
+        # add the tab if it was closed
+        self.app.ui.plot_tab_area.addTab(self.ui.gcode_editor_tab, '%s' % _("Code Editor"))
+        self.ui.gcode_editor_tab.setObjectName('code_editor_tab')
+
+        # delete the absolute and relative position and messages in the infobar
+        self.app.ui.position_label.setText("")
+        self.app.ui.rel_position_label.setText("")
+
+        self.ui.gcode_editor_tab.code_editor.completer_enable = False
+        self.ui.gcode_editor_tab.buttonRun.hide()
+
+        # Switch plot_area to CNCJob tab
+        self.app.ui.plot_tab_area.setCurrentWidget(self.ui.gcode_editor_tab)
+
+        self.ui.gcode_editor_tab.t_frame.hide()
+
+        self.ui.gcode_editor_tab.t_frame.show()
+        self.app.proc_container.view.set_idle()
+        # #############################################################################################################
+        # #############################################################################################################
+
+        self.ui.append_text.set_value(self.app.defaults["cncjob_append"])
+        self.ui.prepend_text.set_value(self.app.defaults["cncjob_prepend"])
+
+        self.ui.exit_editor_button.buttonSave.clicked.connect(self.update_fcgcode)
 
     def build_ui(self):
-        pass
+        # Remove anything else in the GUI Selected Tab
+        self.app.ui.selected_scroll_area.takeWidget()
+        # Put ourselves in the GUI Selected Tab
+        self.app.ui.selected_scroll_area.setWidget(self.ui.edit_widget)
+        # Switch notebook to Selected page
+        self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
 
     def ui_connect(self):
         pass
@@ -64,35 +98,31 @@ class appGCodeEditor(QtCore.QObject):
         self.buttonSave.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as_red.png'))
 
     def edit_fcgcode(self, cnc_obj):
-        assert isinstance(cnc_obj, FlatCAMCNCJob)
+        assert isinstance(cnc_obj, CNCJobObject)
         self.gcode_obj = cnc_obj
 
-        preamble = str(self.ui.prepend_text.get_value())
-        postamble = str(self.ui.append_text.get_value())
-
         gcode_text = self.gcode_obj.source_file
 
-        self.gcode_editor_tab.buttonSave.clicked.connect(self.on_update_source_file)
+        self.set_ui()
+        self.build_ui()
 
+        # then append the text from GCode to the text editor
+        self.ui.gcode_editor_tab.load_text(gcode_text, move_to_start=True, clear_text=True)
         self.app.inform.emit('[success] %s...' % _('Loaded Machine Code into Code Editor'))
 
-        self.ui.gcode_editor_tab.load_text(self, gcode_text, move_to_start=True, clear_text=True)
-
-    def update_gcode(self):
+    def update_fcgcode(self):
+        preamble = str(self.ui.prepend_text.get_value())
+        postamble = str(self.ui.append_text.get_value())
         my_gcode = self.ui.gcode_editor_tab.code_editor.toPlainText()
         self.gcode_obj.source_file = my_gcode
 
         self.ui.gcode_editor_tab.buttonSave.setStyleSheet("")
         self.ui.gcode_editor_tab.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
 
-    def handleOpen(self, filt=None):
-        self.app.defaults.report_usage("handleOpen()")
+    def on_open_gcode(self):
 
-        if filt:
-            _filter_ = filt
-        else:
-            _filter_ = "G-Code Files (*.nc);; G-Code Files (*.txt);; G-Code Files (*.tap);; G-Code Files (*.cnc);; " \
-                       "All Files (*.*)"
+        _filter_ = "G-Code Files (*.nc);; G-Code Files (*.txt);; G-Code Files (*.tap);; G-Code Files (*.cnc);; " \
+                   "All Files (*.*)"
 
         path, _f = QtWidgets.QFileDialog.getOpenFileName(
             caption=_('Open file'), directory=self.app.get_last_folder(), filter=_filter_)
@@ -102,11 +132,11 @@ class appGCodeEditor(QtCore.QObject):
             if file.open(QtCore.QIODevice.ReadOnly):
                 stream = QtCore.QTextStream(file)
                 self.code_edited = stream.readAll()
-                self.ui.gcode_editor_tab.load_text(self, self.code_edited, move_to_start=True, clear_text=True)
+                self.ui.gcode_editor_tab.load_text(self.code_edited, move_to_start=True, clear_text=True)
                 file.close()
 
 
-class appGCodeEditorUI:
+class AppGCodeEditorUI:
     def __init__(self, app):
         self.app = app
 
@@ -121,52 +151,96 @@ class appGCodeEditorUI:
         #     QtWidgets.QSizePolicy.MinimumExpanding
         # )
 
-        self.layout = QtWidgets.QVBoxLayout()
-        self.layout.setContentsMargins(0, 0, 0, 0)
-
-        self.editor_frame = QtWidgets.QFrame()
-        self.editor_frame.setContentsMargins(0, 0, 0, 0)
-        self.layout.addWidget(self.editor_frame)
-
-        self.editor_layout = QtWidgets.QGridLayout(self.editor_frame)
-        self.editor_layout.setContentsMargins(2, 2, 2, 2)
-        self.editor_frame.setLayout(self.editor_layout)
-
-        # #############################################################################################################
-        # ############# ADD a new TAB in the PLot Tab Area
-        # #############################################################################################################
-        self.gcode_editor_tab = AppTextEditor(app=self.app, plain_text=True)
-
-        # add the tab if it was closed
-        self.app.ui.plot_tab_area.addTab(self.gcode_editor_tab, '%s' % _("Code Editor"))
-        self.gcode_editor_tab.setObjectName('code_editor_tab')
-
-        # delete the absolute and relative position and messages in the infobar
-        self.app.ui.position_label.setText("")
-        self.app.ui.rel_position_label.setText("")
+        self.gcode_editor_tab = None
+
+        self.edit_widget = QtWidgets.QWidget()
+        # ## Box for custom widgets
+        # This gets populated in offspring implementations.
+        layout = QtWidgets.QVBoxLayout()
+        self.edit_widget.setLayout(layout)
+
+        # add a frame and inside add a vertical box layout. Inside this vbox layout I add all the Drills widgets
+        # this way I can hide/show the frame
+        self.edit_frame = QtWidgets.QFrame()
+        self.edit_frame.setContentsMargins(0, 0, 0, 0)
+        layout.addWidget(self.edit_frame)
+        self.edit_box = QtWidgets.QVBoxLayout()
+        self.edit_box.setContentsMargins(0, 0, 0, 0)
+        self.edit_frame.setLayout(self.edit_box)
+
+        # ## Page Title box (spacing between children)
+        self.title_box = QtWidgets.QHBoxLayout()
+        self.edit_box.addLayout(self.title_box)
+
+        # ## Page Title icon
+        pixmap = QtGui.QPixmap(self.app.resource_location + '/flatcam_icon32.png')
+        self.icon = QtWidgets.QLabel()
+        self.icon.setPixmap(pixmap)
+        self.title_box.addWidget(self.icon, stretch=0)
+
+        # ## Title label
+        self.title_label = QtWidgets.QLabel("<font size=5><b>%s</b></font>" % _('GCode Editor'))
+        self.title_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+        self.title_box.addWidget(self.title_label, stretch=1)
+
+        # ## Object name
+        self.name_box = QtWidgets.QHBoxLayout()
+        self.edit_box.addLayout(self.name_box)
+        name_label = QtWidgets.QLabel(_("Name:"))
+        self.name_box.addWidget(name_label)
+        self.name_entry = FCEntry()
+        self.name_box.addWidget(self.name_entry)
+
+        # Prepend text to GCode
+        prependlabel = QtWidgets.QLabel('%s:' % _('Prepend to CNC Code'))
+        prependlabel.setToolTip(
+            _("Type here any G-Code commands you would\n"
+              "like to add at the beginning of the G-Code file.")
+        )
+        self.edit_box.addWidget(prependlabel)
 
-        self.gcode_editor_tab.code_editor.completer_enable = False
-        self.gcode_editor_tab.buttonRun.hide()
+        self.prepend_text = FCTextArea()
+        self.prepend_text.setPlaceholderText(
+            _("Type here any G-Code commands you would\n"
+              "like to add at the beginning of the G-Code file.")
+        )
+        self.edit_box.addWidget(self.prepend_text)
+
+        # Append text to GCode
+        appendlabel = QtWidgets.QLabel('%s:' % _('Append to CNC Code'))
+        appendlabel.setToolTip(
+            _("Type here any G-Code commands you would\n"
+              "like to append to the generated file.\n"
+              "I.e.: M2 (End of program)")
+        )
+        self.edit_box.addWidget(appendlabel)
 
-        # Switch plot_area to CNCJob tab
-        self.app.ui.plot_tab_area.setCurrentWidget(self.gcode_editor_tab)
+        self.append_text = FCTextArea()
+        self.append_text.setPlaceholderText(
+            _("Type here any G-Code commands you would\n"
+              "like to append to the generated file.\n"
+              "I.e.: M2 (End of program)")
+        )
+        self.edit_box.addWidget(self.append_text)
+
+        h_lay = QtWidgets.QHBoxLayout()
+        h_lay.setAlignment(QtCore.Qt.AlignVCenter)
+        self.edit_box.addLayout(h_lay)
+
+        # GO Button
+        self.update_gcode_button = FCButton(_('Update Code'))
+        # self.update_gcode_button.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
+        self.update_gcode_button.setToolTip(
+            _("Update the Gcode in the Editor with the values\n"
+              "in the 'Prepend' and 'Append' text boxes.")
+        )
 
-        self.gcode_editor_tab.t_frame.hide()
-        # then append the text from GCode to the text editor
-        try:
-            self.gcode_editor_tab.load_text(self.app.gcode_edited.getvalue(), move_to_start=True, clear_text=True)
-        except Exception as e:
-            log.debug('FlatCAMCNNJob.on_edit_code_click() -->%s' % str(e))
-            self.app.inform.emit('[ERROR] %s %s' % ('FlatCAMCNNJob.on_edit_code_click() -->', str(e)))
-            return
-
-        self.gcode_editor_tab.t_frame.show()
-        self.app.proc_container.view.set_idle()
+        h_lay.addWidget(self.update_gcode_button)
 
-        self.layout.addStretch()
+        layout.addStretch()
 
         # Editor
-        self.exit_editor_button = QtWidgets.QPushButton(_('Exit Editor'))
+        self.exit_editor_button = FCButton(_('Exit Editor'))
         self.exit_editor_button.setIcon(QtGui.QIcon(self.app.resource_location + '/power16.png'))
         self.exit_editor_button.setToolTip(
             _("Exit from Editor.")
@@ -177,9 +251,9 @@ class appGCodeEditorUI:
                                               font-weight: bold;
                                           }
                                           """)
-        self.layout.addWidget(self.exit_editor_button)
-        # ############################ FINSIHED GUI ###################################
-        # #############################################################################
+        layout.addWidget(self.exit_editor_button)
+        # ############################ FINSIHED GUI ##################################################################
+        # #############################################################################################################
 
     def confirmation_message(self, accepted, minval, maxval):
         if accepted is False:

+ 1 - 2
appObjects/FlatCAMCNCJob.py

@@ -595,8 +595,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
         try:
             self.gcode_editor_tab.load_text(self.app.gcode_edited.getvalue(), move_to_start=True, clear_text=True)
         except Exception as e:
-            log.debug('FlatCAMCNNJob.on_edit_code_click() -->%s' % str(e))
-            self.app.inform.emit('[ERROR] %s %s' % ('FlatCAMCNNJob.on_edit_code_click() -->', str(e)))
+            log.debug('FlatCAMCNCJob.on_edit_code_click() -->%s' % str(e))
             return
 
         self.gcode_editor_tab.t_frame.show()

+ 20 - 10
appObjects/FlatCAMGeometry.py

@@ -1881,6 +1881,7 @@ class GeometryObject(FlatCAMObj, Geometry):
             job_obj.z_pdepth = float(self.app.defaults["geometry_z_pdepth"])
             job_obj.feedrate_probe = float(self.app.defaults["geometry_feedrate_probe"])
 
+            total_gcode = ''
             for tooluid_key in list(tools_dict.keys()):
                 tool_cnt += 1
 
@@ -1970,6 +1971,8 @@ class GeometryObject(FlatCAMObj, Geometry):
                 else:
                     dia_cnc_dict['gcode'] = res
 
+                total_gcode += res
+
                 # tell gcode_parse from which point to start drawing the lines depending on what kind of
                 # object is the source of gcode
                 job_obj.toolchange_xy_type = "geometry"
@@ -1993,6 +1996,8 @@ class GeometryObject(FlatCAMObj, Geometry):
                 })
                 dia_cnc_dict.clear()
 
+            job_obj.source_file = total_gcode
+
         # Object initialization function for app.app_obj.new_object()
         # RUNNING ON SEPARATE THREAD!
         def job_init_multi_geometry(job_obj, app_obj):
@@ -2031,6 +2036,7 @@ class GeometryObject(FlatCAMObj, Geometry):
                     self.app.inform.emit('[ERROR_NOTCL] %s...' % _('Cancelled. Empty file, it has no geometry'))
                     return 'fail'
 
+            total_gcode = ''
             for tooluid_key in list(tools_dict.keys()):
                 tool_cnt += 1
                 dia_cnc_dict = deepcopy(tools_dict[tooluid_key])
@@ -2123,6 +2129,7 @@ class GeometryObject(FlatCAMObj, Geometry):
                     return 'fail'
                 else:
                     dia_cnc_dict['gcode'] = res
+                total_gcode += res
 
                 self.app.inform.emit('[success] %s' % _("G-Code parsing in progress..."))
                 dia_cnc_dict['gcode_parsed'] = job_obj.gcode_parse()
@@ -2149,6 +2156,8 @@ class GeometryObject(FlatCAMObj, Geometry):
                 })
                 dia_cnc_dict.clear()
 
+            job_obj.source_file = total_gcode
+
         if use_thread:
             # To be run in separate thread
             def job_thread(a_obj):
@@ -2288,17 +2297,18 @@ class GeometryObject(FlatCAMObj, Geometry):
             # it seems that the tolerance needs to be a lot lower value than 0.01 and it was hardcoded initially
             # to a value of 0.0005 which is 20 times less than 0.01
             tol = float(self.app.defaults['global_tolerance']) / 20
-            job_obj.generate_from_geometry_2(
-                self, tooldia=tooldia, offset=offset, tolerance=tol,
-                z_cut=z_cut, z_move=z_move,
-                feedrate=feedrate, feedrate_z=feedrate_z, feedrate_rapid=feedrate_rapid,
-                spindlespeed=spindlespeed, dwell=dwell, dwelltime=dwelltime,
-                multidepth=multidepth, depthpercut=depthperpass,
-                toolchange=toolchange, toolchangez=toolchangez, toolchangexy=toolchangexy,
-                extracut=extracut, extracut_length=extracut_length, startz=startz, endz=endz, endxy=endxy,
-                pp_geometry_name=ppname_g
+            res = job_obj.generate_from_geometry_2(self, tooldia=tooldia, offset=offset, tolerance=tol,
+                                                   z_cut=z_cut, z_move=z_move, feedrate=feedrate,
+                                                   feedrate_z=feedrate_z, feedrate_rapid=feedrate_rapid,
+                                                   spindlespeed=spindlespeed, dwell=dwell, dwelltime=dwelltime,
+                                                   multidepth=multidepth, depthpercut=depthperpass,
+                                                   toolchange=toolchange, toolchangez=toolchangez,
+                                                   toolchangexy=toolchangexy,
+                                                   extracut=extracut, extracut_length=extracut_length,
+                                                   startz=startz, endz=endz, endxy=endxy,
+                                                   pp_geometry_name=ppname_g
             )
-
+            job_obj.source_file = res
             # tell gcode_parse from which point to start drawing the lines depending on what kind of object is the
             # source of gcode
             job_obj.toolchange_xy_type = "geometry"

+ 1 - 0
appTools/ToolDrilling.py

@@ -1797,6 +1797,7 @@ class ToolDrilling(AppTool, Excellon):
                     self.total_gcode_parsed += tool_gcode_parsed
 
             job_obj.gcode = self.total_gcode
+            job_obj.source_file = self.total_gcode
             job_obj.gcode_parsed = self.total_gcode_parsed
             if job_obj.gcode == 'fail':
                 return 'fail'

+ 4 - 0
appTools/ToolSolderPaste.py

@@ -913,6 +913,7 @@ class SolderPaste(AppTool):
             job_obj.options['xmax'] = xmax
             job_obj.options['ymax'] = ymax
 
+            total_gcode = ''
             for tooluid_key, tooluid_value in obj.tools.items():
                 # find the tool_dia associated with the tooluid_key
                 tool_dia = tooluid_value['tooldia']
@@ -934,6 +935,7 @@ class SolderPaste(AppTool):
                     return 'fail'
                 else:
                     tool_cnc_dict['gcode'] = res
+                total_gcode += res
 
                 # ## PARSE GCODE # ##
                 tool_cnc_dict['gcode_parsed'] = job_obj.gcode_parse()
@@ -949,6 +951,8 @@ class SolderPaste(AppTool):
                 })
                 tool_cnc_dict.clear()
 
+            job_obj.source_file = total_gcode
+
         if use_thread:
             # To be run in separate thread
             def job_thread(app_obj):

+ 11 - 1
app_Main.py

@@ -83,6 +83,7 @@ from appEditors.AppGeoEditor import AppGeoEditor
 from appEditors.AppExcEditor import AppExcEditor
 from appEditors.AppGerberEditor import AppGerberEditor
 from appEditors.AppTextEditor import AppTextEditor
+from appEditors.appGCodeEditor import AppGCodeEditor
 from appParsers.ParseHPGL2 import HPGL2
 
 # FlatCAM Workers
@@ -1574,6 +1575,12 @@ class App(QtCore.QObject):
             self.grb_editor = AppGerberEditor(self)
         except Exception as es:
             log.debug("app_Main.__init__() --> Gerber Editor Error: %s" % str(es))
+
+        try:
+            self.gcode_editor = AppGCodeEditor(self)
+        except Exception as es:
+            log.debug("app_Main.__init__() --> GCode Editor Error: %s" % str(es))
+
         self.log.debug("Finished adding FlatCAM Editor's.")
 
         self.set_ui_title(name=_("New Project - Not saved"))
@@ -2226,7 +2233,10 @@ class App(QtCore.QObject):
             if self.ui.splitter.sizes()[0] == 0:
                 self.ui.splitter.setSizes([1, 1])
 
-            edited_object.on_edit_code_click()
+            # set call source to the Editor we go into
+            self.call_source = 'gcode_editor'
+
+            self.gcode_editor.edit_fcgcode(edited_object)
             return
 
         # make sure that we can't select another object while in Editor Mode:

+ 1 - 0
tclCommands/TclCommandDrillcncjob.py

@@ -332,6 +332,7 @@ class TclCommandDrillcncjob(TclCommandSignaled):
             job_obj.excellon_optimization_type = opt_type
 
             ret_val = job_obj.generate_from_excellon_by_tool(obj, tools, use_ui=False)
+            job_obj.source_file = ret_val
 
             if ret_val == 'fail':
                 return 'fail'