ソースを参照

- fixed bug in Geometry Editor that did not allow the copy of geometric elements
- created a new class that holds all the Code Editor functionality and integrated as a Editor in FlatCAM, the location is in flatcamEditors folder
- remade all the functions for view_source, scripts and view_code to use the new TextEditor class; now all the Code Editor tabs are being kept alive, before only one could be in an open state

Marius Stanciu 6 年 前
コミット
83f229ed9e

+ 134 - 275
FlatCAMApp.py

@@ -48,6 +48,7 @@ from FlatCAMPostProc import load_postprocessors
 from flatcamEditors.FlatCAMGeoEditor import FlatCAMGeoEditor
 from flatcamEditors.FlatCAMExcEditor import FlatCAMExcEditor
 from flatcamEditors.FlatCAMGrbEditor import FlatCAMGrbEditor
+from flatcamEditors.FlatCAMTextEditor import TextEditor
 
 from FlatCAMProcess import *
 from FlatCAMWorkerStack import WorkerStack
@@ -1997,16 +1998,6 @@ class App(QtCore.QObject):
         self.ui.tools_defaults_form.tools_film_group.film_color_button.clicked.connect(
             self.on_film_color_button)
 
-        # ########## Modify G-CODE Plot Area TAB ###########
-        self.ui.code_editor.textChanged.connect(self.handleTextChanged)
-        self.ui.buttonOpen.clicked.connect(self.handleOpen)
-        self.ui.buttonSave.clicked.connect(self.handleSaveGCode)
-        self.ui.buttonPrint.clicked.connect(self.handlePrint)
-        self.ui.buttonPreview.clicked.connect(self.handlePreview)
-        self.ui.buttonFind.clicked.connect(self.handleFindGCode)
-        self.ui.buttonReplace.clicked.connect(self.handleReplaceGCode)
-        self.ui.button_copy_all.clicked.connect(self.handleCopyAll)
-
         # portability changed signal
         self.ui.general_defaults_form.general_app_group.portability_cb.stateChanged.connect(self.on_portable_checked)
 
@@ -2356,7 +2347,6 @@ class App(QtCore.QObject):
 
         self.shell = FCShell(self, version=self.version)
         self.shell._edit.set_model_data(self.myKeywords)
-        self.ui.code_editor.set_model_data(self.myKeywords)
         self.shell.setWindowIcon(self.ui.app_icon)
         self.shell.setWindowTitle("FlatCAM Shell")
         self.shell.resize(*self.defaults["global_shell_shape"])
@@ -4099,19 +4089,35 @@ class App(QtCore.QObject):
 
         self.new_object('gerber', 'new_grb', initialize, plot=False)
 
-
-    def new_script_object(self):
+    def new_script_object(self, name=None):
         """
         Creates a new, blank TCL Script object.
-
+        :param name: a name for the new object
         :return: None
         """
         self.report_usage("new_script_object()")
 
         def initialize(obj, self):
-            obj.source_file = ""
+            obj.source_file = _(
+            "#\n"
+            "# CREATE A NEW FLATCAM TCL SCRIPT\n"
+            "# TCL Tutorial here: https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html\n"
+            "#\n\n"
+            "# FlatCAM commands list:\n"
+            "# AddCircle, AddPolygon, AddPolyline, AddRectangle, AlignDrill, AlignDrillGrid, ClearShell, ClearCopper,\n"
+            "# Cncjob, Cutout, Delete, Drillcncjob, ExportGcode, ExportSVG, Exteriors, GeoCutout, GeoUnion, GetNames,\n"
+            "# GetSys, ImportSvg, Interiors, Isolate, Follow, JoinExcellon, JoinGeometry, ListSys, MillDrills,\n"
+            "# MillSlots, Mirror, New, NewGeometry, Offset, OpenExcellon, OpenGCode, OpenGerber, OpenProject,\n"
+            "# Options, Paint, Panelize, Plot, SaveProject, SaveSys, Scale, SetActive, SetSys, Skew, SubtractPoly,\n"
+            "# SubtractRectangle, Version, WriteGCode\n"
+            "#\n\n"
+        )
+        if name is None:
+            outname = 'new_script'
+        else:
+            outname = name
 
-        self.new_object('script', 'new_script', initialize, plot=False)
+        self.new_object('script', outname, initialize, plot=False)
 
 
     def new_notes_object(self):
@@ -4170,7 +4176,6 @@ class App(QtCore.QObject):
         # update the SHELL auto-completer model with the name of the new object
         self.myKeywords.append(obj.options['name'])
         self.shell._edit.set_model_data(self.myKeywords)
-        self.ui.code_editor.set_model_data(self.myKeywords)
 
         if autoselect:
             # select the just opened object but deselect the previous ones
@@ -5037,7 +5042,6 @@ class App(QtCore.QObject):
                 self.ui.util_defaults_form.kw_group.kw_list_text.get_value().replace(' ', '').split(',')
             self.myKeywords = self.tcl_commands_list + self.autocomplete_kw_list + self.tcl_keywords
             self.shell._edit.set_model_data(self.myKeywords)
-            self.ui.code_editor.set_model_data(self.myKeywords)
 
     def del_extension(self, ext_type):
         if ext_type == 'excellon':
@@ -5090,7 +5094,6 @@ class App(QtCore.QObject):
                 self.ui.util_defaults_form.kw_group.kw_list_text.get_value().replace(' ', '').split(',')
             self.myKeywords = self.tcl_commands_list + self.autocomplete_kw_list + self.tcl_keywords
             self.shell._edit.set_model_data(self.myKeywords)
-            self.ui.code_editor.set_model_data(self.myKeywords)
 
     def restore_extensions(self, ext_type):
         if ext_type == 'excellon':
@@ -5114,7 +5117,6 @@ class App(QtCore.QObject):
             self.autocomplete_kw_list = self.default_keywords
             self.myKeywords = self.tcl_commands_list + self.autocomplete_kw_list + self.tcl_keywords
             self.shell._edit.set_model_data(self.myKeywords)
-            self.ui.code_editor.set_model_data(self.myKeywords)
 
     def delete_all_extensions(self, ext_type):
         if ext_type == 'excellon':
@@ -5129,7 +5131,6 @@ class App(QtCore.QObject):
             # update the self.myKeywords so the model is updated
             self.myKeywords = self.tcl_commands_list + self.tcl_keywords
             self.shell._edit.set_model_data(self.myKeywords)
