- some minor changes in the Python version detection
- added a new Tcl Command named SetPath which will set a path to be used by the Tcl commands. Once set will serve as a fallback path in case that the files fail to be opened first time. It will be persistent, saved in preferences. - added the GUI for the new Open Example in the FIle -> Scripting menu. - I am modifying all the open ... handlers to add a parameter that will flag if the method was launched from Tcl Shell. This way if the method will fail to open the filename (which include the path) it will try to open from a set fallback path. - fixed issue #406, bug introduced recently (leftover changes). - modified the ImportSVG Tcl command name to OpenSVG (open_svg alias) - added a new Tcl command named OpenDXF (open_dxf alias) - fixed some errors in Scripting features - added a new Tcl command named GetPath as a convenient way to get the current default path stored in App.defaults['global_tcl_path']
This commit is contained in:
@@ -78,7 +78,6 @@ class TclCommandBounds(TclCommand):
|
||||
xmin, ymin, xmax, ymax = obj.bounds()
|
||||
result_list.append([xmin, ymin, xmax, ymax])
|
||||
|
||||
self.app.inform.emit('[success] %s ...' %
|
||||
_('TclCommand Bounds done.'))
|
||||
self.app.inform.emit('[success] %s ...' % _('TclCommand Bounds done.'))
|
||||
|
||||
return result_list
|
||||
|
||||
66
tclCommands/TclCommandGetPath.py
Normal file
66
tclCommands/TclCommandGetPath.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# ##########################################################
|
||||
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||
# File Author: Marius Adrian Stanciu (c) #
|
||||
# Date: 4/28/2020 #
|
||||
# MIT Licence #
|
||||
# ##########################################################
|
||||
|
||||
from tclCommands.TclCommand import TclCommand
|
||||
|
||||
import collections
|
||||
import os
|
||||
import logging
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
_ = gettext.gettext
|
||||
|
||||
log = logging.getLogger('base')
|
||||
|
||||
|
||||
class TclCommandGetPath(TclCommand):
|
||||
"""
|
||||
Tcl shell command to get the current default path set for Tcl.
|
||||
|
||||
example:
|
||||
|
||||
"""
|
||||
|
||||
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||
aliases = ['get_path']
|
||||
|
||||
description = '%s %s' % ("--", "Get the default Tcl Shell folder path.")
|
||||
|
||||
# Dictionary of types from Tcl command, needs to be ordered
|
||||
arg_names = collections.OrderedDict([
|
||||
])
|
||||
|
||||
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||
option_types = collections.OrderedDict([
|
||||
])
|
||||
|
||||
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||
required = []
|
||||
|
||||
# structured help for current command, args needs to be ordered
|
||||
help = {
|
||||
'main': "Will get the folder path used as a fallback path for opening files.",
|
||||
'args': collections.OrderedDict([
|
||||
]),
|
||||
'examples': ['get_path']
|
||||
}
|
||||
|
||||
def execute(self, args, unnamed_args):
|
||||
"""
|
||||
|
||||
:param args:
|
||||
:param unnamed_args:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.app.shell.append_output("Current default Tcl Shell path is: ")
|
||||
path = self.app.defaults["global_tcl_path"]
|
||||
return path
|
||||
94
tclCommands/TclCommandOpenDXF.py
Normal file
94
tclCommands/TclCommandOpenDXF.py
Normal file
@@ -0,0 +1,94 @@
|
||||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
|
||||
import collections
|
||||
|
||||
|
||||
class TclCommandOpenDXF(TclCommandSignaled):
|
||||
"""
|
||||
Tcl shell command to open an DXF file as a Geometry/Gerber Object.
|
||||
"""
|
||||
|
||||
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||
aliases = ['open_dxf']
|
||||
|
||||
description = '%s %s' % ("--", "Open a DXF file as a Geometry (or Gerber) Object.")
|
||||
|
||||
# dictionary of types from Tcl command, needs to be ordered
|
||||
arg_names = collections.OrderedDict([
|
||||
('filename', str)
|
||||
])
|
||||
|
||||
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||
option_types = collections.OrderedDict([
|
||||
('type', str),
|
||||
('outname', str)
|
||||
])
|
||||
|
||||
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||
required = ['filename']
|
||||
|
||||
# structured help for current command, args needs to be ordered
|
||||
help = {
|
||||
'main': "Open a DXF file as a Geometry (or Gerber) Object.",
|
||||
'args': collections.OrderedDict([
|
||||
('filename', 'Absolute path to file to open. Required.\n'
|
||||
'WARNING: no spaces are allowed. If unsure enclose the entire path with quotes.'),
|
||||
('type', 'Open as a Gerber or Geometry (default) object. Values can be: "geometry" or "gerber"'),
|
||||
('outname', 'Name of the resulting Geometry object.')
|
||||
]),
|
||||
'examples': ['open_dxf D:\\my_beautiful_svg_file.SVG']
|
||||
}
|
||||
|
||||
def execute(self, args, unnamed_args):
|
||||
"""
|
||||
execute current TCL shell command
|
||||
|
||||
:param args: array of known named arguments and options
|
||||
:param unnamed_args: array of other values which were passed into command
|
||||
without -somename and we do not have them in known arg_names
|
||||
:return: None or exception
|
||||
"""
|
||||
|
||||
# How the object should be initialized
|
||||
def obj_init(geo_obj, app_obj):
|
||||
|
||||
# if geo_obj.kind != 'geometry' and geo_obj.kind != 'gerber':
|
||||
# self.raise_tcl_error('Expected Geometry or Gerber, got %s %s.' % (outname, type(geo_obj)))
|
||||
|
||||
geo_obj.import_dxf(filename, obj_type, units=units)
|
||||
|
||||
filename = args['filename']
|
||||
|
||||
if 'outname' in args:
|
||||
outname = args['outname']
|
||||
else:
|
||||
outname = filename.split('/')[-1].split('\\')[-1]
|
||||
|
||||
if 'type' in args:
|
||||
obj_type = str(args['type']).lower()
|
||||
else:
|
||||
obj_type = 'geometry'
|
||||
|
||||
if obj_type != "geometry" and obj_type != "gerber":
|
||||
self.raise_tcl_error("Option type can be 'geometry' or 'gerber' only, got '%s'." % obj_type)
|
||||
|
||||
units = self.app.defaults['units'].upper()
|
||||
|
||||
with self.app.proc_container.new("Open DXF"):
|
||||
|
||||
# Object creation
|
||||
ret_val = self.app.new_object(obj_type, outname, obj_init, plot=False)
|
||||
if ret_val == 'fail':
|
||||
filename = self.app.defaults['global_tcl_path'] + '/' + outname
|
||||
ret_val = self.app.new_object(obj_type, outname, obj_init, plot=False)
|
||||
self.app.shell.append_output(
|
||||
"No path provided or path is wrong. Using the default Path... \n")
|
||||
|
||||
if ret_val == 'fail':
|
||||
return "Failed. The OpenDXF command was used but could not open the DXF file"
|
||||
|
||||
# Register recent file
|
||||
self.app.file_opened.emit("dxf", filename)
|
||||
|
||||
# GUI feedback
|
||||
self.app.inform.emit("Opened: " + filename)
|
||||
@@ -52,10 +52,11 @@ class TclCommandOpenExcellon(TclCommandSignaled):
|
||||
"""
|
||||
|
||||
filename = args.pop('filename')
|
||||
# filename = filename.replace(' ', '')
|
||||
|
||||
if ' ' in filename:
|
||||
return "The absolute path to the project file contain spaces which is not allowed.\n" \
|
||||
"Please enclose the path within quotes."
|
||||
|
||||
args['plot'] = False
|
||||
args['from_tcl'] = True
|
||||
self.app.open_excellon(filename, **args)
|
||||
|
||||
@@ -51,6 +51,7 @@ class TclCommandOpenGCode(TclCommandSignaled):
|
||||
:return: None or exception
|
||||
"""
|
||||
args['plot'] = False
|
||||
args['from_tcl'] = True
|
||||
filename = args["filename"]
|
||||
if ' ' in filename:
|
||||
return "The absolute path to the project file contain spaces which is not allowed.\n" \
|
||||
|
||||
@@ -49,25 +49,11 @@ class TclCommandOpenGerber(TclCommandSignaled):
|
||||
:return: None or exception
|
||||
"""
|
||||
|
||||
# How the object should be initialized
|
||||
def obj_init(gerber_obj, app_obj):
|
||||
if 'follow' in args:
|
||||
self.raise_tcl_error("The 'follow' parameter is obsolete. To create 'follow' geometry use the 'follow' "
|
||||
"parameter for the Tcl Command isolate()")
|
||||
|
||||
if gerber_obj.kind != 'gerber':
|
||||
self.raise_tcl_error('Expected GerberObject, got %s %s.' % (outname, type(gerber_obj)))
|
||||
|
||||
# Opening the file happens here
|
||||
try:
|
||||
gerber_obj.parse_file(filename)
|
||||
except IOError:
|
||||
app_obj.inform.emit("[ERROR_NOTCL] Failed to open file: %s " % filename)
|
||||
self.raise_tcl_error('Failed to open file: %s' % filename)
|
||||
|
||||
except ParseError as e:
|
||||
app_obj.inform.emit("[ERROR_NOTCL] Failed to parse file: %s, %s " % (filename, str(e)))
|
||||
self.log.error(str(e))
|
||||
return
|
||||
|
||||
filename = args['filename']
|
||||
filename = args.pop('filename')
|
||||
|
||||
if ' ' in filename:
|
||||
return "The absolute path to the project file contain spaces which is not allowed.\n" \
|
||||
@@ -78,17 +64,6 @@ class TclCommandOpenGerber(TclCommandSignaled):
|
||||
else:
|
||||
outname = filename.split('/')[-1].split('\\')[-1]
|
||||
|
||||
if 'follow' in args:
|
||||
self.raise_tcl_error("The 'follow' parameter is obsolete. To create 'follow' geometry use the 'follow' "
|
||||
"parameter for the Tcl Command isolate()")
|
||||
|
||||
with self.app.proc_container.new("Opening Gerber"):
|
||||
|
||||
# Object creation
|
||||
self.app.new_object("gerber", outname, obj_init, plot=False)
|
||||
|
||||
# Register recent file
|
||||
self.app.file_opened.emit("gerber", filename)
|
||||
|
||||
# GUI feedback
|
||||
self.app.inform.emit("[success] Opened: " + filename)
|
||||
args['plot'] = False
|
||||
args['from_tcl'] = True
|
||||
self.app.open_gerber(filename, outname, **args)
|
||||
|
||||
@@ -53,4 +53,4 @@ class TclCommandOpenProject(TclCommandSignaled):
|
||||
return "The absolute path to the project file contain spaces which is not allowed.\n" \
|
||||
"Please enclose the path within quotes."
|
||||
|
||||
self.app.open_project(filename, cli=True, plot=False)
|
||||
self.app.open_project(filename, cli=True, plot=False, from_tcl=True)
|
||||
|
||||
93
tclCommands/TclCommandOpenSVG.py
Normal file
93
tclCommands/TclCommandOpenSVG.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
|
||||
import collections
|
||||
|
||||
|
||||
class TclCommandOpenSVG(TclCommandSignaled):
|
||||
"""
|
||||
Tcl shell command to import an SVG file as a Geometry Object.
|
||||
"""
|
||||
|
||||
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||
aliases = ['open_svg']
|
||||
|
||||
description = '%s %s' % ("--", "Open a SVG file as a Geometry (or Gerber) Object.")
|
||||
|
||||
# dictionary of types from Tcl command, needs to be ordered
|
||||
arg_names = collections.OrderedDict([
|
||||
('filename', str)
|
||||
])
|
||||
|
||||
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||
option_types = collections.OrderedDict([
|
||||
('type', str),
|
||||
('outname', str)
|
||||
])
|
||||
|
||||
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||
required = ['filename']
|
||||
|
||||
# structured help for current command, args needs to be ordered
|
||||
help = {
|
||||
'main': "Open a SVG file as a Geometry (or Gerber) Object.",
|
||||
'args': collections.OrderedDict([
|
||||
('filename', 'Absolute path to file to open. Required.\n'
|
||||
'WARNING: no spaces are allowed. If unsure enclose the entire path with quotes.'),
|
||||
('type', 'Open as a Gerber or Geometry (default) object. Values can be: "geometry" or "gerber"'),
|
||||
('outname', 'Name of the resulting Geometry object.')
|
||||
]),
|
||||
'examples': ['open_svg D:\\my_beautiful_svg_file.SVG']
|
||||
}
|
||||
|
||||
def execute(self, args, unnamed_args):
|
||||
"""
|
||||
execute current TCL shell command
|
||||
|
||||
:param args: array of known named arguments and options
|
||||
:param unnamed_args: array of other values which were passed into command
|
||||
without -somename and we do not have them in known arg_names
|
||||
:return: None or exception
|
||||
"""
|
||||
|
||||
# How the object should be initialized
|
||||
def obj_init(geo_obj, app_obj):
|
||||
|
||||
# if geo_obj.kind != 'geometry' or geo_obj.kind != 'gerber':
|
||||
# self.raise_tcl_error('Expected Geometry or Gerber, got %s %s.' % (outname, type(geo_obj)))
|
||||
|
||||
geo_obj.import_svg(filename, obj_type, units=units)
|
||||
|
||||
filename = args['filename']
|
||||
|
||||
if 'outname' in args:
|
||||
outname = args['outname']
|
||||
else:
|
||||
outname = filename.split('/')[-1].split('\\')[-1]
|
||||
|
||||
if 'type' in args:
|
||||
obj_type = args['type'].lower()
|
||||
else:
|
||||
obj_type = 'geometry'
|
||||
|
||||
if obj_type != "geometry" and obj_type != "gerber":
|
||||
self.raise_tcl_error("Option type can be 'geometry' or 'gerber' only, got '%s'." % obj_type)
|
||||
|
||||
units = self.app.defaults['units'].upper()
|
||||
|
||||
with self.app.proc_container.new("Import SVG"):
|
||||
|
||||
# Object creation
|
||||
ret_val = self.app.new_object(obj_type, outname, obj_init, plot=False)
|
||||
if ret_val == 'fail':
|
||||
filename = self.app.defaults['global_tcl_path'] + '/' + outname
|
||||
ret_val = self.app.new_object(obj_type, outname, obj_init, plot=False)
|
||||
self.app.shell.append_output(
|
||||
"No path provided or path is wrong. Using the default Path... \n")
|
||||
if ret_val == 'fail':
|
||||
return "Failed. The OpenSVG command was used but could not open the SVG file"
|
||||
|
||||
# Register recent file
|
||||
self.app.file_opened.emit("svg", filename)
|
||||
|
||||
# GUI feedback
|
||||
self.app.inform.emit("Opened: " + filename)
|
||||
@@ -50,4 +50,4 @@ class TclCommandSaveProject(TclCommandSignaled):
|
||||
:return: None or exception
|
||||
"""
|
||||
|
||||
self.app.save_project(args['filename'])
|
||||
self.app.save_project(args['filename'], from_tcl=True)
|
||||
|
||||
93
tclCommands/TclCommandSetPath.py
Normal file
93
tclCommands/TclCommandSetPath.py
Normal file
@@ -0,0 +1,93 @@
|
||||
# ##########################################################
|
||||
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||
# File Author: Marius Adrian Stanciu (c) #
|
||||
# Date: 4/28/2020 #
|
||||
# MIT Licence #
|
||||
# ##########################################################
|
||||
|
||||
from tclCommands.TclCommand import TclCommand
|
||||
|
||||
import collections
|
||||
import os
|
||||
import logging
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
_ = gettext.gettext
|
||||
|
||||
log = logging.getLogger('base')
|
||||
|
||||
|
||||
class TclCommandSetPath(TclCommand):
|
||||
"""
|
||||
Tcl shell command to set the default path for Tcl Shell for opening files.
|
||||
|
||||
example:
|
||||
|
||||
"""
|
||||
|
||||
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||
aliases = ['set_path']
|
||||
|
||||
description = '%s %s' % ("--", "Set the folder path to the specified path.")
|
||||
|
||||
# Dictionary of types from Tcl command, needs to be ordered
|
||||
arg_names = collections.OrderedDict([
|
||||
('path', str)
|
||||
])
|
||||
|
||||
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||
option_types = collections.OrderedDict([
|
||||
])
|
||||
|
||||
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||
required = ['path']
|
||||
|
||||
# structured help for current command, args needs to be ordered
|
||||
help = {
|
||||
'main': "Will set the folder path to the specified path.\n"
|
||||
"By using this command there is no need for usage of the absolute path to the files.",
|
||||
'args': collections.OrderedDict([
|
||||
('path', 'A folder path to where the user is supposed to have the file that he will work with.\n'
|
||||
'WARNING: No spaces allowed. Use quotes around the path if it contains spaces.'),
|
||||
]),
|
||||
'examples': ['set_path D:\\Project_storage_path']
|
||||
}
|
||||
|
||||
def execute(self, args, unnamed_args):
|
||||
"""
|
||||
|
||||
:param args:
|
||||
:param unnamed_args:
|
||||
:return:
|
||||
"""
|
||||
|
||||
if 'path' not in args:
|
||||
return "Failed. The Tcl command set_path was used but no path argument was provided."
|
||||
else:
|
||||
path = str(args['path']).replace('\\', '/')
|
||||
|
||||
# check if path exists
|
||||
path_isdir = os.path.isdir(path)
|
||||
if path_isdir is False:
|
||||
path_isfile = os.path.isfile(path)
|
||||
if path_isfile:
|
||||
self.app.inform.emit('[ERROR] %s: %s, %s' % (
|
||||
"The provided path",
|
||||
str(path),
|
||||
"is a path to file and not a directory as expected."))
|
||||
return "Failed. The Tcl command set_path was used but it was not a directory."
|
||||
else:
|
||||
self.app.inform.emit('[ERROR] %s: %s, %s' % (
|
||||
"The provided path",
|
||||
str(path),
|
||||
"do not exist. Check for typos."))
|
||||
return "Failed. The Tcl command set_path was used but it does not exist."
|
||||
|
||||
cd_command = 'cd %s' % path
|
||||
self.app.shell.exec_command(cd_command, no_echo=False)
|
||||
self.app.defaults["global_tcl_path"] = str(path)
|
||||
self.app.inform.emit('[success] %s: %s' % ("Relative path set to", str(path)))
|
||||
@@ -103,7 +103,7 @@ class TclCommandWriteGCode(TclCommandSignaled):
|
||||
return "fail"
|
||||
|
||||
try:
|
||||
obj.export_gcode(str(filename), str(preamble), str(postamble))
|
||||
obj.export_gcode(str(filename), str(preamble), str(postamble), from_tcl=True)
|
||||
except Exception as e:
|
||||
if muted is False:
|
||||
return "Operation failed: %s" % str(e)
|
||||
|
||||
@@ -25,9 +25,9 @@ import tclCommands.TclCommandExteriors
|
||||
import tclCommands.TclCommandGeoCutout
|
||||
import tclCommands.TclCommandGeoUnion
|
||||
import tclCommands.TclCommandGetNames
|
||||
import tclCommands.TclCommandGetPath
|
||||
import tclCommands.TclCommandGetSys
|
||||
import tclCommands.TclCommandHelp
|
||||
import tclCommands.TclCommandImportSvg
|
||||
import tclCommands.TclCommandInteriors
|
||||
import tclCommands.TclCommandIsolate
|
||||
import tclCommands.TclCommandFollow
|
||||
@@ -43,10 +43,12 @@ import tclCommands.TclCommandNewExcellon
|
||||
import tclCommands.TclCommandNewGeometry
|
||||
import tclCommands.TclCommandNewGerber
|
||||
import tclCommands.TclCommandOffset
|
||||
import tclCommands.TclCommandOpenDXF
|
||||
import tclCommands.TclCommandOpenExcellon
|
||||
import tclCommands.TclCommandOpenGCode
|
||||
import tclCommands.TclCommandOpenGerber
|
||||
import tclCommands.TclCommandOpenProject
|
||||
import tclCommands.TclCommandOpenSVG
|
||||
import tclCommands.TclCommandOptions
|
||||
import tclCommands.TclCommandPaint
|
||||
import tclCommands.TclCommandPanelize
|
||||
@@ -58,6 +60,7 @@ import tclCommands.TclCommandSaveSys
|
||||
import tclCommands.TclCommandScale
|
||||
import tclCommands.TclCommandSetActive
|
||||
import tclCommands.TclCommandSetOrigin
|
||||
import tclCommands.TclCommandSetPath
|
||||
import tclCommands.TclCommandSetSys
|
||||
import tclCommands.TclCommandSkew
|
||||
import tclCommands.TclCommandSubtractPoly
|
||||
|
||||
Reference in New Issue
Block a user