Merged in marius_stanciu/flatcam_beta/Beta (pull request #224)

Beta
This commit is contained in:
Marius Stanciu 2019-09-23 01:20:53 +00:00
commit 8f5a1a07f0
22 changed files with 2563 additions and 2194 deletions

View File

@ -1198,8 +1198,8 @@ class App(QtCore.QObject):
# Keyword list
"util_autocomplete_keywords": 'Desktop, Documents, FlatConfig, FlatPrj, Marius, My Documents, Paste_1, '
'Repetier, Roland_MDX_20, Toolchange_Custom, Toolchange_Probe_MACH3, '
'Toolchange_manual, Users, all, angle_x, angle_y, axis, axisoffset, box, '
'center_x, center_y, columns, combine, connect, contour, default, '
'Toolchange_manual, Users, all, angle_x, angle_y, axis, auto, axisoffset, '
'box, center_x, center_y, columns, combine, connect, contour, default, '
'depthperpass, dia, diatol, dist, drilled_dias, drillz, dwell, dwelltime, '
'feedrate_z, grbl_11, grbl_laser, gridoffsety, gridx, gridy, has_offset, '
'holes, hpgl, iso_type, line_xyz, margin, marlin, method, milled_dias, '
@ -1586,6 +1586,19 @@ class App(QtCore.QObject):
# ### End of Data ####
# ##############################################
# ######### SETUP OBJECT COLLECTION ############
# ##############################################
self.collection = ObjectCollection(self)
self.ui.project_tab_layout.addWidget(self.collection.view)
# ### Adjust tabs width ## ##
# self.collection.view.setMinimumWidth(self.ui.options_scroll_area.widget().sizeHint().width() +
# self.ui.options_scroll_area.verticalScrollBar().sizeHint().width())
self.collection.view.setMinimumWidth(290)
self.log.debug("Finished creating Object Collection.")
# ###############################################
# ############# SETUP Plot Area #################
# ###############################################
@ -1607,9 +1620,7 @@ class App(QtCore.QObject):
start_plot_time = time.time() # debug
self.plotcanvas = None
# this is a list just because when in legacy it is needed to add multiple cursors
# each gets deleted when the axes are deleted therefore there is a need of one for each
self.app_cursor = []
self.app_cursor = None
self.hover_shapes = None
self.on_plotcanvas_setup()
@ -1639,19 +1650,6 @@ class App(QtCore.QObject):
self.trayIcon = FlatCAMSystemTray(app=self, icon=QtGui.QIcon('share/flatcam_icon32_green.png'),
parent=self.parent_w)
# ##############################################
# ######### SETUP OBJECT COLLECTION ############
# ##############################################
self.collection = ObjectCollection(self)
self.ui.project_tab_layout.addWidget(self.collection.view)
# ### Adjust tabs width ## ##
# self.collection.view.setMinimumWidth(self.ui.options_scroll_area.widget().sizeHint().width() +
# self.ui.options_scroll_area.verticalScrollBar().sizeHint().width())
self.collection.view.setMinimumWidth(290)
self.log.debug("Finished creating Object Collection.")
# ###############################################
# ############# Worker SETUP ####################
# ###############################################
@ -2109,17 +2107,17 @@ class App(QtCore.QObject):
'join_geometry', 'list_sys', 'listsys', 'milld', 'mills', 'milldrills', 'millslots',
'mirror', 'ncc',
'ncc_clear', 'ncr', 'new', 'new_geometry', 'non_copper_regions', 'offset',
'open_excellon', 'open_gcode', 'open_gerber', 'open_project', 'options', 'paint',
'pan', 'panel', 'panelize', 'plot_all', 'plot_objects', 'quit_flatcam',
'open_excellon', 'open_gcode', 'open_gerber', 'open_project', 'options', 'origin',
'paint', 'pan', 'panel', 'panelize', 'plot_all', 'plot_objects', 'quit_flatcam',
'save', 'save_project',
'save_sys', 'scale',
'set_active', 'set_sys', 'setsys', 'skew', 'subtract_poly', 'subtract_rectangle',
'save_sys', 'scale', 'set_active', 'set_origin', 'set_sys',
'setsys', 'skew', 'subtract_poly', 'subtract_rectangle',
'version', 'write_gcode'
]
self.default_keywords = ['Desktop', 'Documents', 'FlatConfig', 'FlatPrj', 'Marius', 'My Documents', 'Paste_1',
'Repetier', 'Roland_MDX_20', 'Toolchange_Custom', 'Toolchange_Probe_MACH3',
'Toolchange_manual', 'Users', 'all', 'angle_x', 'angle_y', 'axis', 'axisoffset',
'Toolchange_manual', 'Users', 'all', 'angle_x', 'angle_y', 'auto', 'axis', 'axisoffset',
'box', 'center_x', 'center_y', 'columns', 'combine', 'connect', 'contour', 'default',
'depthperpass', 'dia', 'diatol', 'dist', 'drilled_dias', 'drillz', 'dwell',
'dwelltime', 'feedrate_z', 'grbl_11', 'grbl_laser', 'gridoffsety', 'gridx', 'gridy',
@ -2490,6 +2488,7 @@ class App(QtCore.QObject):
self.mp = None
self.mm = None
self.mr = None
self.mp_zc = None
# when True, the app has to return from any thread
self.abort_flag = False
@ -6783,16 +6782,56 @@ class App(QtCore.QObject):
pass
self.replot_signal[list].connect(origin_replot)
def on_set_zero_click(self, event):
# this function will be available only for mouse left click
def on_set_zero_click(self, event, location=None, noplot=False, use_thread=True):
"""
if self.is_legacy is False:
event_pos = event.pos
else:
event_pos = (event.xdata, event.ydata)
:param event:
:param location:
:param noplot:
:param use_thread:
:return:
"""
noplot_sig = noplot
def worker_task():
with self.proc_container.new(_("Setting Origin...")):
for obj in self.collection.get_list():
obj.offset((x, y))
self.object_changed.emit(obj)
# Update the object bounding box options
a, b, c, d = obj.bounds()
obj.options['xmin'] = a
obj.options['ymin'] = b
obj.options['xmax'] = c
obj.options['ymax'] = d
self.inform.emit('[success] %s...' %
_('Origin set'))
if noplot_sig is False:
self.replot_signal.emit([])
if location is not None:
if len(location) != 2:
self.inform.emit('[ERROR_NOTCL] %s...' %
_("Origin coordinates specified but incomplete."))
return 'fail'
x, y = location
if use_thread is True:
self.worker_task.emit({'fcn': worker_task, 'params': []})
else:
worker_task()
self.should_we_save = True
return
pos_canvas = self.plotcanvas.translate_coords(event_pos)
if event.button == 1:
if self.is_legacy is False:
event_pos = event.pos
else:
event_pos = (event.xdata, event.ydata)
pos_canvas = self.plotcanvas.translate_coords(event_pos)
if self.grid_status() == True:
pos = self.geo_editor.snap(pos_canvas[0], pos_canvas[1])
else:
@ -6801,23 +6840,10 @@ class App(QtCore.QObject):
x = 0 - pos[0]
y = 0 - pos[1]
def worker_task():
with self.proc_container.new(_("Setting Origin...")):
for obj in self.collection.get_list():
obj.offset((x, y))
self.object_changed.emit(obj)
# Update the object bounding box options
a, b, c, d = obj.bounds()
obj.options['xmin'] = a
obj.options['ymin'] = b
obj.options['xmax'] = c
obj.options['ymax'] = d
self.inform.emit('[success]%s...' %
_('Origin set'))
self.replot_signal.emit([])
self.worker_task.emit({'fcn': worker_task, 'params': []})
if use_thread is True:
self.worker_task.emit({'fcn': worker_task, 'params': []})
else:
worker_task()
self.should_we_save = True
def on_jump_to(self, custom_location=None, fit_center=True):

View File

@ -85,7 +85,7 @@ class FlatCAMObj(QtCore.QObject):
if self.app.is_legacy is False:
self.shapes = self.app.plotcanvas.new_shape_group()
else:
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='application')
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name=name)
# self.mark_shapes = self.app.plotcanvas.new_shape_collection(layers=2)
self.mark_shapes = {}