-            self.ui.code_editor.set_model_data(self.myKeywords)
 
     def on_edit_join(self, name=None):
         """
@@ -6554,192 +6555,6 @@ class App(QtCore.QObject):
         # This will write the setting to the platform specific storage.
         del settings
 
-    def handlePrint(self):
-        self.report_usage("handlePrint()")
-
-        dialog = QtPrintSupport.QPrintDialog()
-        if dialog.exec_() == QtWidgets.QDialog.Accepted:
-            self.ui.code_editor.document().print_(dialog.printer())
-
-    def handlePreview(self):
-        self.report_usage("handlePreview()")
-
-        dialog = QtPrintSupport.QPrintPreviewDialog()
-        dialog.paintRequested.connect(self.ui.code_editor.print_)
-        dialog.exec_()
-
-    def handleTextChanged(self):
-        # enable = not self.ui.code_editor.document().isEmpty()
-        # self.ui.buttonPrint.setEnabled(enable)
-        # self.ui.buttonPreview.setEnabled(enable)
-        pass
-
-    def handleOpen(self, filt=None):
-        self.report_usage("handleOpen()")
-
-        if filt:
-            _filter_ = filt
-        else:
-            _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.get_last_folder(), filter=_filter_)
-
-        if path:
-            file = QtCore.QFile(path)
-            if file.open(QtCore.QIODevice.ReadOnly):
-                stream = QtCore.QTextStream(file)
-                self.gcode_edited = stream.readAll()
-                self.ui.code_editor.setPlainText(self.gcode_edited)
-                file.close()
-
-    def handleSaveGCode(self, name=None, filt=None):
-        self.report_usage("handleSaveGCode()")
-
-        if filt:
-            _filter_ = filt
-        else:
-            _filter_ = "G-Code Files (*.nc);; G-Code Files (*.txt);; G-Code Files (*.tap);; G-Code Files (*.cnc);; " \
-                       "All Files (*.*)"
-
-        if name:
-            obj_name = name
-        else:
-            try:
-                obj_name = self.collection.get_active().options['name']
-            except AttributeError:
-                obj_name = 'file'
-                if filt is None:
-                    _filter_ = "FlatConfig Files (*.FlatConfig);;All Files (*.*)"
-
-        try:
-            filename = str(QtWidgets.QFileDialog.getSaveFileName(
-                caption=_("Export G-Code ..."),
-                directory=self.defaults["global_last_folder"] + '/' + str(obj_name),
-                filter=_filter_
-            )[0])
-        except TypeError:
-            filename = str(QtWidgets.QFileDialog.getSaveFileName(caption=_("Export G-Code ..."), filter=_filter_)[0])
-
-        if filename == "":
-            self.inform.emit('[WARNING_NOTCL] %s' %
-                             _("Export Code cancelled."))
-            return
-        else:
-            try:
-                my_gcode = self.ui.code_editor.toPlainText()
-                with open(filename, 'w') as f:
-                    for line in my_gcode:
-                        f.write(line)
-            except FileNotFoundError:
-                self.inform.emit('[WARNING] %s' %
-                                 _("No such file or directory"))
-                return
-            except PermissionError:
-                self.inform.emit('[WARNING] %s' %
-                                 _("Permission denied, saving not possible.\n"
-                                   "Most likely another app is holding the file open and not accessible."))
-                return
-
-        # Just for adding it to the recent files list.
-        if self.defaults["global_open_style"] is False:
-            self.file_opened.emit("cncjob", filename)
-        self.file_saved.emit("cncjob", filename)
-        self.inform.emit('%s: %s' % (_("Saved to"), str(filename)))
-
-    def handleFindGCode(self):
-        self.report_usage("handleFindGCode()")
-
-        flags = QtGui.QTextDocument.FindCaseSensitively
-        text_to_be_found = self.ui.entryFind.get_value()
-
-        r = self.ui.code_editor.find(str(text_to_be_found), flags)
-        if r is False:
-            self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
-
-    def handleReplaceGCode(self):
-        self.report_usage("handleReplaceGCode()")
-
-        old = self.ui.entryFind.get_value()
-        new = self.ui.entryReplace.get_value()
-
-        if self.ui.sel_all_cb.isChecked():
-            while True:
-                cursor = self.ui.code_editor.textCursor()
-                cursor.beginEditBlock()
-                flags = QtGui.QTextDocument.FindCaseSensitively
-                # self.ui.editor is the QPlainTextEdit
-                r = self.ui.code_editor.find(str(old), flags)
-                if r:
-                    qc = self.ui.code_editor.textCursor()
-                    if qc.hasSelection():
-                        qc.insertText(new)
-                else:
-                    self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
-                    break
-            # Mark end of undo block
-            cursor.endEditBlock()
-        else:
-            cursor = self.ui.code_editor.textCursor()
-            cursor.beginEditBlock()
-            qc = self.ui.code_editor.textCursor()
-            if qc.hasSelection():
-                qc.insertText(new)
-            # Mark end of undo block
-            cursor.endEditBlock()
-
-    def handleCopyAll(self):
-        text = self.ui.code_editor.toPlainText()
-        self.clipboard.setText(text)
-        self.inform.emit(_("Code Editor content copied to clipboard ..."))
-
-    def handleRunCode(self):
-        # trying to run a Tcl command without having the Shell open will create some warnings because the Tcl Shell
-        # tries to print on a hidden widget, therefore show the dock if hidden
-        if self.ui.shell_dock.isHidden():
-            self.ui.shell_dock.show()
-
-        self.script_code = deepcopy(self.ui.code_editor.toPlainText())
-        # self.shell._sysShell.exec_command(script_code)
-
-        old_line = ''
-        for tcl_command_line in self.script_code.splitlines():
-            # do not process lines starting with '#' = comment and empty lines
-            if not tcl_command_line.startswith('#') and tcl_command_line != '':
-                # id FlatCAM is run in Windows then replace all the slashes with
-                # the UNIX style slash that TCL understands
-                if sys.platform == 'win32':
-                    if "open" in tcl_command_line:
-                        tcl_command_line = tcl_command_line.replace('\\', '/')
-
-                if old_line != '':
-                    new_command = old_line + tcl_command_line + '\n'
-                else:
-                    new_command = tcl_command_line
-
-                # execute the actual Tcl command
-                try:
-                    self.shell.open_proccessing()  # Disables input box.
-
-                    result = self.tcl.eval(str(new_command))
-                    if result != 'None':
-                        self.shell.append_output(result + '\n')
-
-                    old_line = ''
-                except tk.TclError:
-                    old_line = old_line + tcl_command_line + '\n'
-                except Exception as e:
-                    log.debug("App.handleRunCode() --> %s" % str(e))
-
-        if old_line != '':
-            # it means that the script finished with an error
-            result = self.tcl.eval("set errorInfo")
-            self.log.error("Exec command Exception: %s" % (result + '\n'))
-            self.shell.append_error('ERROR: ' + result + '\n')
-
-        self.shell.close_proccessing()
-
     def on_tool_add_keypress(self):
         # ## Current application units in Upper Case
         self.units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
@@ -9138,38 +8953,29 @@ class App(QtCore.QObject):
     # ###############################################################################################################
 
     def init_code_editor(self, name):
-        # Signals section
-        # Disconnect the old signals
-        try:
-            self.ui.buttonOpen.clicked.disconnect()
-        except TypeError:
-            pass
 
-        try:
-            self.ui.buttonSave.clicked.disconnect()
-        except TypeError:
-            pass
+        self.ui.text_editor_tab = TextEditor(app=self)
 
         # add the tab if it was closed
-        self.ui.plot_tab_area.addTab(self.ui.cncjob_tab, '%s' % name)
-        self.ui.cncjob_tab.setObjectName('cncjob_tab')
+        self.ui.plot_tab_area.addTab(self.ui.text_editor_tab, '%s' % name)
+        self.ui.text_editor_tab.setObjectName('text_editor_tab')
 
         # delete the absolute and relative position and messages in the infobar
         self.ui.position_label.setText("")
         self.ui.rel_position_label.setText("")
 
         # first clear previous text in text editor (if any)
-        self.ui.code_editor.clear()
-        self.ui.code_editor.setReadOnly(False)
+        self.ui.text_editor_tab.code_editor.clear()
+        self.ui.text_editor_tab.code_editor.setReadOnly(False)
         self.toggle_codeeditor = True
-        self.ui.code_editor.completer_enable = False
-        self.ui.buttonRun.hide()
+        self.ui.text_editor_tab.code_editor.completer_enable = False
+        self.ui.text_editor_tab.buttonRun.hide()
 
         # make sure to keep a reference to the code editor
-        self.reference_code_editor = self.ui.code_editor
+        self.reference_code_editor = self.ui.text_editor_tab.code_editor
 
         # Switch plot_area to CNCJob tab
-        self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab)
+        self.ui.plot_tab_area.setCurrentWidget(self.ui.text_editor_tab)
 
     def on_view_source(self):
         self.inform.emit('%s' %
@@ -9193,9 +8999,30 @@ class App(QtCore.QObject):
         else:
             flt = "All Files (*.*)"
 
-        self.init_code_editor(name=_("Source Editor"))
-        self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen(filt=flt))
-        self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode(filt=flt))
+        self.source_editor_tab = TextEditor(app=self)
+
+        # add the tab if it was closed
+        self.ui.plot_tab_area.addTab(self.source_editor_tab, '%s' % _("Source Editor"))
+        self.source_editor_tab.setObjectName('source_editor_tab')
+
+        # delete the absolute and relative position and messages in the infobar
+        self.ui.position_label.setText("")
+        self.ui.rel_position_label.setText("")
+
+        # first clear previous text in text editor (if any)
+        self.source_editor_tab.code_editor.clear()
+        self.source_editor_tab.code_editor.setReadOnly(False)
+
+        self.source_editor_tab.code_editor.completer_enable = False
+        self.source_editor_tab.buttonRun.hide()
+
+        # Switch plot_area to CNCJob tab
+        self.ui.plot_tab_area.setCurrentWidget(self.source_editor_tab)
+
+        self.source_editor_tab.buttonOpen.clicked.disconnect()
+        self.source_editor_tab.buttonOpen.clicked.connect(lambda: self.source_editor_tab.handleOpen(filt=flt))
+        self.source_editor_tab.buttonSave.clicked.disconnect()
+        self.source_editor_tab.buttonSave.clicked.connect(lambda: self.source_editor_tab.handleSaveGCode(filt=flt))
 
         # then append the text from GCode to the text editor
         if obj.kind == 'cncjob':
@@ -9218,22 +9045,22 @@ class App(QtCore.QObject):
                                  _("There is no selected object for which to see it's source file code."))
                 return 'fail'
 
-        self.ui.cncjob_frame.hide()
+        self.source_editor_tab.t_frame.hide()
         try:
             for line in file:
                 QtWidgets.QApplication.processEvents()
                 proc_line = str(line).strip('\n')
-                self.ui.code_editor.append(proc_line)
+                self.source_editor_tab.code_editor.append(proc_line)
         except Exception as e:
             log.debug('App.on_view_source() -->%s' % str(e))
             self.inform.emit('[ERROR] %s: %s' %
                              (_('Failed to load the source code for the selected object'), str(e)))
             return
 
-        self.handleTextChanged()
-        self.ui.cncjob_frame.show()
+        self.source_editor_tab.handleTextChanged()
+        self.source_editor_tab.t_frame.show()
 
-        self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
+        self.source_editor_tab.code_editor.moveCursor(QtGui.QTextCursor.Start)
         self.proc_container.view.set_idle()
         # self.ui.show()
 
@@ -9242,16 +9069,18 @@ class App(QtCore.QObject):
 
         if self.toggle_codeeditor is False:
             self.init_code_editor(name=_("Code Editor"))
-            self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen())
-            self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode())
+            self.ui.text_editor_tab.buttonOpen.clicked.disconnect()
+            self.ui.text_editor_tab.buttonOpen.clicked.connect(lambda: self.ui.text_editor_tab.handleOpen())
+            self.ui.text_editor_tab.buttonSave.clicked.disconnect()
+            self.ui.text_editor_tab.buttonSave.clicked.connect(lambda: self.ui.text_editor_tab.handleSaveGCode())
         else:
             for idx in range(self.ui.plot_tab_area.count()):
-                if self.ui.plot_tab_area.widget(idx).objectName() == "cncjob_tab":
+                if self.ui.plot_tab_area.widget(idx).objectName() == "text_editor_tab":
                     self.ui.plot_tab_area.closeTab(idx)
                     break
             self.toggle_codeeditor = False
 
-    def on_filenewscript(self, silent=False):
+    def on_filenewscript(self, silent=False, name=None, text=None):
         """
         Will create a new script file and open it in the Code Editor
         :param silent: if True will not display status messages
