jpcgt/flatcam/Beta слито с Beta

This commit is contained in:
Camellan 2019-12-27 21:32:27 +04:00
commit 9fc0d64806
344 changed files with 20333 additions and 17266 deletions

File diff suppressed because it is too large Load Diff

View File

@ -505,6 +505,94 @@ class ToolsDB(QtWidgets.QWidget):
self.table_widget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
table_hlay.addWidget(self.table_widget)
# set the number of columns and the headers tool tips
self.configure_table()
# pal = QtGui.QPalette()
# pal.setColor(QtGui.QPalette.Background, Qt.white)
# New Bookmark
new_vlay = QtWidgets.QVBoxLayout()
layout.addLayout(new_vlay)
# new_tool_lbl = QtWidgets.QLabel('<b>%s</b>' % _("New Tool"))
# new_vlay.addWidget(new_tool_lbl, alignment=QtCore.Qt.AlignBottom)
self.buttons_frame = QtWidgets.QFrame()
self.buttons_frame.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.buttons_frame)
self.buttons_box = QtWidgets.QHBoxLayout()
self.buttons_box.setContentsMargins(0, 0, 0, 0)
self.buttons_frame.setLayout(self.buttons_box)
self.buttons_frame.show()
add_entry_btn = FCButton(_("Add Geometry Tool in DB"))
add_entry_btn.setToolTip(
_("Add a new tool in the Tools Database.\n"
"It will be used in the Geometry UI.\n"
"You can edit it after it is added.")
)
self.buttons_box.addWidget(add_entry_btn)
# add_fct_entry_btn = FCButton(_("Add Paint/NCC Tool in DB"))
# add_fct_entry_btn.setToolTip(
# _("Add a new tool in the Tools Database.\n"
# "It will be used in the Paint/NCC Tools UI.\n"
# "You can edit it after it is added.")
# )
# self.buttons_box.addWidget(add_fct_entry_btn)
remove_entry_btn = FCButton(_("Delete Tool from DB"))
remove_entry_btn.setToolTip(
_("Remove a selection of tools in the Tools Database.")
)
self.buttons_box.addWidget(remove_entry_btn)
export_db_btn = FCButton(_("Export DB"))
export_db_btn.setToolTip(
_("Save the Tools Database to a custom text file.")
)
self.buttons_box.addWidget(export_db_btn)
import_db_btn = FCButton(_("Import DB"))
import_db_btn.setToolTip(
_("Load the Tools Database information's from a custom text file.")
)
self.buttons_box.addWidget(import_db_btn)
self.add_tool_from_db = FCButton(_("Add Tool from Tools DB"))
self.add_tool_from_db.setToolTip(
_("Add a new tool in the Tools Table of the\n"
"active Geometry object after selecting a tool\n"
"in the Tools Database.")
)
self.add_tool_from_db.hide()
self.cancel_tool_from_db = FCButton(_("Cancel"))
self.cancel_tool_from_db.hide()
hlay = QtWidgets.QHBoxLayout()
layout.addLayout(hlay)
hlay.addWidget(self.add_tool_from_db)
hlay.addWidget(self.cancel_tool_from_db)
hlay.addStretch()
# ##############################################################################
# ######################## SIGNALS #############################################
# ##############################################################################
add_entry_btn.clicked.connect(self.on_tool_add)
remove_entry_btn.clicked.connect(self.on_tool_delete)
export_db_btn.clicked.connect(self.on_export_tools_db_file)
import_db_btn.clicked.connect(self.on_import_tools_db_file)
# closebtn.clicked.connect(self.accept)
self.add_tool_from_db.clicked.connect(self.on_tool_requested_from_app)
self.cancel_tool_from_db.clicked.connect(self.on_cancel_tool)
self.setup_db_ui()
def configure_table(self):
self.table_widget.setColumnCount(27)
# self.table_widget.setColumnWidth(0, 20)
self.table_widget.setHorizontalHeaderLabels(
@ -648,83 +736,8 @@ class ToolsDB(QtWidgets.QWidget):
_("End Z.\n"
"A position on Z plane to move immediately after job stop."))
# pal = QtGui.QPalette()
# pal.setColor(QtGui.QPalette.Background, Qt.white)
# New Bookmark
new_vlay = QtWidgets.QVBoxLayout()
layout.addLayout(new_vlay)
# new_tool_lbl = QtWidgets.QLabel('<b>%s</b>' % _("New Tool"))
# new_vlay.addWidget(new_tool_lbl, alignment=QtCore.Qt.AlignBottom)
self.buttons_frame = QtWidgets.QFrame()
self.buttons_frame.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.buttons_frame)
self.buttons_box = QtWidgets.QHBoxLayout()
self.buttons_box.setContentsMargins(0, 0, 0, 0)
self.buttons_frame.setLayout(self.buttons_box)
self.buttons_frame.show()
add_entry_btn = FCButton(_("Add Tool to Tools DB"))
add_entry_btn.setToolTip(
_("Add a new tool in the Tools Database.\n"
"You can edit it after it is added.")
)
remove_entry_btn = FCButton(_("Remove Tool from Tools DB"))
remove_entry_btn.setToolTip(
_("Remove a selection of tools in the Tools Database.")
)
export_db_btn = FCButton(_("Export Tool DB"))
export_db_btn.setToolTip(
_("Save the Tools Database to a custom text file.")
)
import_db_btn = FCButton(_("Import Tool DB"))
import_db_btn.setToolTip(
_("Load the Tools Database information's from a custom text file.")
)
# button_hlay.addStretch()
self.buttons_box.addWidget(add_entry_btn)
self.buttons_box.addWidget(remove_entry_btn)
self.buttons_box.addWidget(export_db_btn)
self.buttons_box.addWidget(import_db_btn)
# self.buttons_box.addWidget(closebtn)
self.add_tool_from_db = FCButton(_("Add Tool from Tools DB"))
self.add_tool_from_db.setToolTip(
_("Add a new tool in the Tools Table of the\n"
"active Geometry object after selecting a tool\n"
"in the Tools Database.")
)
self.add_tool_from_db.hide()
self.cancel_tool_from_db = FCButton(_("Cancel"))
self.cancel_tool_from_db.hide()
hlay = QtWidgets.QHBoxLayout()
layout.addLayout(hlay)
hlay.addWidget(self.add_tool_from_db)
hlay.addWidget(self.cancel_tool_from_db)
hlay.addStretch()
# ##############################################################################
# ######################## SIGNALS #############################################
# ##############################################################################
add_entry_btn.clicked.connect(self.on_tool_add)
remove_entry_btn.clicked.connect(self.on_tool_delete)
export_db_btn.clicked.connect(self.on_export_tools_db_file)
import_db_btn.clicked.connect(self.on_import_tools_db_file)
# closebtn.clicked.connect(self.accept)
self.add_tool_from_db.clicked.connect(self.on_tool_requested_from_app)
self.cancel_tool_from_db.clicked.connect(self.on_cancel_tool)
self.setup_db_ui()
def setup_db_ui(self):
filename = self.app.data_path + '/tools_db.FlatConfig'
filename = self.app.data_path + '/tools_db.FlatDB'
# load the database tools from the file
try:
@ -1007,7 +1020,17 @@ class ToolsDB(QtWidgets.QWidget):
dict_elem = dict()
dict_elem['name'] = 'new_tool'
dict_elem['tooldia'] = self.app.defaults["geometry_cnctooldia"]
if type(self.app.defaults["geometry_cnctooldia"]) == float:
dict_elem['tooldia'] = self.app.defaults["geometry_cnctooldia"]
else:
try:
tools_string = self.app.defaults["geometry_cnctooldia"].split(",")
tools_diameters = [eval(a) for a in tools_string if a != '']
dict_elem['tooldia'] = tools_diameters[0] if tools_diameters else 0.0
except Exception as e:
self.app.log.debug("ToolDB.on_tool_add() --> %s" % str(e))
return
dict_elem['offset'] = 'Path'
dict_elem['offset_value'] = 0.0
dict_elem['type'] = 'Rough'
@ -1151,7 +1174,7 @@ class ToolsDB(QtWidgets.QWidget):
def on_save_tools_db(self, silent=False):
self.app.log.debug("ToolsDB.on_save_button() --> Saving Tools Database to file.")
filename = self.app.data_path + "/tools_db.FlatConfig"
filename = self.app.data_path + "/tools_db.FlatDB"
# Preferences save, update the color of the Tools DB Tab text
for idx in range(self.app.ui.plot_tab_area.count()):

View File