View File

@ -9,6 +9,16 @@ CAD program, and create G-Code for Isolation routing.
=================================================
23.09.2019
- in legacy graphic engine, fixed bug that made the old object disappear when a new object was loaded
- in legacy graphic engine, fixed bug that crashed the app when creating a new project
- in legacy graphic engine, fixed a bug that when deleting an object all objects where deleted
- added a new TclCommand named "set_origin" which will set the origin for all loaded objects to zero if the -auto True argument is used and to a certain x,y location if the format is: set_origin 5,7
- added a new TclCommand named "bounds" which will return a list of bounds values from a supplied list of objects names. For use in Tcl Scripts
- updated strings in the translations and the .POT file
- added the new keywords to the default keywords list
22.09.2019
- fixed zoom directions legacy graphic engine (previous commit)
@ -29,6 +39,7 @@ CAD program, and create G-Code for Isolation routing.
- updated and corrected the Romanian and Spanish translations
- updated the .PO files for the rest of the translations, they need to be filled in.
- fixed crash when trying to set a workspace in FlatCAM in the Legacy engine 2D mode by disabling this function for the case of 2D mode
- fixed exception when trying to Fit View (shortcut key 'V') with no object loaded, in legacy graphic engine
21.09.2019

View File

@ -5041,7 +5041,7 @@ class Excellon(Geometry):
def bounds(self):
"""
Returns coordinates of rectangular bounds
of Gerber geometry: (xmin, ymin, xmax, ymax).
of Excellon geometry: (xmin, ymin, xmax, ymax).
"""
# fixed issue of getting bounds only for one level lists of objects
# now it can get bounds for nested lists of objects