@@ -9262,36 +9091,64 @@ class App(QtCore.QObject):
                              _("New TCL script file created in Code Editor."))
 
         flt = "FlatCAM Scripts (*.FlatScript);;All Files (*.*)"
-        self.init_code_editor(name=_("Script Editor"))
-        self.ui.code_editor.completer_enable = True
-        self.ui.code_editor.append(_(
-            "#\n"
-            "# CREATE A NEW FLATCAM TCL SCRIPT\n"
-            "# TCL Tutorial here: https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html\n"
-            "#\n\n"
-            "# FlatCAM commands list:\n"
-            "# AddCircle, AddPolygon, AddPolyline, AddRectangle, AlignDrill, AlignDrillGrid, ClearShell, ClearCopper,\n"
-            "# Cncjob, Cutout, Delete, Drillcncjob, ExportGcode, ExportSVG, Exteriors, GeoCutout, GeoUnion, GetNames,\n"
-            "# GetSys, ImportSvg, Interiors, Isolate, Follow, JoinExcellon, JoinGeometry, ListSys, MillDrills,\n"
-            "# MillSlots, Mirror, New, NewGeometry, Offset, OpenExcellon, OpenGCode, OpenGerber, OpenProject,\n"
-            "# Options, Paint, Panelize, Plot, SaveProject, SaveSys, Scale, SetActive, SetSys, Skew, SubtractPoly,\n"
-            "# SubtractRectangle, Version, WriteGCode\n"
-            "#\n\n"
-        ))
 