@ -659,8 +659,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
self.units_found = self.app.defaults['units']
self.fill_color = self.app.defaults['global_plot_fill']
self.outline_color = self.app.defaults['global_plot_line']
self.fill_color = self.app.defaults['gerber_plot_fill']
self.outline_color = self.app.defaults['gerber_plot_line']
# Attributes to be included in serialization
# Always append to it because it carries contents
@ -738,6 +738,10 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
self.ui.tool_type_label.hide()
self.ui.tool_type_radio.hide()
# override the Preferences Value; in Basic mode the Tool Type is always Circular ('C1')
self.ui.tool_type_radio.set_value('circular')
self.ui.tipdialabel.hide()
self.ui.tipdia_spinner.hide()
self.ui.tipanglelabel.hide()
@ -1436,7 +1440,10 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
def iso_init(geo_obj, app_obj):
# Propagate options
geo_obj.options["cnctooldia"] = str(self.options["isotooldia"])
geo_obj.tool_type = self.ui.tool_type_radio.get_value().upper()
if self.ui.tool_type_radio.get_value() == 'v':
geo_obj.tool_type = 'V'
else:
geo_obj.tool_type = 'C1'
# if milling type is climb then the move is counter-clockwise around features
mill_t = 1 if milling_type == 'cl' else 0
@ -1783,7 +1790,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
if 'color' in kwargs:
color = kwargs['color']
else:
color = self.app.defaults['global_plot_fill']
color = self.app.defaults['gerber_plot_fill']
if 'marked_aperture' not in kwargs:
return
@ -3529,7 +3536,9 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
# Plot Excellon (All polygons?)
if self.options["solid"]:
for geo in self.solid_geometry:
self.add_shape(shape=geo, color='#750000BF', face_color='#C40000BF',
self.add_shape(shape=geo,
color=self.app.defaults["excellon_plot_line"],
face_color=self.app.defaults["excellon_plot_fill"],
visible=visible,
layer=2)
else:
@ -3588,7 +3597,15 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
})
if "cnctooldia" not in self.options:
self.options["cnctooldia"] = self.app.defaults["geometry_cnctooldia"]
if type(self.app.defaults["geometry_cnctooldia"]) == float:
self.options["cnctooldia"] = self.app.defaults["geometry_cnctooldia"]
else:
try:
tools_string = self.app.defaults["geometry_cnctooldia"].split(",")
tools_diameters = [eval(a) for a in tools_string if a != '']
self.options["cnctooldia"] = tools_diameters[0] if tools_diameters else 0.0
except Exception as e:
log.debug("FlatCAMObj.FlatCAMGeometry.init() --> %s" % str(e))
self.options["startz"] = self.app.defaults["geometry_startz"]
@ -4059,7 +4076,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
# I use lambda's because the connected functions have parameters that could be used in certain scenarios
self.ui.addtool_btn.clicked.connect(lambda: self.on_tool_add())
self.ui.addtool_entry.returnPressed.connect(self.on_tool_add)
self.ui.copytool_btn.clicked.connect(lambda: self.on_tool_copy())
self.ui.deltool_btn.clicked.connect(lambda: self.on_tool_delete())
@ -4112,11 +4128,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
except (TypeError, AttributeError):
pass
try:
self.ui.addtool_entry.returnPressed.disconnect()
except (TypeError, AttributeError):
pass
try:
self.ui.copytool_btn.clicked.disconnect()
except (TypeError, AttributeError):
@ -5778,12 +5789,15 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
return factor
def plot_element(self, element, color='#FF0000FF', visible=None):
def plot_element(self, element, color=None, visible=None):
if color is None:
color = '#FF0000FF'
visible = visible if visible else self.options['plot']
try:
for sub_el in element:
self.plot_element(sub_el)
self.plot_element(sub_el, color=color)
except TypeError: # Element is not iterable...
# if self.app.is_legacy is False:
@ -5810,12 +5824,14 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
if self.multigeo is True: # geo multi tool usage
for tooluid_key in self.tools:
solid_geometry = self.tools[tooluid_key]['solid_geometry']
self.plot_element(solid_geometry, visible=visible)
self.plot_element(solid_geometry, visible=visible,
color=self.app.defaults["geometry_plot_line"])
else:
# plot solid geometry that may be an direct attribute of the geometry object
# for SingleGeo
if self.solid_geometry:
self.plot_element(self.solid_geometry, visible=visible)
self.plot_element(self.solid_geometry, visible=visible,
color=self.app.defaults["geometry_plot_line"])
# self.plot_element(self.solid_geometry, visible=self.options['plot'])

View File

@ -9,19 +9,58 @@ CAD program, and create G-Code for Isolation routing.
=================================================
27.12.2019
- updated the POT file and the translation files for German, Spanish and French languages
26.12.2019
- modified the ToolDB class and changed some strings
- Preferences classes now have access to the App attributes through app.setup_obj_classes() method
- moved app.setup_obj_classes() upper in the App.__init__()
- added a new Preferences setting allowing to modify the mouse cursor color
- remade the GUI in Preferences -> General grouping the settings in a more clear way
- made available the Jump To function in Excellon Editor
- added a clean_up() method in all the Editor Tools that need it, to be run when aborting using the ESC key
- fixed an error in the Gerber parser; it did not took into consideration the aperture size declared before the beginning of a Gerber region. Detected for Gerber files generated by KiCAD 5.x
- in Panelize Tool made sure that for Gerber objects if one of the apertures is without geometry then it is ignored
- further modifications in Preferences -> General GUI
- further modifications in Preferences -> General GUI - extended the changes
- in Legacy(2D) graphic engine made to work the mouse color change
- theme changing is no longer auto-reboot upon change; it require now to press a button
- cleaned the Preferences classes and added the signals and signal slots in those classes, removing them from the main app class
- each FlatCAM object found in Preferences has it's own set of controls for changing the colors
- added a set of gray icons to be used when the theme is complete dark (for now it is useful only for MacOS with dark theme because at the moment the app is not styled to dark UI except the plot area)
25.12.2019
- fixed an issue in old default file detection and in saving the factory defaults file
- in Preferences window removed the Import/Export Preferences buttons because they are redundant with the entries in the File -> Menu -> Backup. and added a button to Restore Defaults
- when in Basic mode the Tool type of the tool in the Geometry UI Tool Table after isolating a Gerber object is automatically selected as 'C1'
- let the multiprocessing Pool have as many processes as needed
- added a new Preferences setting allowing a custom mouse line width (to make it thicker or thinner)
- changed the extension of the Tool Database file to FlatDB for easy recognition (in the future double clicking such a file might import the new tools in the FC database)
24.12.2019
- edited some icons so they don't contain white background
- fixed an incorrect usage of object in the app.select_objects() method
- fixed a typo in ToolDB.on_tool_add()
23.12.2019
- some fixes in the Legacy(2D) graphic mode regarding the possibility of changing the color of the Gerber objects
- added a method to darken the outline color for Gerber objects when they have the color set
- when Printing as PDF Gerber objects now the rendered color is the print color
- speed up the plotting in OpenGL(3D) graphic mode
- spped up the color setting for Gerber object when using the OpenGL(3D) graphic mode
- speed up the color setting for Gerber object when using the OpenGL(3D) graphic mode
- setting color for Gerber objects work on a selection of Gerber objects
- ~~when the selection is changed in the Project Tree the selection shape on canvas is deleted~~
- if an object is selected on Project Tree and it does not have the selection shape drawn, first click on canvas over it will draw the selection shape
- in Tool Transform added a new feature named 'Buffer'. For Geometry and Gerber objects will create (and replace) a geometry at a distance from the original geometry and for Excellon will adjust the Tool diameters
- solved issue #355 - when the tool diameter field in the Edit → Preferences → Geometry → Geometry General → Tools → Tool dia is only one the app failed to read it
- solved issue #356 - in Tools DB can not be added more than one tool if a translation is active
- some changes related to the fact that the geometry default tool diameter value can be comma separated string of tool diameters
22.12.2019

View File