View File

@ -306,10 +306,21 @@ class PlotCanvasLegacy(QtCore.QObject):
self.figure.add_axes(self.axes)
self.axes.set_aspect(1)
self.axes.grid(True)
self.axes.axhline(color=(0.70, 0.3, 0.3), linewidth=2)
self.axes.axvline(color=(0.70, 0.3, 0.3), linewidth=2)
self.adjust_axes(-10, -10, 100, 100)
# Re-draw
self.canvas.draw_idle()
def redraw(self):
"""
Created only to serve for compatibility with the VisPy plotcanvas (the other graphic engine, 3D)
:return:
"""
self.clear()
def adjust_axes(self, xmin, ymin, xmax, ymax):
"""
Adjusts all axes while maintaining the use of the whole canvas
@ -329,6 +340,12 @@ class PlotCanvasLegacy(QtCore.QObject):
# FlatCAMApp.App.log.debug("PC.adjust_axes()")
if not self.app.collection.get_list():
xmin = -10
ymin = -10
xmax = 100
ymax = 100
width = xmax - xmin
height = ymax - ymin
try:
@ -588,7 +605,7 @@ class PlotCanvasLegacy(QtCore.QObject):
:param position: Mouse event position
:return: Tuple with mouse position
"""
return (position[0], position[1])
return position[0], position[1]
def on_draw(self, renderer):

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
from tclCommands.TclCommand import TclCommand
from ObjectCollection import *
from camlib import get_bounds
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
class TclCommandBounds(TclCommand):
"""
Tcl shell command to return the bounds values for a supplied list of objects (identified by their names).
example:
"""
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
aliases = ['get_bounds', 'bounds']
# Dictionary of types from Tcl command, needs to be ordered
arg_names = collections.OrderedDict([
('objects', 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 = []
# structured help for current command, args needs to be ordered
help = {
'main': "Will return a list of bounds values, each set of bound values is "
"a list itself: [xmin, ymin, xmax, ymax].",
'args': collections.OrderedDict([
('objects', 'A list of object names separated by comma without spaces.'),
]),
'examples': ['bounds a_obj.GTL,b_obj.DRL']
}
def execute(self, args, unnamed_args):
"""
:param args:
:param unnamed_args:
:return:
"""
obj_list = list()
if 'objects' in args:
try:
obj_list = [str(obj_name) for obj_name in str(args['objects']).split(",") if obj_name != '']
except AttributeError as e:
log.debug("TclCommandBounds.execute --> %s" % str(e))
if not obj_list:
self.raise_tcl_error('%s: %s:' % (
_("Expected a list of objects names separated by comma. Got"), str(args['objects'])))
return 'fail'
else:
self.raise_tcl_error('%s: %s:' % (
_("Expected a list of objects names separated by comma. Got"), str(args['objects'])))
return 'fail'
result_list = list()
for name in obj_list:
obj = self.app.collection.get_by_name(name)
xmin, ymin, xmax, ymax = obj.bounds()
result_list.append([xmin, ymin, xmax, ymax])
self.app.inform.emit('[success] %s ...' %
_('TclCommand Bounds done.'))
return result_list

View File

@ -136,6 +136,7 @@ class TclCommandCopperClear(TclCommand):
tools = [float(eval(dia)) for dia in tooldia.split(",") if dia != '']
except AttributeError:
tools = [float(tooldia)]
# store here the default data for Geometry Data
default_data = {}
default_data.update({

View File

@ -0,0 +1,88 @@
from tclCommands.TclCommand import TclCommand
from ObjectCollection import *
from camlib import get_bounds
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
class TclCommandSetOrigin(TclCommand):
"""
Tcl shell command to set the origin to zero or to a specified location for all loaded objects in FlatCAM.
example:
"""
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
aliases = ['set_origin', 'origin']
# Dictionary of types from Tcl command, needs to be ordered
arg_names = collections.OrderedDict([
('loc', str)
])
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
option_types = collections.OrderedDict([
('auto', bool)
])
# 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 set the origin at the specified x,y location.",
'args': collections.OrderedDict([
('loc', 'Location to offset all the selected objects. No spaces between x and y pair. Use like this: 2,3'),
('auto', 'If set to 1 it will set the origin to the minimum x, y of the object selection bounding box.'
'-auto=1 is not correct but -auto 1 or -auto True is correct.')
]),
'examples': ['set_origin 3,2', 'set_origin -auto 1']
}
def execute(self, args, unnamed_args):
"""
:param args:
:param unnamed_args:
:return:
"""
loc = list()
if 'auto' in args:
if args['auto'] == 1:
objs = self.app.collection.get_list()
minx, miny, __, ___ = get_bounds(objs)
loc.append(0 - minx)
loc.append(0 - miny)
else:
loc = [0, 0]
elif 'loc' in args:
try:
location = [float(eval(coord)) for coord in str(args['loc']).split(",") if coord != '']
except AttributeError as e:
log.debug("TclCommandSetOrigin.execute --> %s" % str(e))
location = (0, 0)
loc.append(location[0])
loc.append(location[1])
if len(location) != 2:
self.raise_tcl_error('%s: %s' % (
_("Expected a pair of (x, y) coordinates. Got"), str(len(location))))
return 'fail'
else:
loc = [0, 0]
self.app.on_set_zero_click(event=None, location=loc, noplot=True, use_thread=False)
self.app.inform.emit('[success] Tcl %s: %s' %
(_('Origin set by offsetting all loaded objects with '),
'{0:.4f}, {0:.4f}'.format(loc[0], loc[1])))

View File

@ -10,6 +10,7 @@ import tclCommands.TclCommandAddRectangle
import tclCommands.TclCommandAlignDrill
import tclCommands.TclCommandAlignDrillGrid
import tclCommands.TclCommandBbox
import tclCommands.TclCommandBounds
import tclCommands.TclCommandClearShell
import tclCommands.TclCommandCncjob
import tclCommands.TclCommandCopperClear
@ -53,6 +54,7 @@ import tclCommands.TclCommandSaveProject
import tclCommands.TclCommandSaveSys
import tclCommands.TclCommandScale
import tclCommands.TclCommandSetActive
import tclCommands.TclCommandSetOrigin
import tclCommands.TclCommandSetSys
import tclCommands.TclCommandSkew
import tclCommands.TclCommandSubtractPoly