- solve parenting issues when trying to load a FlatScript from Menu -> File -> Scripting

- added a first new example script and added some files to work with
- added a new parameter that will store the home folder of the FlatCAM installation so we can access the example folder
This commit is contained in:
Marius Stanciu 2020-05-01 17:10:42 +03:00 committed by Marius
parent f47396a6e5
commit 37c6bb2c61
21 changed files with 275 additions and 87 deletions

View File

@ -10,6 +10,9 @@ CHANGELOG for FlatCAM beta
01.05.2020
- added some ToolTips (strings needed to be translated too) for the Cut Z entry in Geometry Object UI that explain why is sometime disabled and reason for it's value (sometime is zero)
- solve parenting issues when trying to load a FlatScript from Menu -> File -> Scripting
- added a first new example script and added some files to work with
- added a new parameter that will store the home folder of the FlatCAM installation so we can access the example folder
30.04.2020

View File

@ -432,6 +432,9 @@ class App(QtCore.QObject):
# ################################# DEFAULTS - PREFERENCES STORAGE ###########################################
# ############################################################################################################
self.defaults = FlatCAMDefaults()
self.defaults["root_folder_path"] = self.app_home
current_defaults_path = os.path.join(self.data_path, "current_defaults.FlatConfig")
if user_defaults:
self.defaults.load(filename=current_defaults_path)
@ -2908,45 +2911,37 @@ class App(QtCore.QObject):
self.new_object('gerber', 'new_grb', initialize, plot=False)
def new_script_object(self, name=None, text=None):
def new_script_object(self):
"""
Creates a new, blank TCL Script object.
:param name: a name for the new object
:param text: pass a source file to the newly created script to be loaded in it
:return: None
"""
self.defaults.report_usage("new_script_object()")
if text is not None:
new_source_file = text
else:
# commands_list = "# AddCircle, AddPolygon, AddPolyline, AddRectangle, AlignDrill, " \
# "AlignDrillGrid, Bbox, Bounds, ClearShell, CopperClear,\n" \
# "# Cncjob, Cutout, Delete, Drillcncjob, ExportDXF, ExportExcellon, ExportGcode,\n" \
# "# ExportGerber, ExportSVG, Exteriors, Follow, GeoCutout, GeoUnion, GetNames,\n" \
# "# GetSys, ImportSvg, Interiors, Isolate, JoinExcellon, JoinGeometry, " \
# "ListSys, MillDrills,\n" \
# "# MillSlots, Mirror, New, NewExcellon, NewGeometry, NewGerber, Nregions, " \
# "Offset, OpenExcellon, OpenGCode, OpenGerber, OpenProject,\n" \
# "# Options, Paint, Panelize, PlotAl, PlotObjects, SaveProject, " \
# "SaveSys, Scale, SetActive, SetSys, SetOrigin, Skew, SubtractPoly,\n" \
# "# SubtractRectangle, Version, WriteGCode\n"
# commands_list = "# AddCircle, AddPolygon, AddPolyline, AddRectangle, AlignDrill, " \
# "AlignDrillGrid, Bbox, Bounds, ClearShell, CopperClear,\n" \
# "# Cncjob, Cutout, Delete, Drillcncjob, ExportDXF, ExportExcellon, ExportGcode,\n" \
# "# ExportGerber, ExportSVG, Exteriors, Follow, GeoCutout, GeoUnion, GetNames,\n" \
# "# GetSys, ImportSvg, Interiors, Isolate, JoinExcellon, JoinGeometry, " \
# "ListSys, MillDrills,\n" \
# "# MillSlots, Mirror, New, NewExcellon, NewGeometry, NewGerber, Nregions, " \
# "Offset, OpenExcellon, OpenGCode, OpenGerber, OpenProject,\n" \
# "# Options, Paint, Panelize, PlotAl, PlotObjects, SaveProject, " \
# "SaveSys, Scale, SetActive, SetSys, SetOrigin, Skew, SubtractPoly,\n" \
# "# SubtractRectangle, Version, WriteGCode\n"
new_source_file = '# %s\n' % _('CREATE A NEW FLATCAM TCL SCRIPT') + \
'# %s:\n' % _('TCL Tutorial is here') + \
'# https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html\n' + '\n\n' + \
'# %s:\n' % _("FlatCAM commands list")
new_source_file += '# %s\n\n' % _("Type >help< followed by Run Code for a list of FlatCAM Tcl Commands "
"(displayed in Tcl Shell).")
new_source_file = '# %s\n' % _('CREATE A NEW FLATCAM TCL SCRIPT') + \
'# %s:\n' % _('TCL Tutorial is here') + \
'# https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html\n' + '\n\n' + \
'# %s:\n' % _("FlatCAM commands list")
new_source_file += '# %s\n\n' % _("Type >help< followed by Run Code for a list of FlatCAM Tcl Commands "
"(displayed in Tcl Shell).")
def initialize(obj, app):
obj.source_file = deepcopy(new_source_file)
if name is None:
outname = 'new_script'
else:
outname = name
outname = 'new_script'
self.new_object('script', outname, initialize, plot=False)
def new_document_object(self):
@ -8339,14 +8334,14 @@ class App(QtCore.QObject):
# set cursor of the code editor with the cursor at the searcehd line
self.ui.plot_tab_area.currentWidget().code_editor.setTextCursor(cursor)
def on_filenewscript(self, silent=False, name=None, text=None):
def on_filenewscript(self, silent=False):
"""
Will create a new script file and open it in the Code Editor
:param silent: if True will not display status messages
:param name: if specified will be the name of the new script
:param text: pass a source file to the newly created script to be loaded in it
:return: None
:param silent: if True will not display status messages
:param name: if specified will be the name of the new script
:param text: pass a source file to the newly created script to be loaded in it
:return: None
"""
if silent is False:
self.inform.emit('[success] %s' % _("New TCL script file created in Code Editor."))
@ -8355,10 +8350,7 @@ class App(QtCore.QObject):
self.ui.position_label.setText("")
self.ui.rel_position_label.setText("")
if name is not None:
self.new_script_object(name=name, text=text)
else:
self.new_script_object(text=text)
self.new_script_object()
# script_text = script_obj.source_file
#
@ -8372,9 +8364,9 @@ class App(QtCore.QObject):
"""
Will open a Tcl script file into the Code Editor
:param silent: if True will not display status messages
:param name: name of a Tcl script file to open
:return:
:param silent: if True will not display status messages
:param name: name of a Tcl script file to open
:return: None
"""
self.defaults.report_usage("on_fileopenscript")
@ -9609,27 +9601,46 @@ class App(QtCore.QObject):
:param silent: If True there will be no messages printed to StatusBar
:return: None
"""
def obj_init(script_obj, app_obj):
assert isinstance(script_obj, ScriptObject), \
"Expected to initialize a ScriptObject but got %s" % type(script_obj)
if silent is False:
app_obj.inform.emit('[success] %s' % _("TCL script file opened in Code Editor."))
try:
script_obj.parse_file(filename)
except IOError:
app_obj.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Failed to open file"), filename))
return "fail"
except ParseError as err:
app_obj.inform.emit('[ERROR_NOTCL] %s: %s. %s' % (_("Failed to parse file"), filename, str(err)))
app_obj.log.error(str(err))
return "fail"
except Exception as e:
log.debug("App.open_script() -> %s" % str(e))
msg = '[ERROR] %s' % _("An internal error has occurred. See shell.\n")
msg += traceback.format_exc()
app_obj.inform.emit(msg)
return "fail"
App.log.debug("open_script()")
with self.proc_container.new(_("Opening TCL Script...")):
try:
with open(filename, "r") as opened_script:
script_content = opened_script.readlines()
script_content = ''.join(script_content)
if silent is False:
self.inform.emit('[success] %s' % _("TCL script file opened in Code Editor."))
except Exception as e:
log.debug("App.open_script() -> %s" % str(e))
self.inform.emit('[ERROR_NOTCL] %s' % _("Failed to open TCL Script."))
return
# Object name
script_name = outname or filename.split('/')[-1].split('\\')[-1]
# New object creation and file processing
self.on_filenewscript(name=script_name, text=script_content)
# Object creation
ret_val = self.new_object("script", script_name, obj_init, autoselected=False, plot=False)
if ret_val == 'fail':
filename = self.defaults['global_tcl_path'] + '/' + script_name
ret_val = self.new_object("script", script_name, obj_init, autoselected=False, plot=False)
if ret_val == 'fail':
self.inform.emit('[ERROR_NOTCL]%s' % _('Failed to open TCL Script.'))
return 'fail'
# Register recent file
self.file_opened.emit("script", filename)

View File

@ -0,0 +1,69 @@
G04*
G04 GERBER (RE)GENERATED BY FLATCAM v8.992 - www.flatcam.org - Version Date: 2020/05/01*
G04 Filename: test.gbr*
G04 Created on : Friday, 01 May 2020 at 17:03*
%INBottom.gbr*%
%MOMM*%
%ADD13C,0.8*%
%ADD14C,1.27*%
%ADD15C,1.27*%
%ADD16R,1.5X1.5*%
%ADD17C,1.5*%
%FSLAX53Y53*%
G04*
G71*
G90*
G75*
G01*
%LNBottom*%
%LPD*%
X20779Y24462D2*
D13*
Y27002D1*
X18229D1*
X14429D1*
X18229D2*
X19509D1*
Y28272D1*
X32209Y14302D2*
X28399D1*
Y16842D1*
Y14302D2*
X18239D1*
X20779Y16842D2*
X23329D1*
Y28272D1*
X27129D1*
X20779Y19382D2*
X14429D1*
X20779Y21922D2*
X18239D1*
X28399D2*
X32209D1*
D14*
X27129Y28272D3*
D15*
X19509D3*
D14*
X14429Y19382D3*
D15*
Y27002D3*
D14*
X18239Y21922D3*
D15*
Y14302D3*
D14*
X32209Y21922D3*
D15*
Y14302D3*
D16*
X28399Y24462D3*
D17*
Y21922D3*
Y19382D3*
Y16842D3*
X20779D3*
Y19382D3*
Y21922D3*
Y24462D3*
M02*

View File

@ -0,0 +1,28 @@
M48
;EXCELLON GENERATED BY FLATCAM v8.992 - www.flatcam.org - Version Date: 2020/05/01
;Filename: test.txt
;Created on : Friday, 01 May 2020 at 17:04
INCH,LZ
;FILE_FORMAT=2:4
T1F00S00C0.0220
T2F00S00C0.0354
%
T01
X010681Y011130
X007681Y011130
X005681Y010630
X007181Y008630
X005681Y007630
X007181Y005630
X012681Y005630
X012681Y008630
T02
X011181Y009630
X011181Y008630
X011181Y007630
X011181Y006630
X008181Y006630
X008181Y007630
X008181Y008630
X008181Y009630
M30

View File

@ -0,0 +1,30 @@
G04*
G04 GERBER (RE)GENERATED BY FLATCAM v8.992 - www.flatcam.org - Version Date: 2020/05/01*
G04 Filename: test_1*
G04 Created on : Friday, 01 May 2020 at 17:07*
G04*
G04 RS-274X GERBER GENERATED BY FLATCAM v8.992 - www.flatcam.org - Version Date: 2020/05/01*
G04 Filename: test_1_edit*
G04 Created on : Friday, 01 May 2020 at 17:06*
%FSLAX24Y24*%
%MOIN*%
%ADD10C,0.003937*%
G70*
G90*
G01*
%LPD*%
D10*
X05118Y11417D02*
X05118Y05118D01*
X05118Y05118D02*
X08661Y05118D01*
X08661Y05118D02*
X08661Y11417D01*
X08661Y11417D02*
X05118Y11417D01*
X08661Y11417D02*
X05118Y11417D01*
X08661Y11417D02*
X05118Y11417D01*
M02*

View File

@ -0,0 +1,19 @@
# ----------- START: This is needed only for the examples ----------------
# first set the default location where to search for the files to be open and store it to the ROOT_FOLDER variable
set ROOT_FOLDER [get_sys root_folder_path]
# calculate the resources path for the examples we need to run and store it inside the PATH varaible
set PATH ${ROOT_FOLDER}/assets/examples/files
# ----------- END: This is needed only for the examples ----------------
# set the working path to the path that holds the files we are going to work with
set_path $PATH
# load the GERBER file
open_gerber test.gbr
# load the Excellon ifle
open_excellon test.txt
# plot them all so we can see them on canvas
plot_all

View File

@ -28,6 +28,7 @@ class FlatCAMDefaults:
"version": 8.992, # defaults format version, not necessarily equal to app version
"first_run": True,
"units": "MM",
"root_folder_path": '',
"global_serial": 0,
"global_stats": dict(),
"global_tabs_detachable": True,

View File

@ -25,8 +25,8 @@ if '_' not in builtins.__dict__:
class TextEditor(QtWidgets.QWidget):
def __init__(self, app, text=None, plain_text=None):
super().__init__()
def __init__(self, app, text=None, plain_text=None, parent=None):
super().__init__(parent=parent)
self.app = app
self.plain_text = plain_text

View File

@ -50,15 +50,14 @@ class ScriptObject(FlatCAMObj):
self.units = ''
self.script_editor_tab = None
self.ser_attrs = ['options', 'kind', 'source_file']
self.source_file = ''
self.script_code = ''
self.units_found = self.app.defaults['units']
# self.script_editor_tab = TextEditor(app=self.app, plain_text=True)
self.script_editor_tab = TextEditor(app=self.app, plain_text=True)
def set_ui(self, ui):
"""
Sets the Object UI in Selected Tab for the FlatCAM Script type of object.
@ -87,6 +86,8 @@ class ScriptObject(FlatCAMObj):
'<span style="color:red;"><b>Advanced</b></span>'
))
self.script_editor_tab = TextEditor(app=self.app, plain_text=True, parent=self.app.ui)
# tab_here = False
# # try to not add too many times a tab that it is already installed
# for idx in range(self.app.ui.plot_tab_area.count()):
@ -99,8 +100,8 @@ class ScriptObject(FlatCAMObj):
# self.app.ui.plot_tab_area.addTab(self.script_editor_tab, '%s' % _("Script Editor"))
# self.script_editor_tab.setObjectName(self.options['name'])
self.app.ui.plot_tab_area.addTab(self.script_editor_tab, '%s' % _("Script Editor"))
self.script_editor_tab.setObjectName(self.options['name'])
# self.app.ui.plot_tab_area.addTab(self.script_editor_tab, '%s' % _("Script Editor"))
# self.script_editor_tab.setObjectName(self.options['name'])
# first clear previous text in text editor (if any)
# self.script_editor_tab.code_editor.clear()
@ -111,7 +112,7 @@ class ScriptObject(FlatCAMObj):
self.script_editor_tab.buttonRun.show()
# Switch plot_area to CNCJob tab
# Switch plot_area to Script Editor tab
self.app.ui.plot_tab_area.setCurrentWidget(self.script_editor_tab)
flt = "FlatCAM Scripts (*.FlatScript);;All Files (*.*)"
@ -150,6 +151,32 @@ class ScriptObject(FlatCAMObj):
def build_ui(self):
FlatCAMObj.build_ui(self)
tab_here = False
# try to not add too many times a tab that it is already installed
for idx in range(self.app.ui.plot_tab_area.count()):
if self.app.ui.plot_tab_area.widget(idx).objectName() == self.options['name']:
tab_here = True
break
# add the tab if it is not already added
if tab_here is False:
self.app.ui.plot_tab_area.addTab(self.script_editor_tab, '%s' % _("Script Editor"))
self.script_editor_tab.setObjectName(self.options['name'])
self.app.ui.plot_tab_area.setCurrentWidget(self.script_editor_tab)
def parse_file(self, filename):
"""
Will set an attribute of the object, self.source_file, with the parsed data.
:param filename: Tcl Script file to parse
:return: None
"""
with open(filename, "r") as opened_script:
script_content = opened_script.readlines()
script_content = ''.join(script_content)
self.source_file = script_content
def handle_run_code(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

View File

@ -128,7 +128,7 @@ class Film(FlatCAMTool):
self.tf_box_combo_label = QtWidgets.QLabel('%s:' % _("Box Object"))
self.tf_box_combo_label.setToolTip(
_("The actual object that is used a container for the\n "
_("The actual object that is used as container for the\n "
"selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created.")

View File

@ -136,7 +136,7 @@ class Panelize(FlatCAMTool):
self.box_combo.is_last = True
self.box_combo.setToolTip(
_("The actual object that is used a container for the\n "
_("The actual object that is used as container for the\n "
"selected object that is to be panelized.")
)
form_layout.addRow(self.box_combo)

View File

@ -15431,7 +15431,7 @@ msgstr "Box-Objekt"
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
@ -16542,7 +16542,7 @@ msgstr ""
#: flatcamTools/ToolPanelize.py:139
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
msgstr ""
"Das eigentliche Objekt, für das ein Container verwendet wird\n"

View File

@ -15118,12 +15118,12 @@ msgstr "Box Object"
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
msgstr ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
@ -16208,10 +16208,10 @@ msgstr ""
#: flatcamTools/ToolPanelize.py:139
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
msgstr ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
#: flatcamTools/ToolPanelize.py:145

View File

@ -15345,7 +15345,7 @@ msgstr "Objeto de caja"
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
@ -16468,7 +16468,7 @@ msgstr ""
#: flatcamTools/ToolPanelize.py:139
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
msgstr ""
"El objeto real que se utiliza como contenedor para\n"

View File

@ -15357,7 +15357,7 @@ msgstr "Objet Box"
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
@ -16465,7 +16465,7 @@ msgstr ""
#: flatcamTools/ToolPanelize.py:139
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
msgstr ""
"L'objet réel qui utilise un conteneur pour la\n"

View File

@ -15132,12 +15132,12 @@ msgstr "Box Object"
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
msgstr ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
@ -16210,10 +16210,10 @@ msgstr ""
#: flatcamTools/ToolPanelize.py:139
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
msgstr ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
#: flatcamTools/ToolPanelize.py:145

View File

@ -12628,7 +12628,7 @@ msgstr ""
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
@ -13573,7 +13573,7 @@ msgstr ""
#: flatcamTools/ToolPanelize.py:138
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
msgstr ""

View File

@ -15180,7 +15180,7 @@ msgstr "Objeto Caixa"
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
@ -16274,7 +16274,7 @@ msgstr ""
#: flatcamTools/ToolPanelize.py:139
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
msgstr ""
"O objeto usado como contêiner para o objeto\n"

View File

@ -15368,7 +15368,7 @@ msgstr "Container"
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
@ -16473,7 +16473,7 @@ msgstr ""
#: flatcamTools/ToolPanelize.py:139
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
msgstr ""
"Obiectul care este folosit ca și container \n"

View File

@ -15227,7 +15227,7 @@ msgstr "Объект рамки"
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."
@ -16329,7 +16329,7 @@ msgstr ""
#: flatcamTools/ToolPanelize.py:139
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object that is to be panelized."
msgstr ""
"Фактический объект, который используется контейнер для\n"

View File

@ -13014,7 +13014,7 @@ msgstr ""
#: flatcamTools/ToolFilm.py:131
msgid ""
"The actual object that is used a container for the\n"
"The actual object that is used as container for the\n"
" selected object for which we create the film.\n"
"Usually it is the PCB outline but it can be also the\n"
"same object for which the film is created."