@ -3466,11 +3466,20 @@ class CNCjob(Geometry):
flat_geometry = self.flatten(temp_solid_geometry, pathonly=True)
log.debug("%d paths" % len(flat_geometry))
if type(self.app.defaults["geometry_cnctooldia"]) == float:
default_dia = self.app.defaults["geometry_cnctooldia"]
else:
try:
tools_string = self.defaults["geometry_cnctooldia"].split(",")
tools_diameters = [eval(a) for a in tools_string if a != '']
default_dia = tools_diameters[0] if tools_diameters else 0.0
except Exception as e:
self.app.log.debug("camlib.CNCJob.generate_from_geometry_2() --> %s" % str(e))
try:
self.tooldia = float(tooldia) if tooldia else self.app.defaults["geometry_cnctooldia"]
self.tooldia = float(tooldia) if tooldia else default_dia
except ValueError:
self.tooldia = [float(el) for el in tooldia.split(',') if el != ''] if tooldia is not None else \
self.app.defaults["geometry_cnctooldia"]
self.tooldia = [float(el) for el in tooldia.split(',') if el != ''] if tooldia is not None else default_dia
self.z_cut = float(z_cut) if z_cut is not None else self.app.defaults["geometry_cutz"]
self.z_move = float(z_move) if z_move is not None else self.app.defaults["geometry_travelz"]
@ -4243,8 +4252,7 @@ class CNCjob(Geometry):
# return fig
def plot2(self, tooldia=None, dpi=75, margin=0.1, gcode_parsed=None,
color={"T": ["#F0E24D4C", "#B5AB3A4C"], "C": ["#5E6CFFFF", "#4650BDFF"]},
alpha={"T": 0.3, "C": 1.0}, tool_tolerance=0.0005, obj=None, visible=False, kind='all'):
color=None, alpha={"T": 0.3, "C": 1.0}, tool_tolerance=0.0005, obj=None, visible=False, kind='all'):
"""
Plots the G-code job onto the given axes.
@ -4261,6 +4269,12 @@ class CNCjob(Geometry):
"""
# units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper()
if color is None:
color = {
"T": [self.app.defaults["cncjob_travel_fill"], self.app.defaults["cncjob_travel_line"]],
"C": [self.app.defaults["cncjob_plot_fill"], self.app.defaults["cncjob_plot_line"]]
}
gcode_parsed = gcode_parsed if gcode_parsed else self.gcode_parsed
path_num = 0

View File

@ -56,8 +56,7 @@ class FCDrillAdd(FCShapeTool):
item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1)
self.draw_app.tools_table_exc.setCurrentItem(item)
except KeyError:
self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
_("To add a drill first select a tool"))
self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' % _("To add a drill first select a tool"))
self.draw_app.select_tool("drill_select")
return
@ -75,6 +74,8 @@ class FCDrillAdd(FCShapeTool):
self.draw_app.app.inform.emit(_("Click to place ..."))
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
@ -119,8 +120,18 @@ class FCDrillAdd(FCShapeTool):
self.geometry = DrawToolShape(self.util_shape(self.points))
self.draw_app.in_action = False
self.complete = True
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Drill added."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Drill added."))
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.tools_table_exc.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCDrillArray(FCShapeTool):
@ -181,6 +192,8 @@ class FCDrillArray(FCShapeTool):
self.draw_app.app.inform.emit(_("Click on target location ..."))
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
@ -292,7 +305,7 @@ class FCDrillArray(FCShapeTool):
try:
QtGui.QGuiApplication.restoreOverrideCursor()
except Exception as e:
except Exception:
pass
# add the point to drills if the diameter is a key in the dict, if not, create it add the drill location
@ -322,6 +335,7 @@ class FCDrillArray(FCShapeTool):
if (self.drill_angle * self.drill_array_size) > 360:
self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
_("Too many drills for the selected spacing angle."))
self.draw_app.app.jump_signal.disconnect()
return
radius = distance(self.destination, self.origin)
@ -338,11 +352,21 @@ class FCDrillArray(FCShapeTool):
geo = self.util_shape((x, y))
self.geometry.append(DrawToolShape(geo))
self.complete = True
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Drill Array added."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Drill Array added."))
self.draw_app.in_action = False
self.draw_app.array_frame.hide()
return
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.tools_table_exc.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCSlot(FCShapeTool):
@ -391,6 +415,8 @@ class FCSlot(FCShapeTool):
self.draw_app.app.inform.emit(_("Click on target location ..."))
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
@ -531,9 +557,19 @@ class FCSlot(FCShapeTool):
self.draw_app.in_action = False
self.complete = True
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Adding Slot completed."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Adding Slot completed."))
self.draw_app.slot_frame.hide()
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.tools_table_exc.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCSlotArray(FCShapeTool):
@ -600,6 +636,8 @@ class FCSlotArray(FCShapeTool):
self.draw_app.app.inform.emit(_("Click on target location ..."))
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
@ -821,6 +859,7 @@ class FCSlotArray(FCShapeTool):
if (self.slot_angle * self.slot_array_size) > 360:
self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' %
_("Too many Slots for the selected spacing angle."))
self.draw_app.app.jump_signal.disconnect()
return
radius = distance(self.destination, self.origin)
@ -842,18 +881,22 @@ class FCSlotArray(FCShapeTool):
self.geometry.append(DrawToolShape(geo))
self.complete = True
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Slot Array added."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Slot Array added."))
self.draw_app.in_action = False
self.draw_app.slot_frame.hide()
self.draw_app.slot_array_frame.hide()
return
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.selected = list()
self.draw_app.tools_table_exc.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCDrillResize(FCShapeTool):
def __init__(self, draw_app):
@ -1084,6 +1127,16 @@ class FCDrillResize(FCShapeTool):
# MS: always return to the Select Tool
self.draw_app.select_tool("drill_select")
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.tools_table_exc.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCDrillMove(FCShapeTool):
def __init__(self, draw_app):
@ -1112,6 +1165,8 @@ class FCDrillMove(FCShapeTool):
dia_on_row = self.draw_app.tools_table_exc.item(row, 1).text()
self.selected_dia_list.append(float(dia_on_row))
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
@ -1156,8 +1211,8 @@ class FCDrillMove(FCShapeTool):
sel_shapes_to_be_deleted = []
self.draw_app.build_ui()
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Drill(s) Move completed."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Drill(s) Move completed."))
self.draw_app.app.jump_signal.disconnect()
def selection_bbox(self):
geo_list = []
@ -1212,6 +1267,16 @@ class FCDrillMove(FCShapeTool):
ss_el = None
return DrawToolUtilityShape(ss_el)
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.tools_table_exc.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCDrillCopy(FCDrillMove):
def __init__(self, draw_app):
@ -1254,8 +1319,18 @@ class FCDrillCopy(FCDrillMove):
sel_shapes_to_be_deleted = []
self.draw_app.build_ui()
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Drill(s) copied."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Drill(s) copied."))
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.tools_table_exc.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCDrillSelect(DrawTool):
@ -2919,6 +2994,11 @@ class FlatCAMExcEditor(QtCore.QObject):
except (TypeError, AttributeError):
pass
try:
self.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
def clear(self):
self.active_tool = None
# self.shape_buffer = []
@ -3690,6 +3770,7 @@ class FlatCAMExcEditor(QtCore.QObject):
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color=self.app.cursor_color_3D,
edge_width=self.app.defaults["global_cursor_width"],
size=self.app.defaults["global_cursor_size"])
self.snap_x = x
@ -3709,12 +3790,7 @@ class FlatCAMExcEditor(QtCore.QObject):
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
# ## Utility geometry (animated)
geo = self.active_tool.utility_geometry(data=(x, y))
if isinstance(geo, DrawToolShape) and geo.geo is not None:
# Remove any previous utility shape
self.tool_shape.clear(update=True)
self.draw_utility_geometry(geo=geo)
self.update_utility_geometry(data=(x, y))
# ## Selection area on canvas section # ##
if event_is_dragging == 1 and event.button == 1:
@ -3739,8 +3815,17 @@ class FlatCAMExcEditor(QtCore.QObject):
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color=self.app.cursor_color_3D,
edge_width=self.app.defaults["global_cursor_width"],
size=self.app.defaults["global_cursor_size"])
def update_utility_geometry(self, data):
# ### Utility geometry (animated) ###
geo = self.active_tool.utility_geometry(data=data)
if isinstance(geo, DrawToolShape) and geo.geo is not None:
# Remove any previous utility shape
self.tool_shape.clear(update=True)
self.draw_utility_geometry(geo=geo)
def on_canvas_key_release(self, event):
self.key = None

View File