-        self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen(filt=flt))
-        self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode(filt=flt))
-        self.ui.buttonRun.show()
+        self.proc_container.view.set_busy(_("Loading..."))
+
+        self.script_editor_tab = TextEditor(app=self)
+
+        # add the tab if it was closed
+        self.ui.plot_tab_area.addTab(self.script_editor_tab, '%s' % _("Script Editor"))
+        self.script_editor_tab.setObjectName('script_editor_tab')
+
+        # delete the absolute and relative position and messages in the infobar
+        self.ui.position_label.setText("")
+        self.ui.rel_position_label.setText("")
+
+        # first clear previous text in text editor (if any)
+        self.script_editor_tab.code_editor.clear()
+        self.script_editor_tab.code_editor.setReadOnly(False)
+
+        self.script_editor_tab.code_editor.completer_enable = True
+        self.script_editor_tab.buttonRun.show()
+
+        # Switch plot_area to CNCJob tab
+        self.ui.plot_tab_area.setCurrentWidget(self.script_editor_tab)
+
+        self.script_editor_tab.buttonOpen.clicked.disconnect()
+        self.script_editor_tab.buttonOpen.clicked.connect(lambda: self.script_editor_tab.handleOpen(filt=flt))
+        self.script_editor_tab.buttonSave.clicked.disconnect()
+        self.script_editor_tab.buttonSave.clicked.connect(lambda: self.script_editor_tab.handleSaveGCode(filt=flt))
+
         try:
-            self.ui.buttonRun.clicked.disconnect(self.handleRunCode)
+            self.script_editor_tab.buttonRun.clicked.disconnect()
         except TypeError:
             pass
-        self.ui.buttonRun.clicked.connect(self.handleRunCode)
+        self.script_editor_tab.buttonRun.clicked.connect(self.script_editor_tab.handleRunCode)
 
-        self.handleTextChanged()
-        self.ui.code_editor.show()
+        self.script_editor_tab.handleTextChanged()
+
+        if name is not None:
+            self.new_script_object(name=name)
+            script_obj = self.collection.get_by_name(name)
+        else:
+            self.new_script_object()
+            script_obj = self.collection.get_by_name('new_script')
 
-        self.new_script_object()
+        script_text = script_obj.source_file
+
+        self.script_editor_tab.t_frame.hide()
+        if text is not None:
+            try:
+                for line in text:
+                    self.script_editor_tab.code_editor.append(line)
+            except TypeError:
+                self.script_editor_tab.code_editor.append(text)
+
+        else:
+            self.script_editor_tab.code_editor.append(script_text)
+        self.script_editor_tab.t_frame.show()
+
+        self.proc_container.view.set_idle()
 
     def on_fileopenscript(self, name=None, silent=False):
         """
@@ -9301,6 +9158,8 @@ class App(QtCore.QObject):
         :param name: name of a Tcl script file to open
         :return:
         """
+        script_content = []
+
         if name:
             filename = name
         else:
@@ -9318,17 +9177,17 @@ class App(QtCore.QObject):
 
         if filename == "":
             if silent is False:
-                self.inform.emit('[WARNING_NOTCL] %s' %
-                                 _("Open TCL script cancelled."))
+                self.inform.emit('[WARNING_NOTCL] %s' % _("Open TCL script cancelled."))
         else:
-            self.on_filenewscript()
+            self.proc_container.view.set_busy(_("Loading..."))
 
             try:
                 with open(filename, "r") as opened_script:
                     try:
                         for line in opened_script:
+                            QtWidgets.QApplication.processEvents()
                             proc_line = str(line).strip('\n')
-                            self.ui.code_editor.append(proc_line)
+                            script_content.append(proc_line)
                     except Exception as e:
                         log.debug('App.on_fileopenscript() -->%s' % str(e))
                         if silent is False:
@@ -9336,17 +9195,17 @@ class App(QtCore.QObject):
                                              ('App.on_fileopenscript() -->', str(e)))
                         return
 
-                    self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
-
-                    self.handleTextChanged()
                     if silent is False:
-                        self.inform.emit('[success] %s' %
-                                         _("TCL script file opened in Code Editor."))
-                    # self.ui.show()
+                        self.inform.emit('[success] %s' % _("TCL script file opened in Code Editor."))
 
             except Exception as e:
                 log.debug("App.on_fileopenscript() -> %s" % str(e))
 
