- working on a proper GCode Editor
This commit is contained in:
parent
65d4f70b21
commit
9e8ab610b4
|
@ -7,6 +7,10 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
=================================================
|
||||
|
||||
22.07.2020
|
||||
|
||||
- working on a proper GCode Editor
|
||||
|
||||
21.07.2020
|
||||
|
||||
- updated the FCRadio class with a method that allow disabling certain options
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# MIT Licence #
|
||||
# ##########################################################
|
||||
|
||||
from appGUI.GUIElements import FCFileSaveDialog, FCEntry, FCTextAreaExtended, FCTextAreaLineNumber
|
||||
from appGUI.GUIElements import FCFileSaveDialog, FCEntry, FCTextAreaExtended, FCTextAreaLineNumber, FCButton
|
||||
from PyQt5 import QtPrintSupport, QtWidgets, QtCore, QtGui
|
||||
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph
|
||||
|
@ -30,6 +30,7 @@ class AppTextEditor(QtWidgets.QWidget):
|
|||
|
||||
self.app = app
|
||||
self.plain_text = plain_text
|
||||
self.callback = lambda x: None
|
||||
|
||||
self.setSizePolicy(
|
||||
QtWidgets.QSizePolicy.MinimumExpanding,
|
||||
|
@ -71,17 +72,17 @@ class AppTextEditor(QtWidgets.QWidget):
|
|||
if text:
|
||||
self.code_editor.setPlainText(text)
|
||||
|
||||
self.buttonPreview = QtWidgets.QPushButton(_('Print Preview'))
|
||||
self.buttonPreview = FCButton(_('Print Preview'))
|
||||
self.buttonPreview.setIcon(QtGui.QIcon(self.app.resource_location + '/preview32.png'))
|
||||
self.buttonPreview.setToolTip(_("Open a OS standard Preview Print window."))
|
||||
self.buttonPreview.setMinimumWidth(100)
|
||||
|
||||
self.buttonPrint = QtWidgets.QPushButton(_('Print Code'))
|
||||
self.buttonPrint = FCButton(_('Print Code'))
|
||||
self.buttonPrint.setIcon(QtGui.QIcon(self.app.resource_location + '/printer32.png'))
|
||||
self.buttonPrint.setToolTip(_("Open a OS standard Print window."))
|
||||
self.buttonPrint.setMinimumWidth(100)
|
||||
|
||||
self.buttonFind = QtWidgets.QPushButton(_('Find in Code'))
|
||||
self.buttonFind = FCButton(_('Find in Code'))
|
||||
self.buttonFind.setIcon(QtGui.QIcon(self.app.resource_location + '/find32.png'))
|
||||
self.buttonFind.setToolTip(_("Will search and highlight in yellow the string in the Find box."))
|
||||
self.buttonFind.setMinimumWidth(100)
|
||||
|
@ -89,7 +90,7 @@ class AppTextEditor(QtWidgets.QWidget):
|
|||
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 = FCButton(_('Replace With'))
|
||||
self.buttonReplace.setIcon(QtGui.QIcon(self.app.resource_location + '/replace32.png'))
|
||||
self.buttonReplace.setToolTip(_("Will replace the string from the Find box with the one in the Replace box."))
|
||||
self.buttonReplace.setMinimumWidth(100)
|
||||
|
@ -101,22 +102,22 @@ class AppTextEditor(QtWidgets.QWidget):
|
|||
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 = FCButton(_('Copy All'))
|
||||
self.button_copy_all.setIcon(QtGui.QIcon(self.app.resource_location + '/copy_file32.png'))
|
||||
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 = FCButton(_('Open Code'))
|
||||
self.buttonOpen.setIcon(QtGui.QIcon(self.app.resource_location + '/folder32_bis.png'))
|
||||
self.buttonOpen.setToolTip(_("Will open a text file in the editor."))
|
||||
self.buttonOpen.setMinimumWidth(100)
|
||||
|
||||
self.buttonSave = QtWidgets.QPushButton(_('Save Code'))
|
||||
self.buttonSave = FCButton(_('Save Code'))
|
||||
self.buttonSave.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
|
||||
self.buttonSave.setToolTip(_("Will save the text in the editor into a file."))
|
||||
self.buttonSave.setMinimumWidth(100)
|
||||
|
||||
self.buttonRun = QtWidgets.QPushButton(_('Run Code'))
|
||||
self.buttonRun = FCButton(_('Run Code'))
|
||||
self.buttonRun.setToolTip(_("Will run the TCL commands found in the text file, one by one."))
|
||||
self.buttonRun.setMinimumWidth(100)
|
||||
|
||||
|
@ -162,6 +163,9 @@ class AppTextEditor(QtWidgets.QWidget):
|
|||
|
||||
self.code_edited = ''
|
||||
|
||||
def set_callback(self, callback):
|
||||
self.callback = callback
|
||||
|
||||
def handlePrint(self):
|
||||
self.app.defaults.report_usage("handlePrint()")
|
||||
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
# ##########################################################
|
||||
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||
# File Author: Marius Adrian Stanciu (c) #
|
||||
# Date: 07/22/2020 #
|
||||
# MIT Licence #
|
||||
# ##########################################################
|
||||
|
||||
from appEditors.AppTextEditor import AppTextEditor
|
||||
from appObjects import FlatCAMCNCJob
|
||||
from appGUI.GUIElements import FCFileSaveDialog, FCEntry, FCTextAreaExtended, FCTextAreaLineNumber, FCButton
|
||||
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||
|
||||
# from io import StringIO
|
||||
|
||||
import logging
|
||||
|
||||
import gettext
|
||||
import appTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
_ = gettext.gettext
|
||||
|
||||
log = logging.getLogger('base')
|
||||
|
||||
|
||||
class appGCodeEditor(QtCore.QObject):
|
||||
|
||||
def __init__(self, app, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
self.app = app
|
||||
self.plain_text = ''
|
||||
self.callback = lambda x: None
|
||||
|
||||
self.ui = appGCodeEditorUI(app=self.app)
|
||||
|
||||
# #################################################################################
|
||||
# ################### SIGNALS #####################################################
|
||||
# #################################################################################
|
||||
|
||||
self.gcode_obj = None
|
||||
self.code_edited = ''
|
||||
|
||||
def set_ui(self):
|
||||
pass
|
||||
|
||||
def build_ui(self):
|
||||
pass
|
||||
|
||||
def ui_connect(self):
|
||||
pass
|
||||
|
||||
def ui_disconnect(self):
|
||||
pass
|
||||
|
||||
def handleTextChanged(self):
|
||||
# enable = not self.ui.code_editor.document().isEmpty()
|
||||
# self.ui.buttonPrint.setEnabled(enable)
|
||||
# self.ui.buttonPreview.setEnabled(enable)
|
||||
|
||||
self.buttonSave.setStyleSheet("QPushButton {color: red;}")
|
||||
self.buttonSave.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as_red.png'))
|
||||
|
||||
def edit_fcgcode(self, cnc_obj):
|
||||
assert isinstance(cnc_obj, FlatCAMCNCJob)
|
||||
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.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):
|
||||
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()")
|
||||
|
||||
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.code_edited = stream.readAll()
|
||||
self.ui.gcode_editor_tab.load_text(self, self.code_edited, move_to_start=True, clear_text=True)
|
||||
file.close()
|
||||
|
||||
|
||||
class appGCodeEditorUI:
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
|
||||
# Number of decimals used by tools in this class
|
||||
self.decimals = self.app.decimals
|
||||
|
||||
# ## Current application units in Upper Case
|
||||
self.units = self.app.defaults['units'].upper()
|
||||
|
||||
# self.setSizePolicy(
|
||||
# QtWidgets.QSizePolicy.MinimumExpanding,
|
||||
# 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.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:
|
||||
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()
|
||||
|
||||
self.layout.addStretch()
|
||||
|
||||
# Editor
|
||||
self.exit_editor_button = QtWidgets.QPushButton(_('Exit Editor'))
|
||||
self.exit_editor_button.setIcon(QtGui.QIcon(self.app.resource_location + '/power16.png'))
|
||||
self.exit_editor_button.setToolTip(
|
||||
_("Exit from Editor.")
|
||||
)
|
||||
self.exit_editor_button.setStyleSheet("""
|
||||
QPushButton
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
""")
|
||||
self.layout.addWidget(self.exit_editor_button)
|
||||
# ############################ FINSIHED GUI ###################################
|
||||
# #############################################################################
|
||||
|
||||
def confirmation_message(self, accepted, minval, maxval):
|
||||
if accepted is False:
|
||||
self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%.*f, %.*f]' % (_("Edited value is out of range"),
|
||||
self.decimals,
|
||||
minval,
|
||||
self.decimals,
|
||||
maxval), False)
|
||||
else:
|
||||
self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)
|
||||
|
||||
def confirmation_message_int(self, accepted, minval, maxval):
|
||||
if accepted is False:
|
||||
self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%d, %d]' %
|
||||
(_("Edited value is out of range"), minval, maxval), False)
|
||||
else:
|
||||
self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)
|
|
@ -1557,8 +1557,13 @@ class FCInputDialog(QtWidgets.QInputDialog):
|
|||
|
||||
|
||||
class FCButton(QtWidgets.QPushButton):
|
||||
def __init__(self, parent=None):
|
||||
super(FCButton, self).__init__(parent)
|
||||
def __init__(self, text=None, checkable=None, click_callback=None, parent=None):
|
||||
super(FCButton, self).__init__(text, parent)
|
||||
if not checkable is None:
|
||||
self.setCheckable(checkable)
|
||||
|
||||
if not click_callback is None:
|
||||
self.clicked.connect(click_callback)
|
||||
|
||||
def get_value(self):
|
||||
return self.isChecked()
|
||||
|
|
|
@ -1870,7 +1870,7 @@ class CNCObjectUI(ObjectUI):
|
|||
self.custom_box.addWidget(self.updateplot_button)
|
||||
|
||||
# Editor
|
||||
self.editor_button = QtWidgets.QPushButton(_('GCode Editor'))
|
||||
self.editor_button = FCButton(_('GCode Editor'))
|
||||
self.editor_button.setIcon(QtGui.QIcon(self.app.resource_location + '/edit_file32.png'))
|
||||
|
||||
self.editor_button.setToolTip(
|
||||
|
|
|
@ -149,6 +149,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
|
||||
self.gcode_editor_tab = None
|
||||
|
||||
self.source_file = ''
|
||||
self.units_found = self.app.defaults['units']
|
||||
|
||||
def build_ui(self):
|
||||
|
@ -538,10 +539,14 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
self.ui.name_entry.set_value(new_name)
|
||||
self.on_name_activate(silent=True)
|
||||
|
||||
preamble = str(self.ui.prepend_text.get_value())
|
||||
postamble = str(self.ui.append_text.get_value())
|
||||
try:
|
||||
preamble = str(self.ui.prepend_text.get_value())
|
||||
postamble = str(self.ui.append_text.get_value())
|
||||
gc = self.export_gcode(filename, preamble=preamble, postamble=postamble)
|
||||
except Exception as err:
|
||||
log.debug("CNCJobObject.export_gcode_handler() --> %s" % str(err))
|
||||
gc = self.export_gcode(filename)
|
||||
|
||||
gc = self.export_gcode(filename, preamble=preamble, postamble=postamble)
|
||||
if gc == 'fail':
|
||||
return
|
||||
|
||||
|
@ -597,8 +602,13 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
self.gcode_editor_tab.t_frame.show()
|
||||
self.app.proc_container.view.set_idle()
|
||||
|
||||
self.gcode_editor_tab.buttonSave.clicked.connect(self.on_update_source_file)
|
||||
|
||||
self.app.inform.emit('[success] %s...' % _('Loaded Machine Code into Code Editor'))
|
||||
|
||||
def on_update_source_file(self):
|
||||
self.source_file = self.gcode_editor_tab.code_editor.toPlainText()
|
||||
|
||||
def gcode_header(self, comment_start_symbol=None, comment_stop_symbol=None):
|
||||
"""
|
||||
Will create a header to be added to all GCode files generated by FlatCAM
|
||||
|
@ -735,6 +745,11 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
|
||||
include_header = True
|
||||
|
||||
if preamble == '':
|
||||
preamble = self.app.defaults["cncjob_prepend"]
|
||||
if postamble == '':
|
||||
preamble = self.app.defaults["cncjob_append"]
|
||||
|
||||
try:
|
||||
if self.special_group:
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s %s %s.' %
|
||||
|
|
|
@ -7745,10 +7745,7 @@ class App(QtCore.QObject):
|
|||
# then append the text from GCode to the text editor
|
||||
if obj.kind == 'cncjob':
|
||||
try:
|
||||
file = obj.export_gcode(
|
||||
preamble=self.defaults["cncjob_prepend"],
|
||||
postamble=self.defaults["cncjob_append"],
|
||||
to_file=True)
|
||||
file = obj.export_gcode(to_file=True)
|
||||
if file == 'fail':
|
||||
return 'fail'
|
||||
except AttributeError:
|
||||
|
@ -8665,14 +8662,14 @@ class App(QtCore.QObject):
|
|||
def job_thread_grb(app_obj):
|
||||
ret = make_gerber()
|
||||
if ret == 'fail':
|
||||
self.inform.emit('[ERROR_NOTCL] %s' % _('Could not export Gerber file.'))
|
||||
self.inform.emit('[ERROR_NOTCL] %s' % _('Could not export file.'))
|
||||
return
|
||||
|
||||
self.worker_task.emit({'fcn': job_thread_grb, 'params': [self]})
|
||||
else:
|
||||
gret = make_gerber()
|
||||
if gret == 'fail':
|
||||
self.inform.emit('[ERROR_NOTCL] %s' % _('Could not export Gerber file.'))
|
||||
self.inform.emit('[ERROR_NOTCL] %s' % _('Could not export file.'))
|
||||
return 'fail'
|
||||
if local_use is not None:
|
||||
return gret
|
||||
|
|
Loading…
Reference in New Issue