@ -1883,6 +1883,7 @@ class DrawTool(object):
# Jump to coords
if key == QtCore.Qt.Key_J or key == 'J':
self.draw_app.app.on_jump_to()
return
def utility_geometry(self, data=None):
return None
@ -1988,6 +1989,15 @@ class FCCircle(FCShapeTool):
self.draw_app.app.inform.emit('[success] %s' % _("Done. Adding Circle completed."))
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCArc(FCShapeTool):
def __init__(self, draw_app):
@ -2213,6 +2223,15 @@ class FCArc(FCShapeTool):
self.draw_app.app.inform.emit('[success] %s' % _("Done. Arc completed."))
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCRectangle(FCShapeTool):
"""
@ -2271,6 +2290,15 @@ class FCRectangle(FCShapeTool):
self.draw_app.app.jump_signal.disconnect()
self.draw_app.app.inform.emit('[success] %s' % _("Done. Rectangle completed."))
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCPolygon(FCShapeTool):
"""
@ -2345,6 +2373,15 @@ class FCPolygon(FCShapeTool):
self.draw_app.draw_utility_geometry(geo=geo)
return _("Backtracked one point ...")
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCPath(FCPolygon):
"""
@ -2401,6 +2438,15 @@ class FCPath(FCPolygon):
self.draw_app.draw_utility_geometry(geo=geo)
return _("Backtracked one point ...")
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCSelect(DrawTool):
def __init__(self, draw_app):
@ -2533,6 +2579,15 @@ class FCExplode(FCShapeTool):
self.draw_app.on_shape_complete()
self.draw_app.app.inform.emit('[success] %s...' % _("Done. Polygons exploded into lines."))
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCMove(FCShapeTool):
def __init__(self, draw_app):
@ -2555,8 +2610,10 @@ class FCMove(FCShapeTool):
if len(self.draw_app.get_selected()) == 0:
self.draw_app.app.inform.emit('[WARNING_NOTCL] %s...' %
_("MOVE: No shape selected. Select a shape to move"))
return
else:
self.draw_app.app.inform.emit(_(" MOVE: Click on reference point ..."))
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
def set_origin(self, origin):
self.draw_app.app.inform.emit(_(" Click on destination point ..."))
@ -2593,8 +2650,8 @@ class FCMove(FCShapeTool):
# Delete old
self.draw_app.delete_selected()
self.complete = True
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Geometry(s) Move completed."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Geometry(s) Move completed."))
self.draw_app.app.jump_signal.disconnect()
def selection_bbox(self):
geo_list = []
@ -2701,6 +2758,15 @@ class FCMove(FCShapeTool):
log.error("[ERROR] Something went bad. %s" % str(e))
raise
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCCopy(FCMove):
def __init__(self, draw_app):
@ -2715,6 +2781,16 @@ class FCCopy(FCMove):
for geom in self.draw_app.get_selected()]
self.complete = True
self.draw_app.app.inform.emit('[success] %s' % _("Done. Geometry(s) Copy completed."))
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCText(FCShapeTool):
@ -2732,11 +2808,12 @@ class FCText(FCShapeTool):
self.app = draw_app.app
self.draw_app.app.inform.emit(_("Click on 1st corner ..."))
self.draw_app.app.inform.emit(_("Click on 1st point ..."))
self.origin = (0, 0)
self.text_gui = TextInputTool(self.app)
self.text_gui.run()
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
def click(self, point):
# Create new geometry
@ -2754,9 +2831,11 @@ class FCText(FCShapeTool):
self.text_gui.text_path = []
self.text_gui.hide_tool()
self.draw_app.select_tool('select')
self.draw_app.app.jump_signal.disconnect()
return
else:
self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' % _("No text to add."))
self.draw_app.app.jump_signal.disconnect()
return
self.text_gui.text_path = []
@ -2780,6 +2859,15 @@ class FCText(FCShapeTool):
except Exception:
return
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCBuffer(FCShapeTool):
def __init__(self, draw_app):
@ -2909,6 +2997,16 @@ class FCBuffer(FCShapeTool):
self.draw_app.select_tool("select")
self.buff_tool.hide_tool()
def clean_up(self):
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCEraser(FCShapeTool):
def __init__(self, draw_app):
@ -2931,6 +3029,7 @@ class FCEraser(FCShapeTool):
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
def set_origin(self, origin):
self.origin = origin
@ -2982,8 +3081,8 @@ class FCEraser(FCShapeTool):
self.draw_app.delete_utility_geometry()
self.draw_app.plot_all()
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Eraser tool action completed."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Eraser tool action completed."))
self.draw_app.app.jump_signal.disconnect()
def utility_geometry(self, data=None):
"""
@ -3013,9 +3112,14 @@ class FCEraser(FCShapeTool):
return DrawToolUtilityShape(geo_list)
def clean_up(self):
self.draw_app.selected = []
self.draw_app.selected = list()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCPaint(FCShapeTool):
def __init__(self, draw_app):
@ -3557,6 +3661,11 @@ class FlatCAMGeoEditor(QtCore.QObject):
except (TypeError, AttributeError):
pass
try:
self.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
def add_shape(self, shape):
"""
Adds a shape to the shape storage.
@ -3831,6 +3940,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color=self.app.cursor_color_3D,
edge_width=self.app.defaults["global_cursor_width"],
size=self.app.defaults["global_cursor_size"])
self.snap_x = x

View File

@ -240,6 +240,8 @@ class FCPad(FCShapeTool):
self.draw_app.app.inform.emit(_("Click to place ..."))
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
@ -378,13 +380,17 @@ class FCPad(FCShapeTool):
self.draw_app.in_action = False
self.complete = True
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Adding Pad completed."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Adding Pad completed."))
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCPadArray(FCShapeTool):
@ -464,6 +470,8 @@ class FCPadArray(FCShapeTool):
self.draw_app.app.inform.emit(_("Click on target location ..."))
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
@ -726,12 +734,16 @@ class FCPadArray(FCShapeTool):
_("Done. Pad Array added."))
self.draw_app.in_action = False
self.draw_app.array_frame.hide()
return
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCPoligonize(FCShapeTool):
@ -1077,6 +1089,10 @@ class FCRegion(FCShapeTool):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
def on_key(self, key):
# Jump to coords
@ -1190,6 +1206,10 @@ class FCTrack(FCRegion):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
def click(self, point):
self.draw_app.in_action = True
@ -1472,6 +1492,10 @@ class FCDisc(FCShapeTool):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCSemiDisc(FCShapeTool):
@ -1737,6 +1761,10 @@ class FCSemiDisc(FCShapeTool):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCScale(FCShapeTool):
@ -1921,6 +1949,8 @@ class FCApertureMove(FCShapeTool):
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
self.sel_limit = self.draw_app.app.defaults["gerber_editor_sel_limit"]
self.selection_shape = self.selection_bbox()
@ -2021,14 +2051,19 @@ class FCApertureMove(FCShapeTool):
self.draw_app.plot_all()
self.draw_app.build_ui()
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Apertures Move completed."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Apertures Move completed."))
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
def utility_geometry(self, data=None):
"""
Temporary geometry on screen while using this tool.
@ -2098,8 +2133,8 @@ class FCApertureCopy(FCApertureMove):
sel_shapes_to_be_deleted = []
self.draw_app.build_ui()
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Apertures copied."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Apertures copied."))
self.draw_app.app.jump_signal.disconnect()
class FCEraser(FCShapeTool):
@ -2130,6 +2165,8 @@ class FCEraser(FCShapeTool):
# Switch notebook to Selected page
self.draw_app.app.ui.notebook.setCurrentWidget(self.draw_app.app.ui.selected_tab)
self.draw_app.app.jump_signal.connect(lambda x: self.draw_app.update_utility_geometry(data=x))
self.sel_limit = self.draw_app.app.defaults["gerber_editor_sel_limit"]
def set_origin(self, origin):
@ -2206,13 +2243,17 @@ class FCEraser(FCShapeTool):
self.draw_app.delete_utility_geometry()
self.draw_app.plot_all()
self.draw_app.app.inform.emit('[success] %s' %
_("Done. Eraser tool action completed."))
self.draw_app.app.inform.emit('[success] %s' % _("Done. Eraser tool action completed."))
self.draw_app.app.jump_signal.disconnect()
def clean_up(self):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
def utility_geometry(self, data=None):
"""
@ -3760,6 +3801,11 @@ class FlatCAMGrbEditor(QtCore.QObject):
except (TypeError, AttributeError):
pass
try:
self.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
def clear(self):
self.active_tool = None
self.selected = []
@ -4543,6 +4589,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color=self.app.cursor_color_3D,
edge_width=self.app.defaults["global_cursor_width"],
size=self.app.defaults["global_cursor_size"])
self.snap_x = x

View File

@ -1211,23 +1211,13 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
self.pref_tab_bottom_layout_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.pref_tab_bottom_layout.addLayout(self.pref_tab_bottom_layout_1)
self.pref_import_button = QtWidgets.QPushButton()
self.pref_import_button.setText(_("Import Preferences"))
self.pref_import_button.setMinimumWidth(130)
self.pref_import_button.setToolTip(
_("Import a full set of FlatCAM settings from a file\n"
"previously saved on HDD.\n\n"
"FlatCAM automatically save a 'factory_defaults' file\n"
"on the first start. Do not delete that file."))
self.pref_tab_bottom_layout_1.addWidget(self.pref_import_button)
self.pref_export_button = QtWidgets.QPushButton()
self.pref_export_button.setText(_("Export Preferences"))
self.pref_export_button.setMinimumWidth(130)
self.pref_export_button.setToolTip(
_("Export a full set of FlatCAM settings in a file\n"
"that is saved on HDD."))
self.pref_tab_bottom_layout_1.addWidget(self.pref_export_button)
self.pref_defaults_button = QtWidgets.QPushButton()
self.pref_defaults_button.setText(_("Restore Defaults"))
self.pref_defaults_button.setMinimumWidth(130)
self.pref_defaults_button.setToolTip(
_("Restore the entire set of default values\n"
"to the initial values loaded after first launch."))
self.pref_tab_bottom_layout_1.addWidget(self.pref_defaults_button)
self.pref_open_button = QtWidgets.QPushButton()
self.pref_open_button.setText(_("Open Pref Folder"))
@ -1236,6 +1226,17 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
_("Open the folder where FlatCAM save the preferences files."))
self.pref_tab_bottom_layout_1.addWidget(self.pref_open_button)
# Clear Settings
self.clear_btn = FCButton('%s' % _('Clear GUI Settings'))
self.clear_btn.setMinimumWidth(130)
self.clear_btn.setToolTip(
_("Clear the GUI settings for FlatCAM,\n"
"such as: layout, gui state, style, hdpi support etc.")
)
self.pref_tab_bottom_layout_1.addWidget(self.clear_btn)
self.pref_tab_bottom_layout_2 = QtWidgets.QHBoxLayout()
self.pref_tab_bottom_layout_2.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.pref_tab_bottom_layout.addLayout(self.pref_tab_bottom_layout_2)
@ -2332,7 +2333,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
:param event: QT event to filter
:return:
"""
if self.general_defaults_form.general_gui_set_group.toggle_tooltips_cb.get_value() is False:
if self.general_defaults_form.general_app_set_group.toggle_tooltips_cb.get_value() is False:
if event.type() == QtCore.QEvent.ToolTip:
return True
else:
@ -3161,15 +3162,12 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
if key == QtCore.Qt.Key_Escape or key == 'Escape':
# TODO: ...?
# self.on_tool_select("select")
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Cancelled."))
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
self.app.geo_editor.delete_utility_geometry()
# deselect any shape that might be selected
self.app.geo_editor.selected = []
self.app.geo_editor.active_tool.clean_up()
self.app.geo_editor.replot()
self.app.geo_editor.select_tool('select')
# hide the notebook
@ -3207,6 +3205,25 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
if key == QtCore.Qt.Key_3 or key == '3':
self.app.on_select_tab('tool')
# Grid Snap
if key == QtCore.Qt.Key_G or key == 'G':
self.app.ui.grid_snap_btn.trigger()
# make sure that the cursor shape is enabled/disabled, too
if self.app.geo_editor.options['grid_snap'] is True:
self.app.app_cursor.enabled = True
else:
self.app.app_cursor.enabled = False
# Corner Snap
if key == QtCore.Qt.Key_K or key == 'K':
self.app.geo_editor.on_corner_snap()
if key == QtCore.Qt.Key_V or key == 'V':
self.app.on_zoom_fit(None)
# we do this so we can reuse the following keys while inside a Tool
# the above keys are general enough so were left outside
if self.app.geo_editor.active_tool is not None and self.geo_select_btn.isChecked() is False:
response = self.app.geo_editor.active_tool.on_key(key=key)
if response is not None:
@ -3240,16 +3257,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
messagebox.setDefaultButton(QtWidgets.QMessageBox.Ok)
messagebox.exec_()
# Grid Snap
if key == QtCore.Qt.Key_G or key == 'G':
self.app.ui.grid_snap_btn.trigger()
# make sure that the cursor shape is enabled/disabled, too
if self.app.geo_editor.options['grid_snap'] is True:
self.app.app_cursor.enabled = True
else:
self.app.app_cursor.enabled = False
# Paint
if key == QtCore.Qt.Key_I or key == 'I':
self.app.geo_editor.select_tool('paint')
@ -3258,10 +3265,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
if key == QtCore.Qt.Key_J or key == 'J':
self.app.on_jump_to()
# Corner Snap
if key == QtCore.Qt.Key_K or key == 'K':
self.app.geo_editor.on_corner_snap()
# Move
if key == QtCore.Qt.Key_M or key == 'M':
self.app.geo_editor.on_move_click()
@ -3319,9 +3322,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
messagebox.setDefaultButton(QtWidgets.QMessageBox.Ok)
messagebox.exec_()
if key == QtCore.Qt.Key_V or key == 'V':
self.app.on_zoom_fit(None)
# Flip on X axis
if key == QtCore.Qt.Key_X or key == 'X':
self.app.geo_editor.transform_tool.on_flipx()
@ -3351,7 +3351,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
if key == QtCore.Qt.Key_M or key == 'M':
self.app.distance_tool.run()
return
elif modifiers == QtCore.Qt.ShiftModifier:
# Run Distance Minimum Tool
if key == QtCore.Qt.Key_M or key == 'M':
@ -3579,7 +3578,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
if key == QtCore.Qt.Key_M or key == 'M':
self.app.distance_tool.run()
return
elif modifiers == QtCore.Qt.ShiftModifier:
# Run Distance Minimum Tool
if key == QtCore.Qt.Key_M or key == 'M':
@ -3590,15 +3588,12 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
elif modifiers == QtCore.Qt.NoModifier:
# Abort the current action
if key == QtCore.Qt.Key_Escape or key == 'Escape':
# TODO: ...?
# self.on_tool_select("select")
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
self.app.exc_editor.delete_utility_geometry()
self.app.exc_editor.replot()
# self.select_btn.setChecked(True)
# self.on_tool_select('select')
self.app.exc_editor.active_tool.clean_up()
self.app.exc_editor.select_tool('drill_select')
return
@ -3655,44 +3650,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
self.app.on_select_tab('tool')
return
# Add Array of Drill Hole Tool
if key == QtCore.Qt.Key_A or key == 'A':
self.app.exc_editor.launched_from_shortcuts = True
self.app.inform.emit("Click on target point.")
self.app.ui.add_drill_array_btn.setChecked(True)
self.app.exc_editor.x = self.app.mouse[0]
self.app.exc_editor.y = self.app.mouse[1]
self.app.exc_editor.select_tool('drill_array')
return
# Copy
if key == QtCore.Qt.Key_C or key == 'C':
self.app.exc_editor.launched_from_shortcuts = True
if self.app.exc_editor.selected:
self.app.inform.emit(_("Click on target point."))
self.app.ui.copy_drill_btn.setChecked(True)
self.app.exc_editor.on_tool_select('drill_copy')
self.app.exc_editor.active_tool.set_origin(
(self.app.exc_editor.snap_x, self.app.exc_editor.snap_y))
else:
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Cancelled. Nothing selected to copy."))
return
# Add Drill Hole Tool
if key == QtCore.Qt.Key_D or key == 'D':
self.app.exc_editor.launched_from_shortcuts = True
self.app.inform.emit(_("Click on target point."))
self.app.ui.add_drill_btn.setChecked(True)
self.app.exc_editor.x = self.app.mouse[0]
self.app.exc_editor.y = self.app.mouse[1]
self.app.exc_editor.select_tool('drill_add')
return
# Grid Snap
if key == QtCore.Qt.Key_G or key == 'G':
self.app.exc_editor.launched_from_shortcuts = True
@ -3704,69 +3661,12 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
self.app.ui.grid_snap_btn.trigger()
return
# Jump to coords
if key == QtCore.Qt.Key_J or key == 'J':
self.app.on_jump_to()
# Corner Snap
if key == QtCore.Qt.Key_K or key == 'K':
self.app.exc_editor.launched_from_shortcuts = True
self.app.ui.corner_snap_btn.trigger()
return
# Move
if key == QtCore.Qt.Key_M or key == 'M':
self.app.exc_editor.launched_from_shortcuts = True
if self.app.exc_editor.selected:
self.app.inform.emit(_("Click on target point."))
self.app.ui.move_drill_btn.setChecked(True)
self.app.exc_editor.on_tool_select('drill_move')
self.app.exc_editor.active_tool.set_origin(
(self.app.exc_editor.snap_x, self.app.exc_editor.snap_y))
else:
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Cancelled. Nothing selected to move."))
return
# Add Array of Slote Hole Tool
if key == QtCore.Qt.Key_Q or key == 'Q':
self.app.exc_editor.launched_from_shortcuts = True
self.app.inform.emit("Click on target point.")
self.app.ui.add_slot_array_btn.setChecked(True)
self.app.exc_editor.x = self.app.mouse[0]
self.app.exc_editor.y = self.app.mouse[1]
self.app.exc_editor.select_tool('slot_array')
return
# Resize Tool
if key == QtCore.Qt.Key_R or key == 'R':
self.app.exc_editor.launched_from_shortcuts = True
self.app.exc_editor.select_tool('drill_resize')
return
# Add Tool
if key == QtCore.Qt.Key_T or key == 'T':
self.app.exc_editor.launched_from_shortcuts = True
# ## Current application units in Upper Case
self.units = self.general_defaults_form.general_app_group.units_radio.get_value().upper()
tool_add_popup = FCInputDialog(title=_("New Tool ..."),
text='%s:' % _('Enter a Tool Diameter'),
min=0.0000, max=99.9999, decimals=4)
tool_add_popup.setWindowIcon(QtGui.QIcon(self.app.resource_location + '/letter_t_32.png'))
val, ok = tool_add_popup.get_value()
if ok:
self.app.exc_editor.on_tool_add(tooldia=val)
formated_val = '%.*f' % (self.decimals, float(val))
self.app.inform.emit(
'[success] %s: %s %s' % (_("Added new tool with dia"), formated_val, str(self.units))
)
else:
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Adding Tool cancelled ..."))
return
# Zoom Fit
if key == QtCore.Qt.Key_V or key == 'V':
self.app.exc_editor.launched_from_shortcuts = True
@ -3787,15 +3687,113 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
# Propagate to tool
response = None
if self.app.exc_editor.active_tool is not None:
response = self.app.exc_editor.active_tool.on_key(key=key)
if response is not None:
self.app.inform.emit(response)
# Show Shortcut list
if key == QtCore.Qt.Key_F3 or key == 'F3':
self.app.on_shortcut_list()
return
# we do this so we can reuse the following keys while inside a Tool
# the above keys are general enough so were left outside
if self.app.exc_editor.active_tool is not None and self.select_drill_btn.isChecked() is False:
response = self.app.exc_editor.active_tool.on_key(key=key)
if response is not None:
self.app.inform.emit(response)
else:
# Add Array of Drill Hole Tool
if key == QtCore.Qt.Key_A or key == 'A':
self.app.exc_editor.launched_from_shortcuts = True
self.app.inform.emit("Click on target point.")
self.app.ui.add_drill_array_btn.setChecked(True)
self.app.exc_editor.x = self.app.mouse[0]
self.app.exc_editor.y = self.app.mouse[1]
self.app.exc_editor.select_tool('drill_array')
return
# Copy
if key == QtCore.Qt.Key_C or key == 'C':
self.app.exc_editor.launched_from_shortcuts = True
if self.app.exc_editor.selected:
self.app.inform.emit(_("Click on target point."))
self.app.ui.copy_drill_btn.setChecked(True)
self.app.exc_editor.on_tool_select('drill_copy')
self.app.exc_editor.active_tool.set_origin(
(self.app.exc_editor.snap_x, self.app.exc_editor.snap_y))
else:
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Cancelled. Nothing selected to copy."))
return
# Add Drill Hole Tool
if key == QtCore.Qt.Key_D or key == 'D':
self.app.exc_editor.launched_from_shortcuts = True
self.app.inform.emit(_("Click on target point."))
self.app.ui.add_drill_btn.setChecked(True)
self.app.exc_editor.x = self.app.mouse[0]
self.app.exc_editor.y = self.app.mouse[1]
self.app.exc_editor.select_tool('drill_add')
return
# Jump to coords
if key == QtCore.Qt.Key_J or key == 'J':
self.app.on_jump_to()
# Move
if key == QtCore.Qt.Key_M or key == 'M':
self.app.exc_editor.launched_from_shortcuts = True
if self.app.exc_editor.selected:
self.app.inform.emit(_("Click on target point."))
self.app.ui.move_drill_btn.setChecked(True)
self.app.exc_editor.on_tool_select('drill_move')
self.app.exc_editor.active_tool.set_origin(
(self.app.exc_editor.snap_x, self.app.exc_editor.snap_y))
else:
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Cancelled. Nothing selected to move."))
return
# Add Array of Slots Hole Tool
if key == QtCore.Qt.Key_Q or key == 'Q':
self.app.exc_editor.launched_from_shortcuts = True
self.app.inform.emit("Click on target point.")
self.app.ui.add_slot_array_btn.setChecked(True)
self.app.exc_editor.x = self.app.mouse[0]
self.app.exc_editor.y = self.app.mouse[1]
self.app.exc_editor.select_tool('slot_array')
return
# Resize Tool
if key == QtCore.Qt.Key_R or key == 'R':
self.app.exc_editor.launched_from_shortcuts = True
self.app.exc_editor.select_tool('drill_resize')
return
# Add Tool
if key == QtCore.Qt.Key_T or key == 'T':
self.app.exc_editor.launched_from_shortcuts = True
# ## Current application units in Upper Case
self.units = self.general_defaults_form.general_app_group.units_radio.get_value().upper()
tool_add_popup = FCInputDialog(title=_("New Tool ..."),
text='%s:' % _('Enter a Tool Diameter'),
min=0.0000, max=99.9999, decimals=4)
tool_add_popup.setWindowIcon(QtGui.QIcon(self.app.resource_location + '/letter_t_32.png'))
val, ok = tool_add_popup.get_value()
if ok:
self.app.exc_editor.on_tool_add(tooldia=val)
formated_val = '%.*f' % (self.decimals, float(val))
self.app.inform.emit(
'[success] %s: %s %s' % (_("Added new tool with dia"), formated_val, str(self.units))
)
else:
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Adding Tool cancelled ..."))
return
elif self.app.call_source == 'measurement':
if modifiers == QtCore.Qt.ControlModifier:
pass