+            self.proc_container.view.set_idle()
+
+            script_name = filename.split('/')[-1].split('\\')[-1]
+            self.on_filenewscript(name=script_name, text=script_content)
+
     def on_filerunscript(self, name=None, silent=False):
         """
         File menu callback for loading and running a TCL script.
@@ -10558,12 +10417,12 @@ class App(QtCore.QObject):
                                     alignment=Qt.AlignBottom | Qt.AlignLeft,
                                     color=QtGui.QColor("gray"))
         # add the tab if it was closed
-        self.ui.plot_tab_area.addTab(self.ui.cncjob_tab, _("Code Editor"))
+        self.ui.plot_tab_area.addTab(self.ui.text_editor_tab, _("Code Editor"))
         # first clear previous text in text editor (if any)
-        self.ui.code_editor.clear()
+        self.ui.text_editor_tab.code_editor.clear()
 
         # Switch plot_area to CNCJob tab
-        self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab)
+        self.ui.plot_tab_area.setCurrentWidget(self.ui.text_editor_tab)
 
         try:
             if filename:
@@ -10571,7 +10430,7 @@ class App(QtCore.QObject):
                 if f.open(QtCore.QIODevice.ReadOnly):
                     stream = QtCore.QTextStream(f)
                     gcode_edited = stream.readAll()
-                    self.ui.code_editor.setPlainText(gcode_edited)
+                    self.ui.text_editor_tab.code_editor.setPlainText(gcode_edited)
                     f.close()
         except IOError:
             App.log.error("Failed to open config file: %s" % filename)

+ 31 - 7
FlatCAMObj.py

@@ -10,6 +10,8 @@ import copy
 import inspect  # TODO: For debugging only.
 from datetime import datetime
 
+from flatcamEditors.FlatCAMTextEditor import TextEditor
+
 from flatcamGUI.ObjectUI import *
 from FlatCAMCommon import LoudDict
 from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
@@ -5992,6 +5994,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
                              (_("Machine Code file saved to"), filename))
 
     def on_edit_code_click(self, *args):
+        self.app.proc_container.view.set_busy(_("Loading..."))
 
         preamble = str(self.ui.prepend_text.get_value())
         postamble = str(self.ui.append_text.get_value())
@@ -6002,25 +6005,46 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
         else:
             self.app.gcode_edited = gco
 
-        self.app.init_code_editor(name=_("Code Editor"))
-        self.app.ui.buttonOpen.clicked.connect(self.app.handleOpen)
-        self.app.ui.buttonSave.clicked.connect(self.app.handleSaveGCode)
+        self.gcode_editor_tab = TextEditor(app=self.app)
+
+        # 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("")
+
+        # first clear previous text in text editor (if any)
+        self.gcode_editor_tab.code_editor.clear()
+        self.gcode_editor_tab.code_editor.setReadOnly(False)
 
+        self.gcode_editor_tab.code_editor.completer_enable = False
+        self.gcode_editor_tab.buttonRun.hide()
+
+        # Switch plot_area to CNCJob tab
+        self.app.ui.plot_tab_area.setCurrentWidget(self.gcode_editor_tab)
+
+        self.gcode_editor_tab.t_frame.hide()
         # then append the text from GCode to the text editor
         try:
             for line in self.app.gcode_edited:
+                QtWidgets.QApplication.processEvents()
+
                 proc_line = str(line).strip('\n')
-                self.app.ui.code_editor.append(proc_line)
+                self.gcode_editor_tab.code_editor.append(proc_line)
         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.app.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
+        self.gcode_editor_tab.code_editor.moveCursor(QtGui.QTextCursor.Start)
+
+        self.gcode_editor_tab.handleTextChanged()
+        self.gcode_editor_tab.t_frame.show()
+        self.app.proc_container.view.set_idle()
 
-        self.app.handleTextChanged()
-        self.app.ui.show()
         self.app.inform.emit('[success] %s...' %
                              _('Loaded Machine Code into Code Editor'))
 

+ 6 - 0
README.md

@@ -10,6 +10,12 @@ CAD program, and create G-Code for Isolation routing.
 
 =================================================
 
+2.10.2019
+
+- fixed bug in Geometry Editor that did not allow the copy of geometric elements
+- created a new class that holds all the Code Editor functionality and integrated as a Editor in FlatCAM, the location is in flatcamEditors folder
+- remade all the functions for view_source, scripts and view_code to use the new TextEditor class; now all the Code Editor tabs are being kept alive, before only one could be in an open state
+
 1.10.2019
 
 - fixed the FCSpinner and FCDoubleSpinner GUI elements to select all on first click and deselect on second click in the Spinbox LineEdit

+ 14 - 2
flatcamEditors/FlatCAMGeoEditor.py

@@ -4081,7 +4081,12 @@ class FlatCAMGeoEditor(QtCore.QObject):
     def on_shape_complete(self):
         self.app.log.debug("on_shape_complete()")
 
-        geom = self.active_tool.geometry.geo
+        geom = []
+        try:
+            for shape in self.active_tool.geometry:
+                geom.append(shape.geo)
+        except TypeError:
+            geom = self.active_tool.geometry.geo
 
         if self.app.defaults['geometry_editor_milling_type'] == 'cl':
             # reverse the geometry coordinates direction to allow creation of Gcode for  climb milling
@@ -4110,8 +4115,15 @@ class FlatCAMGeoEditor(QtCore.QObject):
                 log.debug("FlatCAMGeoEditor.on_shape_complete() Error --> %s" % str(e))
                 return 'fail'
 
+        shape_list = list()
+        try:
+            for geo in geom:
+                shape_list.append(DrawToolShape(geo))
+        except TypeError:
+            shape_list.append(DrawToolShape(geom))
+
         # Add shape
-        self.add_shape(DrawToolShape(geom))
+        self.add_shape(shape_list)
 
         # Remove any utility shapes
         self.delete_utility_geometry()

+ 347 - 0
flatcamEditors/FlatCAMTextEditor.py

@@ -0,0 +1,347 @@
+from flatcamGUI.GUIElements import *
+from PyQt5 import QtPrintSupport
+
+import tkinter as tk
+from copy import deepcopy
+
+import sys
+
+import gettext
+import FlatCAMTranslation as fcTranslate
+import builtins
+
+fcTranslate.apply_language('strings')
+if '_' not in builtins.__dict__:
+    _ = gettext.gettext
+
+
+class TextEditor(QtWidgets.QWidget):
+
+    def __init__(self, app, text=None):
+        super().__init__()
+
+        self.app = app
+        self.setSizePolicy(
+            QtWidgets.QSizePolicy.MinimumExpanding,
+            QtWidgets.QSizePolicy.MinimumExpanding
+        )
+
+        self.main_editor_layout = QtWidgets.QVBoxLayout(self)
+        self.main_editor_layout.setContentsMargins(0, 0, 0, 0)
+
+        self.t_frame = QtWidgets.QFrame()
+        self.t_frame.setContentsMargins(0, 0, 0, 0)
+        self.main_editor_layout.addWidget(self.t_frame)
+
+        self.work_editor_layout = QtWidgets.QGridLayout(self.t_frame)
+        self.work_editor_layout.setContentsMargins(2, 2, 2, 2)
+        self.t_frame.setLayout(self.work_editor_layout)
+
+        self.code_editor = FCTextAreaExtended()
+        stylesheet = """
+                                QTextEdit { selection-background-color:yellow;
+                                            selection-color:black;
+                                }
+                             """
+
+        self.code_editor.setStyleSheet(stylesheet)
+
+        if text:
+            self.code_editor.setPlainText(text)
+
+        self.buttonPreview = QtWidgets.QPushButton(_('Print Preview'))
+        self.buttonPreview.setToolTip(_("Open a OS standard Preview Print window."))
+        self.buttonPreview.setMinimumWidth(100)
+
+        self.buttonPrint = QtWidgets.QPushButton(_('Print Code'))
+        self.buttonPrint.setToolTip(_("Open a OS standard Print window."))
+
+        self.buttonFind = QtWidgets.QPushButton(_('Find in Code'))
+        self.buttonFind.setToolTip(_("Will search and highlight in yellow the string in the Find box."))
+        self.buttonFind.setMinimumWidth(100)
+
+        self.entryFind = FCEntry()
+        self.entryFind.setToolTip(_("Find box. Enter here the strings to be searched in the text."))
+
+        self.buttonReplace = QtWidgets.QPushButton(_('Replace With'))
+        self.buttonReplace.setToolTip(_("Will replace the string from the Find box with the one in the Replace box."))
+        self.buttonReplace.setMinimumWidth(100)
+
+        self.entryReplace = FCEntry()
+        self.entryReplace.setToolTip(_("String to replace the one in the Find box throughout the text."))
+
+        self.sel_all_cb = QtWidgets.QCheckBox(_('All'))
+        self.sel_all_cb.setToolTip(_("When checked it will replace all instances in the 'Find' box\n"
+                                     "with the text in the 'Replace' box.."))
+
+        self.button_copy_all = QtWidgets.QPushButton(_('Copy All'))
+        self.button_copy_all.setToolTip(_("Will copy all the text in the Code Editor to the clipboard."))
+        self.button_copy_all.setMinimumWidth(100)
+
+        self.buttonOpen = QtWidgets.QPushButton(_('Open Code'))
+        self.buttonOpen.setToolTip(_("Will open a text file in the editor."))
+
+        self.buttonSave = QtWidgets.QPushButton(_('Save Code'))
+        self.buttonSave.setToolTip(_("Will save the text in the editor into a file."))
+
+        self.buttonRun = QtWidgets.QPushButton(_('Run Code'))
+        self.buttonRun.setToolTip(_("Will run the TCL commands found in the text file, one by one."))
+
+        self.buttonRun.hide()
+        self.work_editor_layout.addWidget(self.code_editor, 0, 0, 1, 5)
+
+        editor_hlay_1 = QtWidgets.QHBoxLayout()
+        # cnc_tab_lay_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+        editor_hlay_1.addWidget(self.buttonFind)
+        editor_hlay_1.addWidget(self.entryFind)
+        editor_hlay_1.addWidget(self.buttonReplace)
+        editor_hlay_1.addWidget(self.entryReplace)
+        editor_hlay_1.addWidget(self.sel_all_cb)
+        editor_hlay_1.addWidget(self.button_copy_all)
+        self.work_editor_layout.addLayout(editor_hlay_1, 1, 0, 1, 5)
+
+        editor_hlay_2 = QtWidgets.QHBoxLayout()
+        editor_hlay_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+        editor_hlay_2.addWidget(self.buttonPreview)
+        editor_hlay_2.addWidget(self.buttonPrint)
+        self.work_editor_layout.addLayout(editor_hlay_2, 2, 0, 1, 1, QtCore.Qt.AlignLeft)
+
+        cnc_tab_lay_4 = QtWidgets.QHBoxLayout()
+        cnc_tab_lay_4.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
+        cnc_tab_lay_4.addWidget(self.buttonOpen)
+        cnc_tab_lay_4.addWidget(self.buttonSave)
+        cnc_tab_lay_4.addWidget(self.buttonRun)
+        self.work_editor_layout.addLayout(cnc_tab_lay_4, 2, 4, 1, 1)
+
+        # #################################################################################
+        # ################### SIGNALS #####################################################
+        # #################################################################################
+
+        self.code_editor.textChanged.connect(self.handleTextChanged)
+        self.buttonOpen.clicked.connect(self.handleOpen)
+        self.buttonSave.clicked.connect(self.handleSaveGCode)
+        self.buttonPrint.clicked.connect(self.handlePrint)
+        self.buttonPreview.clicked.connect(self.handlePreview)
+        self.buttonFind.clicked.connect(self.handleFindGCode)
+        self.buttonReplace.clicked.connect(self.handleReplaceGCode)
+        self.button_copy_all.clicked.connect(self.handleCopyAll)
+
+        self.code_editor.set_model_data(self.app.myKeywords)
+
+        self.gcode_edited = ''
+        self.script_code = ''
+
+    def handlePrint(self):
+        self.app.report_usage("handlePrint()")
+
+        dialog = QtPrintSupport.QPrintDialog()
+        if dialog.exec_() == QtWidgets.QDialog.Accepted:
+            self.code_editor.document().print_(dialog.printer())
+
+    def handlePreview(self):
+        self.app.report_usage("handlePreview()")
+
+        dialog = QtPrintSupport.QPrintPreviewDialog()
+        dialog.paintRequested.connect(self.code_editor.print_)
+        dialog.exec_()
+
+    def handleTextChanged(self):
+        # enable = not self.ui.code_editor.document().isEmpty()
+        # self.ui.buttonPrint.setEnabled(enable)
+        # self.ui.buttonPreview.setEnabled(enable)
+        pass
+
+    def handleOpen(self, filt=None):
+        self.app.report_usage("handleOpen()")
+
+        if filt:
+            _filter_ = filt
+        else:
+            _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_)
+
+        if path:
+            file = QtCore.QFile(path)
+            if file.open(QtCore.QIODevice.ReadOnly):
+                stream = QtCore.QTextStream(file)
+                self.gcode_edited = stream.readAll()
+                self.code_editor.setPlainText(self.gcode_edited)
+                file.close()
+
+    def handleSaveGCode(self, name=None, filt=None):
+        self.app.report_usage("handleSaveGCode()")
+
+        if filt:
+            _filter_ = filt
+        else:
+            _filter_ = "G-Code Files (*.nc);; G-Code Files (*.txt);; G-Code Files (*.tap);; G-Code Files (*.cnc);; " \
+                       "All Files (*.*)"
+
+        if name:
+            obj_name = name
+        else:
+            try:
+                obj_name = self.app.collection.get_active().options['name']
+            except AttributeError:
+                obj_name = 'file'
+                if filt is None:
+                    _filter_ = "FlatConfig Files (*.FlatConfig);;All Files (*.*)"
+
+        try:
+            filename = str(QtWidgets.QFileDialog.getSaveFileName(
+                caption=_("Export G-Code ..."),
+                directory=self.app.defaults["global_last_folder"] + '/' + str(obj_name),
+                filter=_filter_
+            )[0])
+        except TypeError:
+            filename = str(QtWidgets.QFileDialog.getSaveFileName(caption=_("Export G-Code ..."), filter=_filter_)[0])
+
+        if filename == "":
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export Code cancelled."))
+            return
+        else:
+            try:
+                my_gcode = self.code_editor.toPlainText()
+                with open(filename, 'w') as f:
+                    for line in my_gcode:
+                        f.write(line)
+            except FileNotFoundError:
+                self.app.inform.emit('[WARNING] %s' % _("No such file or directory"))
+                return
+            except PermissionError:
+                self.app.inform.emit('[WARNING] %s' %
+                                     _("Permission denied, saving not possible.\n"
+                                       "Most likely another app is holding the file open and not accessible."))
+                return
+
+        # Just for adding it to the recent files list.
+        if self.app.defaults["global_open_style"] is False:
+            self.app.file_opened.emit("cncjob", filename)
+        self.app.file_saved.emit("cncjob", filename)
+        self.app.inform.emit('%s: %s' % (_("Saved to"), str(filename)))
+
+    def handleFindGCode(self):
+        self.app.report_usage("handleFindGCode()")
+
+        flags = QtGui.QTextDocument.FindCaseSensitively
+        text_to_be_found = self.entryFind.get_value()
+
+        r = self.code_editor.find(str(text_to_be_found), flags)
+        if r is False:
+            self.code_editor.moveCursor(QtGui.QTextCursor.Start)
+
+    def handleReplaceGCode(self):
+        self.app.report_usage("handleReplaceGCode()")
+
+        old = self.entryFind.get_value()
+        new = self.entryReplace.get_value()
+
+        if self.sel_all_cb.isChecked():
+            while True:
+                cursor = self.code_editor.textCursor()
+                cursor.beginEditBlock()
+                flags = QtGui.QTextDocument.FindCaseSensitively
+                # self.ui.editor is the QPlainTextEdit
+                r = self.code_editor.find(str(old), flags)
+                if r:
+                    qc = self.code_editor.textCursor()
+                    if qc.hasSelection():
+                        qc.insertText(new)
+                else:
+                    self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
+                    break
+            # Mark end of undo block
+            cursor.endEditBlock()
+        else:
+            cursor = self.code_editor.textCursor()
+            cursor.beginEditBlock()
+            qc = self.code_editor.textCursor()
+            if qc.hasSelection():
+                qc.insertText(new)
+            # Mark end of undo block
+            cursor.endEditBlock()
+
+    def handleCopyAll(self):
+        text = self.code_editor.toPlainText()
+        self.app.clipboard.setText(text)
+        self.app.inform.emit(_("Code Editor content copied to clipboard ..."))
+
+    def handleRunCode(self):
+        # trying to run a Tcl command without having the Shell open will create some warnings because the Tcl Shell
+        # tries to print on a hidden widget, therefore show the dock if hidden
+        if self.app.ui.shell_dock.isHidden():
+            self.app.ui.shell_dock.show()
+
+        self.script_code = deepcopy(self.code_editor.toPlainText())
+
+        old_line = ''
+        for tcl_command_line in self.app.script_code.splitlines():
+            # do not process lines starting with '#' = comment and empty lines
+            if not tcl_command_line.startswith('#') and tcl_command_line != '':
+                # id FlatCAM is run in Windows then replace all the slashes with
+                # the UNIX style slash that TCL understands
+                if sys.platform == 'win32':
+                    if "open" in tcl_command_line:
+                        tcl_command_line = tcl_command_line.replace('\\', '/')
+
+                if old_line != '':
+                    new_command = old_line + tcl_command_line + '\n'
+                else:
+                    new_command = tcl_command_line
+
+                # execute the actual Tcl command
+                try:
+                    self.app.shell.open_proccessing()  # Disables input box.
+
+                    result = self.app.tcl.eval(str(new_command))
+                    if result != 'None':
+                        self.app.shell.append_output(result + '\n')
+
+                    old_line = ''
+                except tk.TclError:
+                    old_line = old_line + tcl_command_line + '\n'
+                except Exception as e:
+                    log.debug("App.handleRunCode() --> %s" % str(e))
+
+        if old_line != '':
+            # it means that the script finished with an error
+            result = self.app.tcl.eval("set errorInfo")
+            log.error("Exec command Exception: %s" % (result + '\n'))
+            self.app.shell.append_error('ERROR: ' + result + '\n')
+
+        self.app.shell.close_proccessing()
+
+    def closeEvent(self, QCloseEvent):
+        try:
+            self.code_editor.textChanged.disconnect()
+        except TypeError:
+            pass
+        try:
+            self.buttonOpen.clicked.disconnect()
+        except TypeError:
+            pass
+        try:
+            self.buttonPrint.clicked.disconnect()
+        except TypeError:
+            pass
+        try:
+            self.buttonPreview.clicked.disconnect()
+        except TypeError:
+            pass
+        try:
+            self.buttonFind.clicked.disconnect()
+        except TypeError:
+            pass
+        try:
+            self.buttonReplace.clicked.disconnect()
+        except TypeError:
+            pass
+        try:
+            self.button_copy_all.clicked.disconnect()
+        except TypeError:
+            pass
+
+        super().closeEvent(QCloseEvent)

+ 92 - 92
flatcamGUI/FlatCAMGUI.py

@@ -934,12 +934,12 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.geometry_scroll_area = QtWidgets.QScrollArea()
         self.geometry_tab_lay.addWidget(self.geometry_scroll_area)
 
-        self.cncjob_tab = QtWidgets.QWidget()
-        self.cncjob_tab.setObjectName("cncjob_tab")
-        self.pref_tab_area.addTab(self.cncjob_tab, _("CNC-JOB"))
+        self.text_editor_tab = QtWidgets.QWidget()
+        self.text_editor_tab.setObjectName("text_editor_tab")
+        self.pref_tab_area.addTab(self.text_editor_tab, _("CNC-JOB"))
         self.cncjob_tab_lay = QtWidgets.QVBoxLayout()
         self.cncjob_tab_lay.setContentsMargins(2, 2, 2, 2)
-        self.cncjob_tab.setLayout(self.cncjob_tab_lay)
+        self.text_editor_tab.setLayout(self.cncjob_tab_lay)
 
         self.cncjob_scroll_area = QtWidgets.QScrollArea()
         self.cncjob_tab_lay.addWidget(self.cncjob_scroll_area)
@@ -1843,94 +1843,94 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         # self.cncjob_tab_layout.setContentsMargins(2, 2, 2, 2)
         # self.cncjob_tab.setLayout(self.cncjob_tab_layout)
 
-        self.cncjob_tab = QtWidgets.QWidget()
-
-        self.c_temp_layout = QtWidgets.QVBoxLayout(self.cncjob_tab)
-        self.c_temp_layout.setContentsMargins(0, 0, 0, 0)
-
-        self.cncjob_frame = QtWidgets.QFrame()
-        self.cncjob_frame.setContentsMargins(0, 0, 0, 0)
-        self.c_temp_layout.addWidget(self.cncjob_frame)
-
-        self.cncjob_tab_layout = QtWidgets.QGridLayout(self.cncjob_frame)
-        self.cncjob_tab_layout.setContentsMargins(2, 2, 2, 2)
-        self.cncjob_frame.setLayout(self.cncjob_tab_layout)
-
-        self.code_editor = FCTextAreaExtended()
-        stylesheet = """
-                        QTextEdit { selection-background-color:yellow;
-                                    selection-color:black;
-                        }
-                     """
-
-        self.code_editor.setStyleSheet(stylesheet)
-
-        self.buttonPreview = QtWidgets.QPushButton(_('Print Preview'))
-        self.buttonPreview.setToolTip(_("Open a OS standard Preview Print window."))
-        self.buttonPrint = QtWidgets.QPushButton(_('Print Code'))
-        self.buttonPrint.setToolTip(_("Open a OS standard Print window."))
-
-        self.buttonFind = QtWidgets.QPushButton(_('Find in Code'))
-        self.buttonFind.setToolTip(_("Will search and highlight in yellow the string in the Find box."))
-        self.buttonFind.setMinimumWidth(100)
-
-        self.buttonPreview.setMinimumWidth(100)
-
-        self.entryFind = FCEntry()
-        self.entryFind.setToolTip(_("Find box. Enter here the strings to be searched in the text."))
-
-        self.buttonReplace = QtWidgets.QPushButton(_('Replace With'))
-        self.buttonReplace.setToolTip(_("Will replace the string from the Find box with the one in the Replace box."))
-
-        self.buttonReplace.setMinimumWidth(100)
-
-        self.entryReplace = FCEntry()
-        self.entryReplace.setToolTip(_("String to replace the one in the Find box throughout the text."))
-
-        self.sel_all_cb = QtWidgets.QCheckBox(_('All'))
-        self.sel_all_cb.setToolTip(_("When checked it will replace all instances in the 'Find' box\n"
-                                     "with the text in the 'Replace' box.."))
-
-        self.button_copy_all = QtWidgets.QPushButton(_('Copy All'))
-        self.button_copy_all.setToolTip(_("Will copy all the text in the Code Editor to the clipboard."))
-
-        self.button_copy_all.setMinimumWidth(100)
-
-        self.buttonOpen = QtWidgets.QPushButton(_('Open Code'))
-        self.buttonOpen.setToolTip(_("Will open a text file in the editor."))
-
-        self.buttonSave = QtWidgets.QPushButton(_('Save Code'))
-        self.buttonSave.setToolTip(_("Will save the text in the editor into a file."))
-
-        self.buttonRun = QtWidgets.QPushButton(_('Run Code'))
-        self.buttonRun.setToolTip(_("Will run the TCL commands found in the text file, one by one."))
-
-        self.buttonRun.hide()
-        self.cncjob_tab_layout.addWidget(self.code_editor, 0, 0, 1, 5)
-
-        cnc_tab_lay_1 = QtWidgets.QHBoxLayout()
-        # cnc_tab_lay_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
-        cnc_tab_lay_1.addWidget(self.buttonFind)
-        cnc_tab_lay_1.addWidget(self.entryFind)
-        cnc_tab_lay_1.addWidget(self.buttonReplace)
-        cnc_tab_lay_1.addWidget(self.entryReplace)
-        cnc_tab_lay_1.addWidget(self.sel_all_cb)
-        cnc_tab_lay_1.addWidget(self.button_copy_all)
-        self.cncjob_tab_layout.addLayout(cnc_tab_lay_1, 1, 0, 1, 5)
-
-        cnc_tab_lay_3 = QtWidgets.QHBoxLayout()
-        cnc_tab_lay_3.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
-        cnc_tab_lay_3.addWidget(self.buttonPreview)
-        cnc_tab_lay_3.addWidget(self.buttonPrint)
-        self.cncjob_tab_layout.addLayout(cnc_tab_lay_3, 2, 0, 1, 1, QtCore.Qt.AlignLeft)
-
-        cnc_tab_lay_4 = QtWidgets.QHBoxLayout()
-        cnc_tab_lay_4.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
-        cnc_tab_lay_4.addWidget(self.buttonOpen)
-        cnc_tab_lay_4.addWidget(self.buttonSave)
-        cnc_tab_lay_4.addWidget(self.buttonRun)
-
-        self.cncjob_tab_layout.addLayout(cnc_tab_lay_4, 2, 4, 1, 1)
+        # self.cncjob_tab = QtWidgets.QWidget()
+        #
+        # self.c_temp_layout = QtWidgets.QVBoxLayout(self.cncjob_tab)
+        # self.c_temp_layout.setContentsMargins(0, 0, 0, 0)
+        #
+        # self.cncjob_frame = QtWidgets.QFrame()
+        # self.cncjob_frame.setContentsMargins(0, 0, 0, 0)
+        # self.c_temp_layout.addWidget(self.cncjob_frame)
+        #
+        # self.cncjob_tab_layout = QtWidgets.QGridLayout(self.cncjob_frame)
+        # self.cncjob_tab_layout.setContentsMargins(2, 2, 2, 2)
+        # self.cncjob_frame.setLayout(self.cncjob_tab_layout)
+        #
+        # self.code_editor = FCTextAreaExtended()
+        # stylesheet = """
+        #                 QTextEdit { selection-background-color:yellow;
+        #                             selection-color:black;
+        #                 }
+        #              """
+        #
+        # self.code_editor.setStyleSheet(stylesheet)
+        #
+        # self.buttonPreview = QtWidgets.QPushButton(_('Print Preview'))
+        # self.buttonPreview.setToolTip(_("Open a OS standard Preview Print window."))
+        # self.buttonPrint = QtWidgets.QPushButton(_('Print Code'))
+        # self.buttonPrint.setToolTip(_("Open a OS standard Print window."))
+        #
+        # self.buttonFind = QtWidgets.QPushButton(_('Find in Code'))
+        # self.buttonFind.setToolTip(_("Will search and highlight in yellow the string in the Find box."))
+        # self.buttonFind.setMinimumWidth(100)
+        #
+        # self.buttonPreview.setMinimumWidth(100)
+        #
+        # self.entryFind = FCEntry()
+        # self.entryFind.setToolTip(_("Find box. Enter here the strings to be searched in the text."))
+        #
+        # self.buttonReplace = QtWidgets.QPushButton(_('Replace With'))
+        # self.buttonReplace.setToolTip(_("Will replace the string from the Find box with the one in the Replace box."))
+        #
+        # self.buttonReplace.setMinimumWidth(100)
+        #
+        # self.entryReplace = FCEntry()
+        # self.entryReplace.setToolTip(_("String to replace the one in the Find box throughout the text."))
+        #
+        # self.sel_all_cb = QtWidgets.QCheckBox(_('All'))
+        # self.sel_all_cb.setToolTip(_("When checked it will replace all instances in the 'Find' box\n"
+        #                              "with the text in the 'Replace' box.."))
+        #
+        # self.button_copy_all = QtWidgets.QPushButton(_('Copy All'))
+        # self.button_copy_all.setToolTip(_("Will copy all the text in the Code Editor to the clipboard."))
+        #
+        # self.button_copy_all.setMinimumWidth(100)
+        #
+        # self.buttonOpen = QtWidgets.QPushButton(_('Open Code'))
+        # self.buttonOpen.setToolTip(_("Will open a text file in the editor."))
+        #
+        # self.buttonSave = QtWidgets.QPushButton(_('Save Code'))
+        # self.buttonSave.setToolTip(_("Will save the text in the editor into a file."))
+        #
+        # self.buttonRun = QtWidgets.QPushButton(_('Run Code'))
+        # self.buttonRun.setToolTip(_("Will run the TCL commands found in the text file, one by one."))
+        #
+        # self.buttonRun.hide()
+        # self.cncjob_tab_layout.addWidget(self.code_editor, 0, 0, 1, 5)
+        #
+        # cnc_tab_lay_1 = QtWidgets.QHBoxLayout()
+        # # cnc_tab_lay_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+        # cnc_tab_lay_1.addWidget(self.buttonFind)
+        # cnc_tab_lay_1.addWidget(self.entryFind)
+        # cnc_tab_lay_1.addWidget(self.buttonReplace)
+        # cnc_tab_lay_1.addWidget(self.entryReplace)
+        # cnc_tab_lay_1.addWidget(self.sel_all_cb)
+        # cnc_tab_lay_1.addWidget(self.button_copy_all)
+        # self.cncjob_tab_layout.addLayout(cnc_tab_lay_1, 1, 0, 1, 5)
+        #
+        # cnc_tab_lay_3 = QtWidgets.QHBoxLayout()
+        # cnc_tab_lay_3.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+        # cnc_tab_lay_3.addWidget(self.buttonPreview)
+        # cnc_tab_lay_3.addWidget(self.buttonPrint)
+        # self.cncjob_tab_layout.addLayout(cnc_tab_lay_3, 2, 0, 1, 1, QtCore.Qt.AlignLeft)
+        #
+        # cnc_tab_lay_4 = QtWidgets.QHBoxLayout()
+        # cnc_tab_lay_4.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
+        # cnc_tab_lay_4.addWidget(self.buttonOpen)
+        # cnc_tab_lay_4.addWidget(self.buttonSave)
+        # cnc_tab_lay_4.addWidget(self.buttonRun)
+        #
+        # self.cncjob_tab_layout.addLayout(cnc_tab_lay_4, 2, 4, 1, 1)
 
         # #################################
         # ## Build InfoBar is done here ###

+ 2 - 2
flatcamTools/ToolSolderPaste.py

@@ -1306,13 +1306,13 @@ class SolderPaste(FlatCAMTool):
         time_str = "{:%A, %d %B %Y at %H:%M}".format(datetime.now())
 
         # add the tab if it was closed
-        self.app.ui.plot_tab_area.addTab(self.app.ui.cncjob_tab, _("Code Editor"))
+        self.app.ui.plot_tab_area.addTab(self.app.ui.text_editor_tab, _("Code Editor"))
 
         # first clear previous text in text editor (if any)
         self.app.ui.code_editor.clear()
 
         # Switch plot_area to CNCJob tab
-        self.app.ui.plot_tab_area.setCurrentWidget(self.app.ui.cncjob_tab)
+        self.app.ui.plot_tab_area.setCurrentWidget(self.app.ui.text_editor_tab)
 
         name = self.cnc_obj_combo.currentText()
         obj = self.app.collection.get_by_name(name)