View File

@ -310,6 +310,7 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
# Update cursor
self.fcapp.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
symbol='++', edge_color=self.fcapp.cursor_color_3D,
edge_width=self.fcapp.defaults["global_cursor_width"],
size=self.fcapp.defaults["global_cursor_size"])
def new_text_group(self, collection=None):

View File

@ -375,16 +375,19 @@ class PlotCanvasLegacy(QtCore.QObject):
pass
# log.debug("Cache updated the screen!")
def new_cursor(self, axes=None, big=None):
def new_cursor(self, axes=None, big=None, color=None):
# if axes is None:
# c = MplCursor(axes=self.axes, color='black', linewidth=1)
# else:
# c = MplCursor(axes=axes, color='black', linewidth=1)
if self.app.defaults['global_theme'] == 'white':
color = '#000000'
if color:
color = color
else:
color = '#FFFFFF'
if self.app.defaults['global_theme'] == 'white':
color = '#000000'
else:
color = '#FFFFFF'
if big is True:
self.big_cursor = True
@ -398,20 +401,25 @@ class PlotCanvasLegacy(QtCore.QObject):
return c
def draw_cursor(self, x_pos, y_pos):
def draw_cursor(self, x_pos, y_pos, color=None):
"""
Draw a cursor at the mouse grid snapped position
:param x_pos: mouse x position
:param y_pos: mouse y position
:param color: custom color of the mouse
:return:
"""
# there is no point in drawing mouse cursor when panning as it jumps in a confusing way
if self.app.app_cursor.enabled is True and self.panning is False:
if self.app.defaults['global_theme'] == 'white':
color = '#000000'
if color:
color = color
else:
color = '#FFFFFF'
if self.app.defaults['global_theme'] == 'white':
color = '#000000'
else:
color = '#FFFFFF'
if self.big_cursor is False:
try:
@ -421,10 +429,11 @@ class PlotCanvasLegacy(QtCore.QObject):
# The size of the cursor is multiplied by 1.65 because that value made the cursor similar with the
# one in the OpenGL(3D) graphic engine
pointer_size = int(float(self.app.defaults["global_cursor_size"] ) * 1.65)
elements = self.axes.plot(x, y, '+', color=color, ms=pointer_size, mew=1, animated=True)
elements = self.axes.plot(x, y, '+', color=color, ms=pointer_size,
mew=self.app.defaults["global_cursor_width"], animated=True)
for el in elements:
self.axes.draw_artist(el)
except Exception as e:
except Exception:
# this happen at app initialization since self.app.geo_editor does not exist yet
# I could reshuffle the object instantiating order but what's the point?
# I could crash something else and that's pythonic, too
@ -439,7 +448,10 @@ class PlotCanvasLegacy(QtCore.QObject):
def clear_cursor(self, state):
if state is True:
self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1])
if self.app.defaults["global_cursor_color_enabled"] is True:
self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1], color=self.app.cursor_color_3D)
else:
self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1])
else:
if self.big_cursor is True:
self.ch_line.remove()
@ -784,7 +796,10 @@ class PlotCanvasLegacy(QtCore.QObject):
self.panning = False
# And update the cursor
self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1])
if self.app.defaults["global_cursor_color_enabled"] is True:
self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1], color=self.app.cursor_color_3D)
else:
self.draw_cursor(x_pos=self.mouse[0], y_pos=self.mouse[1])
def on_mouse_move(self, event):
"""
@ -818,8 +833,10 @@ class PlotCanvasLegacy(QtCore.QObject):
# #### Temporary place-holder for cached update #####
self.update_screen_request.emit([0, 0, 0, 0, 0])
self.draw_cursor(x_pos=x, y_pos=y)
if self.app.defaults["global_cursor_color_enabled"] is True:
self.draw_cursor(x_pos=x, y_pos=y, color=self.app.cursor_color_3D)
else:
self.draw_cursor(x_pos=x, y_pos=y)
# self.canvas.blit(self.axes.bbox)
def translate_coords(self, position):
@ -891,6 +908,7 @@ class FakeCursor(QtCore.QObject):
def set_data(self, pos, **kwargs):
"""Internal event handler to draw the cursor when the mouse moves."""
return
class ShapeCollectionLegacy:

File diff suppressed because it is too large Load Diff

View File

@ -50,7 +50,7 @@ def apply_patches():
try:
self._update_child_widget_dim()
except Exception as e:
print(e)
print("VisPyPatches.apply_patches._update_clipper() -> %s" % str(e))
Grid._prepare_draw = _prepare_draw
Grid._update_clipper = _update_clipper
@ -72,7 +72,7 @@ def apply_patches():
if GL:
GL.glDisable(GL.GL_LINE_SMOOTH)
GL.glLineWidth(1.0)
GL.glLineWidth(2.0)
if self._changed['pos']:
self.pos_buf.set_data(self._pos)

View File

@ -437,18 +437,20 @@ class Gerber(Geometry):
gline = gline.strip(' \r\n')
# log.debug("Line=%3s %s" % (line_num, gline))
# ###################
# Ignored lines #####
# Comments #####
# ###################
# ###############################################################
# ################ Ignored lines ############################
# ################ Comments ############################
# ###############################################################
match = self.comm_re.search(gline)
if match:
continue
# Polarity change ###### ##
# Example: %LPD*% or %LPC*%
# If polarity changes, creates geometry from current
# buffer, then adds or subtracts accordingly.
# ###############################################################
# ################ Polarity change #############################
# ######## Example: %LPD*% or %LPC*% ###################
# ######## If polarity changes, creates geometry from current #
# ######## buffer, then adds or subtracts accordingly. #
# ###############################################################
match = self.lpol_re.search(gline)
if match:
new_polarity = match.group(1)
@ -491,11 +493,9 @@ class Gerber(Geometry):
# TODO: Remove when bug fixed
if len(poly_buffer) > 0:
if current_polarity == 'D':
# self.follow_geometry = self.follow_geometry.union(cascaded_union(follow_buffer))
self.solid_geometry = self.solid_geometry.union(cascaded_union(poly_buffer))
else:
# self.follow_geometry = self.follow_geometry.difference(cascaded_union(follow_buffer))
self.solid_geometry = self.solid_geometry.difference(cascaded_union(poly_buffer))
# follow_buffer = []
@ -504,11 +504,11 @@ class Gerber(Geometry):
current_polarity = new_polarity
continue
# ############################################################# ##
# Number format ############################################### ##
# Example: %FSLAX24Y24*%
# ############################################################# ##
# TODO: This is ignoring most of the format. Implement the rest.
# ################################################################
# ##################### Number format ###########################
# ##################### Example: %FSLAX24Y24*% #################
# ################################################################
match = self.fmt_re.search(gline)
if match:
absolute = {'A': 'Absolute', 'I': 'Relative'}[match.group(2)]
@ -524,8 +524,10 @@ class Gerber(Geometry):
log.debug("Gerber format found. Coordinates type = %s (Absolute or Relative)" % absolute)
continue
# ## Mode (IN/MM)
# Example: %MOIN*%
# ################################################################
# ######################## Mode (IN/MM) #######################
# ##################### Example: %MOIN*% #####################
# ################################################################
match = self.mode_re.search(gline)
if match:
self.units = match.group(1)
@ -535,9 +537,9 @@ class Gerber(Geometry):
self.conversion_done = True
continue
# ############################################################# ##
# Combined Number format and Mode --- Allegro does this ####### ##
# ############################################################# ##
# ################################################################
# Combined Number format and Mode --- Allegro does this ##########
# ################################################################
match = self.fmt_re_alt.search(gline)
if match:
absolute = {'A': 'Absolute', 'I': 'Relative'}[match.group(2)]
@ -558,9 +560,9 @@ class Gerber(Geometry):
self.conversion_done = True
continue
# ############################################################# ##
# Search for OrCAD way for having Number format
# ############################################################# ##
# ################################################################
# #### Search for OrCAD way for having Number format ########
# ################################################################
match = self.fmt_re_orcad.search(gline)
if match:
if match.group(1) is not None:
@ -587,9 +589,9 @@ class Gerber(Geometry):
self.conversion_done = True
continue
# ############################################################# ##
# Units (G70/1) OBSOLETE
# ############################################################# ##
# ################################################################
# ############ Units (G70/1) OBSOLETE ######################
# ################################################################
match = self.units_re.search(gline)
if match:
obs_gerber_units = {'0': 'IN', '1': 'MM'}[match.group(1)]
@ -599,21 +601,21 @@ class Gerber(Geometry):
self.conversion_done = True
continue
# ############################################################# ##
# Absolute/relative coordinates G90/1 OBSOLETE ######## ##
# ##################################################### ##
# ################################################################
# ##### Absolute/relative coordinates G90/1 OBSOLETE ###########
# ################################################################
match = self.absrel_re.search(gline)
if match:
absolute = {'0': "Absolute", '1': "Relative"}[match.group(1)]
log.warning("Gerber obsolete coordinates type found = %s (Absolute or Relative) " % absolute)
continue
# ############################################################# ##
# Aperture Macros ##################################### ##
# ################################################################
# Aperture Macros ################################################
# Having this at the beginning will slow things down
# but macros can have complicated statements than could
# be caught by other patterns.
# ############################################################# ##
# ################################################################
if current_macro is None: # No macro started yet
match = self.am1_re.search(gline)
# Start macro if match, else not an AM, carry on.
@ -640,18 +642,20 @@ class Gerber(Geometry):
self.aperture_macros[current_macro].append(gline)
continue
# ## Aperture definitions %ADD...
# ################################################################
# ############## Aperture definitions %ADD... #################
# ################################################################
match = self.ad_re.search(gline)
if match:
# log.info("Found aperture definition. Line %d: %s" % (line_num, gline))
self.aperture_parse(match.group(1), match.group(2), match.group(3))
continue
# ############################################################# ##
# Operation code alone ###################### ##
# Operation code alone, usually just D03 (Flash)
# ################################################################
# ################ Operation code alone #########################
# ########### Operation code alone, usually just D03 (Flash) ###
# self.opcode_re = re.compile(r'^D0?([123])\*$')
# ############################################################# ##
# ################################################################
match = self.opcode_re.search(gline)
if match:
current_operation_code = int(match.group(1))
@ -690,10 +694,10 @@ class Gerber(Geometry):
continue
# ############################################################# ##
# Tool/aperture change
# Example: D12*
# ############################################################# ##
# ################################################################
# ################ Tool/aperture change ########################
# ################ Example: D12* ########################
# ################################################################
match = self.tool_re.search(gline)
if match:
current_aperture = match.group(1)
@ -740,12 +744,11 @@ class Gerber(Geometry):
self.apertures[last_path_aperture]['geometry'].append(deepcopy(geo_dict))
path = [path[-1]]
continue
# ############################################################# ##
# G36* - Begin region
# ############################################################# ##
# ################################################################
# ################ G36* - Begin region ########################
# ################################################################
if self.regionon_re.search(gline):
if len(path) > 1:
# Take care of what is left in the path
@ -780,9 +783,9 @@ class Gerber(Geometry):
making_region = True
continue
# ############################################################# ##
# G37* - End region
# ############################################################# ##
# ################################################################
# ################ G37* - End region ########################
# ################################################################
if self.regionoff_re.search(gline):
making_region = False
@ -830,20 +833,27 @@ class Gerber(Geometry):
# --- Buffered ---
geo_dict = dict()
region_f = Polygon(path).exterior
if current_aperture in self.apertures:
buff_value = float(self.apertures[current_aperture]['size']) / 2.0
# region_geo = Polygon(path).buffer(buff_value, int(self.steps_per_circle))
region_geo = Polygon(path) # Sprint Layout Gerbers with ground fill are crashed with above
else:
region_geo = Polygon(path)
region_f = region_geo.exterior
if not region_f.is_empty:
follow_buffer.append(region_f)
geo_dict['follow'] = region_f
region_s = Polygon(path)
region_s = region_geo
if not region_s.is_valid:
region_s = region_s.buffer(0, int(self.steps_per_circle / 4))
region_s = region_s.buffer(0, int(self.steps_per_circle))
if not region_s.is_empty:
if self.app.defaults['gerber_simplification']:
poly_buffer.append(region_s.simplify(s_tol))
else:
poly_buffer.append(region_s)
if self.is_lpc is True:
geo_dict['clear'] = region_s
else:
@ -855,18 +865,22 @@ class Gerber(Geometry):
path = [[current_x, current_y]] # Start new path
continue
# ## G01/2/3* - Interpolation mode change
# Can occur along with coordinates and operation code but
# sometimes by itself (handled here).
# Example: G01*
# ################################################################
# ################ G01/2/3* - Interpolation mode change #########
# #### Can occur along with coordinates and operation code but ##
# #### sometimes by itself (handled here). #####################
# #### Example: G01* #####################
# ################################################################
match = self.interp_re.search(gline)
if match:
current_interpolation_mode = int(match.group(1))
continue
# ## G01 - Linear interpolation plus flashes
# Operation code (D0x) missing is deprecated... oh well I will support it.
# ################################################################
# ######### G01 - Linear interpolation plus flashes #############
# ######### Operation code (D0x) missing is deprecated #########
# REGEX: r'^(?:G0?(1))?(?:X(-?\d+))?(?:Y(-?\d+))?(?:D0([123]))?\*$'
# ################################################################
match = self.lin_re.search(gline)
if match:
# Dxx alone?
@ -1147,7 +1161,9 @@ class Gerber(Geometry):
# log.debug("Line_number=%3s X=%s Y=%s (%s)" % (line_num, linear_x, linear_y, gline))
continue
# ## G74/75* - Single or multiple quadrant arcs
# ################################################################
# ######### G74/75* - Single or multiple quadrant arcs ##########
# ################################################################
match = self.quad_re.search(gline)
if match:
if match.group(1) == '4':
@ -1156,9 +1172,12 @@ class Gerber(Geometry):
quadrant_mode = 'MULTI'
continue
# ## G02/3 - Circular interpolation
# 2-clockwise, 3-counterclockwise
# Ex. format: G03 X0 Y50 I-50 J0 where the X, Y coords are the coords of the End Point
# ################################################################
# ######### G02/3 - Circular interpolation #####################
# ######### 2-clockwise, 3-counterclockwise #####################
# ######### Ex. format: G03 X0 Y50 I-50 J0 where the #########
# ######### X, Y coords are the coords of the End Point #########
# ################################################################
match = self.circ_re.search(gline)
if match:
arcdir = [None, None, "cw", "ccw"]
@ -1339,12 +1358,16 @@ class Gerber(Geometry):
else:
log.warning("Invalid arc in line %d." % line_num)
# ## EOF
# ################################################################
# ######### EOF - END OF FILE ####################################
# ################################################################
match = self.eof_re.search(gline)
if match:
continue
# ## Line did not match any pattern. Warn user.
# ################################################################
# ######### Line did not match any pattern. Warn user. ##########
# ################################################################
log.warning("Line ignored (%d): %s" % (line_num, gline))
if len(path) > 1:
@ -1433,16 +1456,16 @@ class Gerber(Geometry):
self.solid_geometry = final_poly
# FIX for issue #347 - Sprint Layout generate strange Gerber files when the copper pour is enabled
# FIX for issue #347 - Sprint Layout generate Gerber files when the copper pour is enabled
# it use a filled bounding box polygon to which add clear polygons (negative) to isolate the copper
# features
if self.app.defaults['gerber_extra_buffering']:
candidate_geo = list()
try:
for p in self.solid_geometry:
candidate_geo.append(p.buffer(0.0000001))
candidate_geo.append(p.buffer(-0.0000001))
except TypeError:
candidate_geo.append(self.solid_geometry.buffer(0.0000001))
candidate_geo.append(self.solid_geometry.buffer(-0.0000001))
self.solid_geometry = candidate_geo
# try:

View File

@ -902,6 +902,7 @@ class ToolCopperThieving(FlatCAMTool):
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color=self.app.cursor_color_3D,
edge_width=self.app.defaults["global_cursor_width"],
size=self.app.defaults["global_cursor_size"])
# update the positions on status bar

View File

@ -396,6 +396,7 @@ class Distance(FlatCAMTool):
# Update cursor
self.app.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
symbol='++', edge_color=self.app.cursor_color_3D,
edge_width=self.app.defaults["global_cursor_width"],
size=self.app.defaults["global_cursor_size"])
else:
pos = (pos_canvas[0], pos_canvas[1])

View File

@ -698,11 +698,11 @@ class NonCopperClear(FlatCAMTool, Gerber):
"paintcontour": self.app.defaults["tools_paintcontour"],
"paintoverlap": self.app.defaults["tools_paintoverlap"],
"nccoverlap": self.app.defaults["tools_nccoverlap"],
"nccmargin": self.app.defaults["tools_nccmargin"],
"nccmethod": self.app.defaults["tools_nccmethod"],
"nccconnect": self.app.defaults["tools_nccconnect"],
"ncccontour": self.app.defaults["tools_ncccontour"],
"nccoverlap": self.app.defaults["tools_nccoverlap"],
"nccrest": self.app.defaults["tools_nccrest"]
})
@ -1349,6 +1349,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color=self.app.cursor_color_3D,
edge_width=self.app.defaults["global_cursor_width"],
size=self.app.defaults["global_cursor_size"])
# update the positions on status bar

View File

@ -1290,6 +1290,7 @@ class ToolPaint(FlatCAMTool, Gerber):
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color=self.app.cursor_color_3D,
edge_width=self.app.defaults["global_cursor_width"],
size=self.app.defaults["global_cursor_size"])
# update the positions on status bar

View File

@ -608,22 +608,22 @@ class Panelize(FlatCAMTool):
if panel_obj.multigeo is True:
for tool in panel_obj.tools:
try:
for pol in panel_obj.tools[tool]['solid_geometry']:
geo_len += 1
geo_len += len(panel_obj.tools[tool]['solid_geometry'])
except TypeError:
geo_len = 1
geo_len += 1
else:
try:
for pol in panel_obj.solid_geometry:
geo_len += 1
geo_len = len(panel_obj.solid_geometry)
except TypeError:
geo_len = 1
elif isinstance(panel_obj, FlatCAMGerber):
for ap in panel_obj.apertures:
for elem in panel_obj.apertures[ap]['geometry']:
geo_len += 1
if 'geometry' in panel_obj.apertures[ap]:
try:
geo_len += len(panel_obj.apertures[ap]['geometry'])
except TypeError:
geo_len += 1
self.app.progress.emit(0)
element = 0
for row in range(rows):
currentx = 0.0
@ -724,49 +724,48 @@ class Panelize(FlatCAMTool):
if self.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
if 'geometry' in panel_obj.apertures[apid]:
try:
# calculate the number of polygons
geo_len = len(panel_obj.apertures[apid]['geometry'])
except TypeError:
geo_len = 1
pol_nr = 0
for el in panel_obj.apertures[apid]['geometry']:
if self.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
try:
# calculate the number of polygons
geo_len = len(panel_obj.apertures[apid]['geometry'])
except TypeError:
geo_len = 1
pol_nr = 0
for el in panel_obj.apertures[apid]['geometry']:
if self.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
new_el = dict()
if 'solid' in el:
geo_aper = translate_recursion(el['solid'])
new_el['solid'] = geo_aper
new_el = dict()
if 'solid' in el:
geo_aper = translate_recursion(el['solid'])
new_el['solid'] = geo_aper
if 'clear' in el:
geo_aper = translate_recursion(el['clear'])
new_el['clear'] = geo_aper
if 'clear' in el:
geo_aper = translate_recursion(el['clear'])
new_el['clear'] = geo_aper
if 'follow' in el:
geo_aper = translate_recursion(el['follow'])
new_el['follow'] = geo_aper
if 'follow' in el:
geo_aper = translate_recursion(el['follow'])
new_el['follow'] = geo_aper
obj_fin.apertures[apid]['geometry'].append(deepcopy(new_el))
obj_fin.apertures[apid]['geometry'].append(deepcopy(new_el))
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
if old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %s: %d %d%%' %
(_("Copy"),
int(element),
disp_number))
old_disp_number = disp_number
if old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %s: %d %d%%' %
(_("Copy"),
int(element),
disp_number))
old_disp_number = disp_number
currentx += lenghtx
currenty += lenghty
if panel_type == 'gerber':
self.app.inform.emit('%s' %
_("Generating panel ... Adding the Gerber code."))
self.app.inform.emit('%s' % _("Generating panel ... Adding the Gerber code."))
obj_fin.source_file = self.app.export_gerber(obj_name=self.outname, filename=None,
local_use=obj_fin, use_thread=False)
@ -777,15 +776,11 @@ class Panelize(FlatCAMTool):
# app_obj.log.debug("Finished creating a cascaded union for the panel.")
self.app.proc_container.update_view_text('')
self.app.inform.emit('%s: %d' %
(_("Generating panel... Spawning copies"), (int(rows * columns))))
self.app.inform.emit('%s: %d' % (_("Generating panel... Spawning copies"), (int(rows * columns))))
if isinstance(panel_obj, FlatCAMExcellon):
self.app.progress.emit(50)
self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True)
else:
self.app.progress.emit(50)
self.app.new_object(panel_type, self.outname, job_init_geometry,
plot=True, autoselected=True)
self.app.new_object(panel_type, self.outname, job_init_geometry, plot=True, autoselected=True)
if self.constrain_flag is False:
self.app.inform.emit('[success] %s' % _("Panel done..."))

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 618 B

After

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 595 B

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

Some files were not shown because too many files have changed in this diff Show More