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

This commit is contained in:
Camellan 2019-09-22 18:50:17 +04:00
commit 71d93d73bb
54 changed files with 44337 additions and 39532 deletions

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ from datetime import datetime
from flatcamGUI.ObjectUI import *
from FlatCAMCommon import LoudDict
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
from camlib import *
import itertools
@ -74,10 +75,17 @@ class FlatCAMObj(QtCore.QObject):
# store here the default data for Geometry Data
self.default_data = {}
# 2D mode
# Axes must exist and be attached to canvas.
self.axes = None
self.kind = None # Override with proper name
# self.shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene)
self.shapes = self.app.plotcanvas.new_shape_group()
if self.app.is_legacy is False:
self.shapes = self.app.plotcanvas.new_shape_group()
else:
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app)
# self.mark_shapes = self.app.plotcanvas.new_shape_collection(layers=2)
self.mark_shapes = {}
@ -391,11 +399,12 @@ class FlatCAMObj(QtCore.QObject):
def worker_task(app_obj):
self.shapes.visible = value
# Not all object types has annotations
try:
self.annotation.visible = value
except Exception as e:
pass
if self.app.is_legacy is False:
# Not all object types has annotations
try:
self.annotation.visible = value
except Exception as e:
pass
if threaded is False:
worker_task(app_obj=self.app)
@ -627,8 +636,13 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
self.ui.create_buffer_button.hide()
# add the shapes storage for marking apertures
for ap_code in self.apertures:
self.mark_shapes[ap_code] = self.app.plotcanvas.new_shape_collection(layers=2)
if self.app.is_legacy is False:
for ap_code in self.apertures:
self.mark_shapes[ap_code] = self.app.plotcanvas.new_shape_collection(layers=2)
else:
for ap_code in self.apertures:
self.mark_shapes[ap_code] = ShapeCollectionLegacy(obj=self, app=self.app,
name=self.options['name'] + str(ap_code))
# set initial state of the aperture table and associated widgets
self.on_aperture_table_visibility_change()
@ -1342,10 +1356,26 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
except TypeError:
geometry = [geometry]
def random_color():
color = np.random.rand(4)
color[3] = 1
return color
if self.app.is_legacy is False:
def random_color():
color = np.random.rand(4)
color[3] = 1
return color
else:
def random_color():
while True:
color = np.random.rand(4)
color[3] = 1
new_color = '#'
for idx in range(len(color)):
new_color += '%x' % int(color[idx] * 255)
# do it until a valid color is generated
# a valid color has the # symbol, another 6 chars for the color and the last 2 chars for alpha
# for a total of 9 chars
if len(new_color) == 9:
break
return new_color
try:
if self.options["solid"]:
@ -1380,11 +1410,14 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
self.shapes.redraw()
except (ObjectDeleted, AttributeError):
self.shapes.clear(update=True)
except Exception as e:
log.debug("FlatCAMGerber.plot() --> %s" % str(e))
# experimental plot() when the solid_geometry is stored in the self.apertures
def plot_aperture(self, **kwargs):
def plot_aperture(self, run_thread=True, **kwargs):
"""
:param run_thread: if True run the aperture plot as a thread in a worker
:param kwargs: color and face_color
:return:
"""
@ -1414,31 +1447,34 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
else:
visibility = kwargs['visible']
with self.app.proc_container.new(_("Plotting Apertures")) as proc:
with self.app.proc_container.new(_("Plotting Apertures")):
self.app.progress.emit(30)
def job_thread(app_obj):
self.app.progress.emit(30)
try:
if aperture_to_plot_mark in self.apertures:
for elem in self.apertures[aperture_to_plot_mark]['geometry']:
if 'solid' in elem:
geo = elem['solid']
if type(geo) == Polygon or type(geo) == LineString:
self.add_mark_shape(apid=aperture_to_plot_mark, shape=geo, color=color,
face_color=color, visible=visibility)
else:
for el in geo:
self.add_mark_shape(apid=aperture_to_plot_mark, shape=el, color=color,
geo = elem['solid']
if type(geo) == Polygon or type(geo) == LineString:
self.add_mark_shape(apid=aperture_to_plot_mark, shape=geo, color=color,
face_color=color, visible=visibility)
else:
for el in geo:
self.add_mark_shape(apid=aperture_to_plot_mark, shape=el, color=color,
face_color=color, visible=visibility)
self.mark_shapes[aperture_to_plot_mark].redraw()
self.app.progress.emit(100)
except (ObjectDeleted, AttributeError):
self.clear_plot_apertures()
except Exception as e:
print(str(e))
self.app.worker_task.emit({'fcn': job_thread, 'params': [self]})
if run_thread:
self.app.worker_task.emit({'fcn': job_thread, 'params': [self]})
else:
job_thread(self)
def clear_plot_apertures(self, aperture='all'):
"""
@ -1482,8 +1518,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
if self.ui.apertures_table.cellWidget(cw_row, 5).isChecked():
self.marked_rows.append(True)
# self.plot_aperture(color='#2d4606bf', marked_aperture=aperture, visible=True)
self.plot_aperture(color=self.app.defaults['global_sel_draw_color'], marked_aperture=aperture, visible=True)
self.mark_shapes[aperture].redraw()
self.plot_aperture(color=self.app.defaults['global_sel_draw_color'] + 'FF',
marked_aperture=aperture, visible=True, run_thread=True)
# self.mark_shapes[aperture].redraw()
else:
self.marked_rows.append(False)
self.clear_plot_apertures(aperture=aperture)
@ -1519,7 +1556,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
if mark_all:
for aperture in self.apertures:
# self.plot_aperture(color='#2d4606bf', marked_aperture=aperture, visible=True)
self.plot_aperture(color=self.app.defaults['global_sel_draw_color'],
self.plot_aperture(color=self.app.defaults['global_sel_draw_color'] + 'FF',
marked_aperture=aperture, visible=True)
# HACK: enable/disable the grid for a better look
self.app.ui.grid_snap_btn.trigger()
@ -5349,7 +5386,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
return factor
def plot_element(self, element, color='red', visible=None):
def plot_element(self, element, color='#FF0000FF', visible=None):
visible = visible if visible else self.options['plot']
@ -5358,8 +5395,10 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
self.plot_element(sub_el)
except TypeError: # Element is not iterable...
# if self.app.is_legacy is False:
self.add_shape(shape=element, color=color, visible=visible, layer=0)
def plot(self, visible=None, kind=None):
"""
Plot the object.
@ -5389,7 +5428,9 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
self.plot_element(self.solid_geometry, visible=visible)
# self.plot_element(self.solid_geometry, visible=self.options['plot'])
self.shapes.redraw()
except (ObjectDeleted, AttributeError):
self.shapes.clear(update=True)
@ -5551,9 +5592,10 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
# from predecessors.
self.ser_attrs += ['options', 'kind', 'cnc_tools', 'multitool']
self.text_col = self.app.plotcanvas.new_text_collection()
self.text_col.enabled = True
self.annotation = self.app.plotcanvas.new_text_group(collection=self.text_col)
if self.app.is_legacy is False:
self.text_col = self.app.plotcanvas.new_text_collection()
self.text_col.enabled = True
self.annotation = self.app.plotcanvas.new_text_group(collection=self.text_col)
def build_ui(self):
self.ui_disconnect()
@ -5728,8 +5770,9 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
pass
self.ui.annotation_cb.stateChanged.connect(self.on_annotation_change)
# set if to display text annotations
self.ui.annotation_cb.set_value(self.app.defaults["cncjob_annotation"])
if self.app.is_legacy is False:
# set if to display text annotations
self.ui.annotation_cb.set_value(self.app.defaults["cncjob_annotation"])
# Show/Hide Advanced Options
if self.app.defaults["global_app_level"] == 'b':
@ -6178,11 +6221,12 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
visible = visible if visible else self.options['plot']
if self.ui.annotation_cb.get_value() and self.ui.plot_cb.get_value():
self.text_col.enabled = True
else:
self.text_col.enabled = False
self.annotation.redraw()
if self.app.is_legacy is False:
if self.ui.annotation_cb.get_value() and self.ui.plot_cb.get_value():
self.text_col.enabled = True
else:
self.text_col.enabled = False
self.annotation.redraw()
try:
if self.multitool is False: # single tool usage
@ -6201,16 +6245,20 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
self.shapes.redraw()
except (ObjectDeleted, AttributeError):
self.shapes.clear(update=True)
self.annotation.clear(update=True)
if self.app.is_legacy is False:
self.annotation.clear(update=True)
def on_annotation_change(self):
if self.ui.annotation_cb.get_value():
self.text_col.enabled = True
if self.app.is_legacy is False:
if self.ui.annotation_cb.get_value():
self.text_col.enabled = True
else:
self.text_col.enabled = False
# kind = self.ui.cncplot_method_combo.get_value()
# self.plot(kind=kind)
self.annotation.redraw()
else:
self.text_col.enabled = False
# kind = self.ui.cncplot_method_combo.get_value()
# self.plot(kind=kind)
self.annotation.redraw()
self.inform.emit(_("Not available with the current Graphic Engine Legacy(2D)."))
def convert_units(self, units):
log.debug("FlatCAMObj.FlatCAMECNCjob.convert_units()")

View File

@ -16,6 +16,7 @@ from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import log
import gettext
# import builtins
#
# if '_' not in builtins.__dict__:
@ -154,12 +155,13 @@ def apply_language(domain, lang=None):
return name
def restart_program(app):
def restart_program(app, ask=None):
"""Restarts the current program.
Note: this function does not return. Any cleanup action (like
saving data) must be done before calling this function.
"""
if app.should_we_save and app.collection.get_list():
if app.should_we_save and app.collection.get_list() or ask is True:
msgbox = QtWidgets.QMessageBox()
msgbox.setText(_("There are files/objects modified in FlatCAM. "
"\n"

View File

@ -588,8 +588,8 @@ class ObjectCollection(QtCore.QAbstractItemModel):
self.app.all_objects_list = self.get_list()
self.endRemoveRows()
self.app.plotcanvas.redraw()
if self.app.is_legacy is False:
self.app.plotcanvas.redraw()
if select_project:
# always go to the Project Tab after object deletion as it may be done with a shortcut key

View File

@ -1,4 +1,4 @@
latCAM: 2D Computer-Aided PCB Manufacturing
FlatCAM: 2D Computer-Aided PCB Manufacturing
=================================================
(c) 2014-2019 Juan Pablo Caram
@ -9,6 +9,86 @@ CAD program, and create G-Code for Isolation routing.
=================================================
22.09.2019
- fixed zoom directions legacy graphic engine (previous commit)
- fixed display of MultiGeo geometries in legacy graphic engine
- fixed Paint tool to work in legacy graphic engine
- fixed CutOut Tool to work in legacy graphic engine
- fixed display of distance labels and code optimizations in ToolPaint and NCC Tool
- adjusted axis at startup for legacy graphic engine plotcanvas
- when the graphic engine is changed in Edit -> Preferences -> General -> App Preferences, the application will restart
- made hover shapes work in legacy graphic engine
- fixed bug in display of the apertures marked in the Aperture table found in the Gerber Selected tab and through this made it to also work with the legacy graphic engine
- fixed annotation in Mark Area Tool in Gerber Editor to work in legacy graphic engine
- fixed the MultiColor plot option Gerber selected tab to work in legacy graphic engine
- documented some methods in the ShapeCollectionLegacy class
- updated the files: setup_ubuntu.sh and requirements.txt
- some strings changed to be easier for translation
- updated the .POT file and the translation files
- updated and corrected the Romanian and Spanish translations
- updated the .PO files for the rest of the translations, they need to be filled in.
21.09.2019
- fixed Measuring Tool in legacy graphic engine
- fixed Gerber plotting in legacy graphic engine
- fixed Geometry plotting in legacy graphic engine
- fixed CNCJob and Excellon plotting in legacy graphic engine
- in legacy graphic engine fixed the travel vs cut lines in CNCJob objects
- final fix for key shortcuts with modifier in legacy graphic engine
- refactored some of the code in the legacy graphic engine
- fixed drawing of selection box when dragging mouse on screen and the selection shape drawing on the selected objects
- fixed the moving drawing shape in Tool Move in legacy graphic engine
- fixed moving geometry in Tool Measurement in legacy graphic engine
- fixed Geometry Editor to work in legacy graphic engine
- fixed Excellon Editor to work in legacy graphic engine
- fixed Gerber Editor to work in legacy graphic engine
- fixed NCC tool to work in legacy graphic engine
20.09.2019
- final fix for the --shellvar having spaces within the assigned value; now they are retained
- legacy graphic engine - made the mouse events work (click, release, doubleclick, dragging)
- legacy graphic engine - made the key events work (simple or with modifiers)
- legacy graphic engine - made the mouse cursor work (enabled/disabled, position report); snapping is not moving the cursor yet
- made the mouse cursor snap to the grid when grid snapping is active
- changed the axis color to the one used in the OpenGL graphic engine
- work on ShapeCollectionLegacy
- fixed mouse cursor to work for all objects
- fixed event signals to work in both graphic engines: 2D and 3D
19.09.2019
- made sure that if FlatCAM is registered with a file extension that it does not recognize it will exit
- added some fixes in the the file extension detection
- added some status messages for the Tcl script related methods
- made sure that optionally, when a script is run then it is also loaded into the code editor
- added control over the display of Sys Tray Icon in Edit -> Preferences -> General -> GUI Settings -> Sys Tray Icon checkbox
- updated some of the default values to more reasonable ones
- FlatCAM can be run in HEADLESS mode now. This mode can be selected by using the --headless=1 command line argument or by changing the line headless=False to True in config/configuration.txt file. In this mod the Sys Tray Icon menu will hold only the Run Scrip menu entry and Exit entry.
- added a new TclCommand named quit_flatcam which will ... quit FlatCAM from Tcl Shell or from a script
- fixed the command line argument --shellvar to work when there are spaces in the argument value
- fixed bug in Gerber editor that did not allow to display all shapes after it encountered one shape without 'solid' geometry
- fixed bug in Gerber Editor -> selection area handler where if some of the selected shapes did not had the 'solid' geometry will silently abort selection of further shapes
- added new control in Edit -> Preferences -> General -> Gui Preferences -> Activity Icon. Will select a GIF from a selection, the one used to show that FlatCAM is working.
- changed the script icon to a smaller one in the sys tray menu
- fixed bug with losing the visibility of toolbars if at first startup the user tries to change something in the Preferences before doing a first save of Preferences
- changed a bit the splash PNG file
- moved all the GUI Preferences classes into it's own file flatcamGUI.PreferencesUI.py
- changed the default method for Paint Tool to 'all'
18.09.2019
- added more functionality to the Extension registration with FLatCAM and added to the GUI in Edit -> Preferences -> Utilities
- fixed the parsing of the Manufacturing files when double clicking them and they are registered with FlatCAM
- fixed showing the GUI when some settings (maximized_GUI) are missing from QSettings
- added sys tray menu
- added possibility to edit the custom keywords used by the autocompleter (in Tcl Shell and in the Code Editor). It is done in the Edit -> Preferences -> Utilities
- added a new setting in Edit -> Preferences -> General -> GUI Settings -> Textbox Font which control the font on the Textbox GUI elements
- fixed issue with the sys tray icon not hiding after application close
- added option to run a script from the context menu of the sys tray icon. Changed the color of the sys tray icon to a green one so it will be visible on light and dark themes
17.09.2019
- added more programmers that contributed to FlatCAM over the years, in the "About FlatCAM" -> Programmers window

View File

@ -36,6 +36,10 @@ from shapely.wkt import dumps as sdumps
from shapely.geometry.base import BaseGeometry
from shapely.geometry import shape
# needed for legacy mode
# Used for solid polygons in Matplotlib
from descartes.patch import PolygonPatch
import collections
from collections import Iterable
@ -117,7 +121,11 @@ class Geometry(object):
self.old_disp_number = 0
self.el_count = 0
self.temp_shapes = self.app.plotcanvas.new_shape_group()
if self.app.is_legacy is False:
self.temp_shapes = self.app.plotcanvas.new_shape_group()
else:
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.temp_shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='camlib.geometry')
# if geo_steps_per_circle is None:
# geo_steps_per_circle = int(Geometry.defaults["geo_steps_per_circle"])
@ -3430,7 +3438,7 @@ class Gerber (Geometry):
return 'fail'
log.warning("Joining %d polygons." % len(poly_buffer))
self.app.inform.emit('%s %d %s.' % (_("Gerber processing. Joining"), len(poly_buffer), _("polygons")))
self.app.inform.emit('%s: %d.' % (_("Gerber processing. Joining polygons"), len(poly_buffer)))
if self.use_buffer_for_union:
log.debug("Union by buffer...")

4
descartes/__init__.py Normal file
View File

@ -0,0 +1,4 @@
"""Turn geometric objects into matplotlib patches"""
from descartes.patch import PolygonPatch

66
descartes/patch.py Normal file
View File

@ -0,0 +1,66 @@
"""Paths and patches"""
from matplotlib.patches import PathPatch
from matplotlib.path import Path
from numpy import asarray, concatenate, ones
class Polygon(object):
# Adapt Shapely or GeoJSON/geo_interface polygons to a common interface
def __init__(self, context):
if hasattr(context, 'interiors'):
self.context = context
else:
self.context = getattr(context, '__geo_interface__', context)
@property
def geom_type(self):
return (getattr(self.context, 'geom_type', None)
or self.context['type'])
@property
def exterior(self):
return (getattr(self.context, 'exterior', None)
or self.context['coordinates'][0])
@property
def interiors(self):
value = getattr(self.context, 'interiors', None)
if value is None:
value = self.context['coordinates'][1:]
return value
def PolygonPath(polygon):
"""Constructs a compound matplotlib path from a Shapely or GeoJSON-like
geometric object"""
this = Polygon(polygon)
assert this.geom_type == 'Polygon'
def coding(ob):
# The codes will be all "LINETO" commands, except for "MOVETO"s at the
# beginning of each subpath
n = len(getattr(ob, 'coords', None) or ob)
vals = ones(n, dtype=Path.code_type) * Path.LINETO
vals[0] = Path.MOVETO
return vals
vertices = concatenate(
[asarray(this.exterior)]
+ [asarray(r) for r in this.interiors])
codes = concatenate(
[coding(this.exterior)]
+ [coding(r) for r in this.interiors])
return Path(vertices, codes)
def PolygonPatch(polygon, **kwargs):
"""Constructs a matplotlib patch from a geometric object
The `polygon` may be a Shapely or GeoJSON-like object with or without holes.
The `kwargs` are those supported by the matplotlib.patches.Polygon class
constructor. Returns an instance of matplotlib.patches.PathPatch.
Example (using Shapely Point and a matplotlib axes):
>>> b = Point(0, 0).buffer(1.0)
>>> patch = PolygonPatch(b, fc='blue', ec='blue', alpha=0.5)
>>> axis.add_patch(patch)
"""
return PathPatch(PolygonPath(polygon), **kwargs)

View File

@ -2012,8 +2012,14 @@ class FlatCAMExcEditor(QtCore.QObject):
self.exc_obj = None
# VisPy Visuals
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1)
if self.app.is_legacy is False:
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1)
else:
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_exc_editor')
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_exc_editor')
self.app.pool_recreated.connect(self.pool_recreated)
# Remove from scene
@ -2082,6 +2088,11 @@ class FlatCAMExcEditor(QtCore.QObject):
def entry2option(option, entry):
self.options[option] = float(entry.text())
# Event signals disconnect id holders
self.mp = None
self.mm = None
self.mr = None
# store the status of the editor so the Delete at object level will not work until the edit is finished
self.editor_active = False
log.debug("Initialization of the FlatCAM Excellon Editor is finished ...")
@ -2445,8 +2456,10 @@ class FlatCAMExcEditor(QtCore.QObject):
row_to_be_selected = int(key) - 1
self.last_tool_selected = int(key)
break
self.tools_table_exc.selectRow(row_to_be_selected)
try:
self.tools_table_exc.selectRow(row_to_be_selected)
except TypeError as e:
log.debug("FlatCAMExcEditor.on_tool_add() --> %s" % str(e))
def on_tool_delete(self, dia=None):
self.is_modified = True
@ -2791,16 +2804,23 @@ class FlatCAMExcEditor(QtCore.QObject):
# first connect to new, then disconnect the old handlers
# don't ask why but if there is nothing connected I've seen issues
self.canvas.vis_connect('mouse_press', self.on_canvas_click)
self.canvas.vis_connect('mouse_move', self.on_canvas_move)
self.canvas.vis_connect('mouse_release', self.on_exc_click_release)
self.mp = self.canvas.graph_event_connect('mouse_press', self.on_canvas_click)
self.mm = self.canvas.graph_event_connect('mouse_move', self.on_canvas_move)
self.mr = self.canvas.graph_event_connect('mouse_release', self.on_exc_click_release)
# make sure that the shortcuts key and mouse events will no longer be linked to the methods from FlatCAMApp
# but those from FlatCAMGeoEditor
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_double_click', self.app.on_double_click_over_plot)
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_double_click', self.app.on_double_click_over_plot)
else:
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
self.app.plotcanvas.graph_event_disconnect(self.app.mm)
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
self.app.plotcanvas.graph_event_disconnect(self.app.mdc)
self.app.collection.view.clicked.disconnect()
self.app.ui.popmenu_copy.triggered.disconnect()
@ -2819,15 +2839,22 @@ class FlatCAMExcEditor(QtCore.QObject):
# we restore the key and mouse control to FlatCAMApp method
# first connect to new, then disconnect the old handlers
# don't ask why but if there is nothing connected I've seen issues
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_connect('mouse_double_click', self.app.on_double_click_over_plot)
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot)
self.app.mdc = self.app.plotcanvas.graph_event_connect('mouse_double_click',
self.app.on_double_click_over_plot)
self.app.collection.view.clicked.connect(self.app.collection.on_mouse_down)
self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
self.canvas.vis_disconnect('mouse_release', self.on_exc_click_release)
if self.app.is_legacy is False:
self.canvas.graph_event_disconnect('mouse_press', self.on_canvas_click)
self.canvas.graph_event_disconnect('mouse_move', self.on_canvas_move)
self.canvas.graph_event_disconnect('mouse_release', self.on_exc_click_release)
else:
self.canvas.graph_event_disconnect(self.mp)
self.canvas.graph_event_disconnect(self.mm)
self.canvas.graph_event_disconnect(self.mr)
try:
self.app.ui.popmenu_copy.triggered.disconnect(self.exc_copy_drills)
@ -2903,6 +2930,11 @@ class FlatCAMExcEditor(QtCore.QObject):
self.select_tool("drill_select")
# reset the tool table
self.tools_table_exc.clear()
self.tools_table_exc.setHorizontalHeaderLabels(['#', _('Diameter'), 'D', 'S'])
self.last_tool_selected = None
self.set_ui()
# now that we hava data, create the GUI interface and add it to the Tool Tab
@ -3053,6 +3085,7 @@ class FlatCAMExcEditor(QtCore.QObject):
# element[1] of the tuple is a list of coordinates (a tuple themselves)
ordered_edited_points = sorted(zip(edited_points.keys(), edited_points.values()))
current_tool = 0
for tool_dia in ordered_edited_points:
current_tool += 1
@ -3121,26 +3154,13 @@ class FlatCAMExcEditor(QtCore.QObject):
self.edited_obj_name += "_1"
else:
self.edited_obj_name += "_edit"
self.app.worker_task.emit({'fcn': self.new_edited_excellon,
'params': [self.edited_obj_name]})
self.new_tool_offset = self.exc_obj.tool_offset
# reset the tool table
self.tools_table_exc.clear()
self.tools_table_exc.setHorizontalHeaderLabels(['#', _('Diameter'), 'D', 'S'])
self.last_tool_selected = None
# delete the edited Excellon object which will be replaced by a new one having the edited content of the first
# self.app.collection.set_active(self.exc_obj.options['name'])
# self.app.collection.delete_active()
# restore GUI to the Selected TAB
# Remove anything else in the GUI
self.app.ui.tool_scroll_area.takeWidget()
# Switch notebook to Selected page
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
self.app.worker_task.emit({'fcn': self.new_edited_excellon,
'params': [self.edited_obj_name,
self.new_drills,
self.new_slots,
self.new_tools]})
def update_options(self, obj):
try:
@ -3157,7 +3177,7 @@ class FlatCAMExcEditor(QtCore.QObject):
obj.options = {}
return True
def new_edited_excellon(self, outname):
def new_edited_excellon(self, outname, n_drills, n_slots, n_tools):
"""
Creates a new Excellon object for the edited Excellon. Thread-safe.
@ -3170,12 +3190,17 @@ class FlatCAMExcEditor(QtCore.QObject):
self.app.log.debug("Update the Excellon object with edited content. Source is %s" %
self.exc_obj.options['name'])
new_drills = n_drills
new_slots = n_slots
new_tools = n_tools
# How the object should be initialized
def obj_init(excellon_obj, app_obj):
# self.progress.emit(20)
excellon_obj.drills = self.new_drills
excellon_obj.tools = self.new_tools
excellon_obj.slots = self.new_slots
excellon_obj.drills = deepcopy(new_drills)
excellon_obj.tools = deepcopy(new_tools)
excellon_obj.slots = deepcopy(new_slots)
excellon_obj.tool_offset = self.new_tool_offset
excellon_obj.options['name'] = outname
@ -3192,15 +3217,17 @@ class FlatCAMExcEditor(QtCore.QObject):
app_obj.inform.emit(msg)
raise
# raise
excellon_obj.source_file = self.app.export_excellon(obj_name=outname, filename=None,
local_use=excellon_obj, use_thread=False)
with self.app.proc_container.new(_("Creating Excellon.")):
try:
self.app.new_object("excellon", outname, obj_init)
edited_obj = self.app.new_object("excellon", outname, obj_init)
edited_obj.source_file = self.app.export_excellon(obj_name=edited_obj.options['name'],
local_use=edited_obj,
filename=None,
use_thread=False)
except Exception as e:
log.error("Error on object creation: %s" % str(e))
log.error("Error on Edited object creation: %s" % str(e))
self.app.progress.emit(100)
return
@ -3282,25 +3309,28 @@ class FlatCAMExcEditor(QtCore.QObject):
:param event: Event object dispatched by VisPy
:return: None
"""
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
self.pos = self.canvas.translate_coords(event.pos)
self.pos = self.canvas.translate_coords(event_pos)
if self.app.grid_status() == True:
self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1])
self.app.app_cursor.enabled = True
# Update cursor
self.app.app_cursor.set_data(np.asarray([(self.pos[0], self.pos[1])]), symbol='++', edge_color='black',
size=20)
else:
self.pos = (self.pos[0], self.pos[1])
self.app.app_cursor.enabled = False
if event.button is 1:
if event.button == 1:
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0))
# Selection with left mouse button
if self.active_tool is not None and event.button is 1:
if self.active_tool is not None and event.button == 1:
# Dispatch event to active_tool
# msg = self.active_tool.click(self.app.geo_editor.snap(event.xdata, event.ydata))
self.active_tool.click(self.app.geo_editor.snap(self.pos[0], self.pos[1]))
@ -3318,6 +3348,7 @@ class FlatCAMExcEditor(QtCore.QObject):
modifier_to_use = Qt.ControlModifier
else:
modifier_to_use = Qt.ShiftModifier
# if modifier key is pressed then we add to the selected list the current shape but if it's already
# in the selected list, we removed it. Therefore first click selects, second deselects.
if key_modifier == modifier_to_use:
@ -3422,7 +3453,17 @@ class FlatCAMExcEditor(QtCore.QObject):
:param event: Event object dispatched by VisPy SceneCavas
:return: None
"""
pos_canvas = self.canvas.translate_coords(event.pos)
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
pos_canvas = self.canvas.translate_coords(event_pos)
if self.app.grid_status() == True:
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
@ -3432,7 +3473,7 @@ class FlatCAMExcEditor(QtCore.QObject):
# if the released mouse button was RMB then test if it was a panning motion or not, if not it was a context
# canvas menu
try:
if event.button == 2: # right click
if event.button == right_button: # right click
if self.app.ui.popMenu.mouse_is_panning is False:
try:
QtGui.QGuiApplication.restoreOverrideCursor()
@ -3580,7 +3621,16 @@ class FlatCAMExcEditor(QtCore.QObject):
:return: None
"""
pos = self.canvas.translate_coords(event.pos)
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
pos = self.canvas.translate_coords(event_pos)
event.xdata, event.ydata = pos[0], pos[1]
self.x = event.xdata
@ -3589,7 +3639,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.app.ui.popMenu.mouse_is_panning = False
# if the RMB is clicked and mouse is moving over plot then 'panning_action' is True
if event.button == 2 and event.is_dragging == 1:
if event.button == right_button and event_is_dragging == 1:
self.app.ui.popMenu.mouse_is_panning = True
return
@ -3605,11 +3655,9 @@ class FlatCAMExcEditor(QtCore.QObject):
# ## Snap coordinates
if self.app.grid_status() == True:
x, y = self.app.geo_editor.snap(x, y)
self.app.app_cursor.enabled = True
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
else:
self.app.app_cursor.enabled = False
self.snap_x = x
self.snap_y = y
@ -3636,7 +3684,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.draw_utility_geometry(geo=geo)
# ## Selection area on canvas section # ##
if event.is_dragging == 1 and event.button == 1:
if event_is_dragging == 1 and event.button == 1:
# I make an exception for FCDrillAdd and FCDrillArray because clicking and dragging while making regions
# can create strange issues. Also for FCSlot and FCSlotArray
if isinstance(self.active_tool, FCDrillAdd) or isinstance(self.active_tool, FCDrillArray) or \
@ -3718,10 +3766,10 @@ class FlatCAMExcEditor(QtCore.QObject):
continue
if shape_plus in self.selected:
self.plot_shape(geometry=shape_plus.geo, color=self.app.defaults['global_sel_draw_color'],
self.plot_shape(geometry=shape_plus.geo, color=self.app.defaults['global_sel_draw_color'] + 'FF',
linewidth=2)
continue
self.plot_shape(geometry=shape_plus.geo, color=self.app.defaults['global_draw_color'])
self.plot_shape(geometry=shape_plus.geo, color=self.app.defaults['global_draw_color'] + 'FF')
# for shape in self.storage.get_objects():
# if shape.geo is None: # TODO: This shouldn't have happened
@ -3739,7 +3787,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.shapes.redraw()
def plot_shape(self, geometry=None, color='black', linewidth=1):
def plot_shape(self, geometry=None, color='0x000000FF', linewidth=1):
"""
Plots a geometric object or list of objects without rendering. Plotted objects
are returned as a list. This allows for efficient/animated rendering.

View File

@ -3025,8 +3025,14 @@ class FlatCAMGeoEditor(QtCore.QObject):
# VisPy visuals
self.fcgeometry = None
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1)
if self.app.is_legacy is False:
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1)
else:
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_geo_editor')
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_geo_editor')
self.app.pool_recreated.connect(self.pool_recreated)
# Remove from scene
@ -3163,6 +3169,11 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.transform_complete.connect(self.on_transform_complete)
# Event signals disconnect id holders
self.mp = None
self.mm = None
self.mr = None
# store the status of the editor so the Delete at object level will not work until the edit is finished
self.editor_active = False
log.debug("Initialization of the FlatCAM Geometry Editor is finished ...")
@ -3271,7 +3282,6 @@ class FlatCAMGeoEditor(QtCore.QObject):
# Disable visuals
self.shapes.enabled = False
self.tool_shape.enabled = False
self.app.app_cursor.enabled = False
self.app.ui.geo_editor_menu.setDisabled(True)
self.app.ui.geo_editor_menu.menuAction().setVisible(False)
@ -3309,16 +3319,23 @@ class FlatCAMGeoEditor(QtCore.QObject):
# first connect to new, then disconnect the old handlers
# don't ask why but if there is nothing connected I've seen issues
self.canvas.vis_connect('mouse_press', self.on_canvas_click)
self.canvas.vis_connect('mouse_move', self.on_canvas_move)
self.canvas.vis_connect('mouse_release', self.on_geo_click_release)
self.mp = self.canvas.graph_event_connect('mouse_press', self.on_canvas_click)
self.mm = self.canvas.graph_event_connect('mouse_move', self.on_canvas_move)
self.mr = self.canvas.graph_event_connect('mouse_release', self.on_geo_click_release)
# make sure that the shortcuts key and mouse events will no longer be linked to the methods from FlatCAMApp
# but those from FlatCAMGeoEditor
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_double_click', self.app.on_double_click_over_plot)
if self.app.is_legacy is False:
# make sure that the shortcuts key and mouse events will no longer be linked to the methods from FlatCAMApp
# but those from FlatCAMGeoEditor
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_double_click', self.app.on_double_click_over_plot)
else:
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
self.app.plotcanvas.graph_event_disconnect(self.app.mm)
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
self.app.plotcanvas.graph_event_disconnect(self.app.mdc)
# self.app.collection.view.clicked.disconnect()
self.app.ui.popmenu_copy.triggered.disconnect()
@ -3354,15 +3371,22 @@ class FlatCAMGeoEditor(QtCore.QObject):
# we restore the key and mouse control to FlatCAMApp method
# first connect to new, then disconnect the old handlers
# don't ask why but if there is nothing connected I've seen issues
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_connect('mouse_double_click', self.app.on_double_click_over_plot)
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot)
self.app.mdc = self.app.plotcanvas.graph_event_connect('mouse_double_click',
self.app.on_double_click_over_plot)
# self.app.collection.view.clicked.connect(self.app.collection.on_mouse_down)
self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
self.canvas.vis_disconnect('mouse_release', self.on_geo_click_release)
if self.app.is_legacy is False:
self.canvas.graph_event_disconnect('mouse_press', self.on_canvas_click)
self.canvas.graph_event_disconnect('mouse_move', self.on_canvas_move)
self.canvas.graph_event_disconnect('mouse_release', self.on_geo_click_release)
else:
self.canvas.graph_event_disconnect(self.mp)
self.canvas.graph_event_disconnect(self.mm)
self.canvas.graph_event_disconnect(self.mr)
try:
self.app.ui.popmenu_copy.triggered.disconnect(lambda: self.select_tool('copy'))
@ -3625,18 +3649,17 @@ class FlatCAMGeoEditor(QtCore.QObject):
:param event: Event object dispatched by Matplotlib
:return: None
"""
if self.app.is_legacy is False:
event_pos = event.pos
else:
event_pos = (event.xdata, event.ydata)
self.pos = self.canvas.translate_coords(event.pos)
self.pos = self.canvas.translate_coords(event_pos)
if self.app.grid_status() == True:
self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1])
self.app.app_cursor.enabled = True
# Update cursor
self.app.app_cursor.set_data(np.asarray([(self.pos[0], self.pos[1])]), symbol='++', edge_color='black',
size=20)
else:
self.pos = (self.pos[0], self.pos[1])
self.app.app_cursor.enabled = False
if event.button == 1:
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
@ -3649,8 +3672,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.defaults["global_point_clipboard_format"] % (self.pos[0], self.pos[1]))
return
# Selection with left mouse button
if self.active_tool is not None and event.button is 1:
if self.active_tool is not None and event.button == 1:
# Dispatch event to active_tool
self.active_tool.click(self.snap(self.pos[0], self.pos[1]))
@ -3678,7 +3702,16 @@ class FlatCAMGeoEditor(QtCore.QObject):
:param event: Event object dispatched by VisPy SceneCavas
:return: None
"""
pos = self.canvas.translate_coords(event.pos)
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
pos = self.canvas.translate_coords(event_pos)
event.xdata, event.ydata = pos[0], pos[1]
self.x = event.xdata
@ -3687,8 +3720,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.ui.popMenu.mouse_is_panning = False
# if the RMB is clicked and mouse is moving over plot then 'panning_action' is True
if event.button == 2:
if event.is_dragging:
if event.button == right_button:
if event_is_dragging:
self.app.ui.popMenu.mouse_is_panning = True
# return
else:
@ -3706,11 +3739,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
# ### Snap coordinates ###
if self.app.grid_status() == True:
x, y = self.snap(x, y)
self.app.app_cursor.enabled = True
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
else:
self.app.app_cursor.enabled = False
self.snap_x = x
self.snap_y = y
@ -3728,7 +3759,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
if event.button == 1 and event.is_dragging and isinstance(self.active_tool, FCEraser):
if event.button == 1 and event_is_dragging and isinstance(self.active_tool, FCEraser):
pass
else:
# ### Utility geometry (animated) ###
@ -3740,7 +3771,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
# ### Selection area on canvas section ###
dx = pos[0] - self.pos[0]
if event.is_dragging and event.button == 1:
if event_is_dragging and event.button == 1:
self.app.delete_selection_shape()
if dx < 0:
self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x, y),
@ -3754,7 +3785,16 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.selection_type = None
def on_geo_click_release(self, event):
pos_canvas = self.canvas.translate_coords(event.pos)
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
pos_canvas = self.canvas.translate_coords(event_pos)
if self.app.grid_status() == True:
pos = self.snap(pos_canvas[0], pos_canvas[1])
@ -3776,7 +3816,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.active_tool.click_release((self.pos[0], self.pos[1]))
# self.app.inform.emit(msg)
self.replot()
elif event.button == 2: # right click
elif event.button == right_button: # right click
if self.app.ui.popMenu.mouse_is_panning == False:
if self.in_action is False:
try:
@ -3943,7 +3983,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
# return [shape for shape in self.shape_buffer if shape["selected"]]
return self.selected
def plot_shape(self, geometry=None, color='black', linewidth=1):
def plot_shape(self, geometry=None, color='#000000FF', linewidth=1):
"""
Plots a geometric object or list of objects without rendering. Plotted objects
are returned as a list. This allows for efficient/animated rendering.
@ -3961,7 +4001,6 @@ class FlatCAMGeoEditor(QtCore.QObject):
try:
for geo in geometry:
plot_elements += self.plot_shape(geometry=geo, color=color, linewidth=linewidth)
# Non-iterable
except TypeError:
@ -3999,10 +4038,10 @@ class FlatCAMGeoEditor(QtCore.QObject):
continue
if shape in self.selected:
self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_sel_draw_color'], linewidth=2)
self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_sel_draw_color'] + 'FF', linewidth=2)
continue
self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_draw_color'])
self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_draw_color'] + "FF")
for shape in self.utility:
self.plot_shape(geometry=shape.geo, linewidth=1)

View File

@ -2607,8 +2607,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.ma_lower_threshold_entry = FCEntry()
self.ma_lower_threshold_entry.setValidator(QtGui.QDoubleValidator(0.0000, 9999.9999, 4))
ma_form_layout.addRow(self.ma_upper_threshold_lbl, self.ma_upper_threshold_entry)
ma_form_layout.addRow(self.ma_lower_threshold_lbl, self.ma_lower_threshold_entry)
ma_form_layout.addRow(self.ma_upper_threshold_lbl, self.ma_upper_threshold_entry)
# Buttons
hlay_ma = QtWidgets.QHBoxLayout()
@ -2821,12 +2821,27 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.gerber_obj_options = dict()
# VisPy Visuals
self.shapes = self.canvas.new_shape_collection(layers=1)
self.tool_shape = self.canvas.new_shape_collection(layers=1)
self.ma_annotation = self.canvas.new_text_group()
if self.app.is_legacy is False:
self.shapes = self.canvas.new_shape_collection(layers=1)
self.tool_shape = self.canvas.new_shape_collection(layers=1)
self.ma_annotation = self.canvas.new_text_group()
else:
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_grb_editor')
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_grb_editor')
self.ma_annotation = ShapeCollectionLegacy(
obj=self,
app=self.app,
name='ma_anno_grb_editor',
annotation_job=True)
self.app.pool_recreated.connect(self.pool_recreated)
# Event signals disconnect id holders
self.mp = None
self.mm = None
self.mr = None
# Remove from scene
self.shapes.enabled = False
self.tool_shape.enabled = False
@ -2972,8 +2987,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.buffer_distance_entry.set_value(self.app.defaults["gerber_editor_buff_f"])
self.scale_factor_entry.set_value(self.app.defaults["gerber_editor_scale_f"])
self.ma_upper_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_low"])
self.ma_lower_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_high"])
self.ma_upper_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_high"])
self.ma_lower_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_low"])
self.apsize_entry.set_value(self.app.defaults["gerber_editor_newsize"])
self.aptype_cb.set_value(self.app.defaults["gerber_editor_newtype"])
@ -3511,14 +3526,21 @@ class FlatCAMGrbEditor(QtCore.QObject):
# first connect to new, then disconnect the old handlers
# don't ask why but if there is nothing connected I've seen issues
self.canvas.vis_connect('mouse_press', self.on_canvas_click)
self.canvas.vis_connect('mouse_move', self.on_canvas_move)
self.canvas.vis_connect('mouse_release', self.on_grb_click_release)
self.mp = self.canvas.graph_event_connect('mouse_press', self.on_canvas_click)
self.mm = self.canvas.graph_event_connect('mouse_move', self.on_canvas_move)
self.mr = self.canvas.graph_event_connect('mouse_release', self.on_grb_click_release)
if self.app.is_legacy is False:
self.canvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.canvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.canvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.canvas.graph_event_disconnect('mouse_double_click', self.app.on_double_click_over_plot)
else:
self.canvas.graph_event_disconnect(self.app.mp)
self.canvas.graph_event_disconnect(self.app.mm)
self.canvas.graph_event_disconnect(self.app.mr)
self.canvas.graph_event_disconnect(self.app.mdc)
self.canvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.canvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.canvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.canvas.vis_disconnect('mouse_double_click', self.app.on_double_click_over_plot)
self.app.collection.view.clicked.disconnect()
self.app.ui.popmenu_copy.triggered.disconnect()
@ -3550,15 +3572,20 @@ class FlatCAMGrbEditor(QtCore.QObject):
# we restore the key and mouse control to FlatCAMApp method
# first connect to new, then disconnect the old handlers
# don't ask why but if there is nothing connected I've seen issues
self.canvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.canvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.canvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.canvas.vis_connect('mouse_double_click', self.app.on_double_click_over_plot)
self.app.mp = self.canvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.mm = self.canvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.mr = self.canvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.mdc = self.canvas.graph_event_connect('mouse_double_click', self.app.on_double_click_over_plot)
self.app.collection.view.clicked.connect(self.app.collection.on_mouse_down)
self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
self.canvas.vis_disconnect('mouse_release', self.on_grb_click_release)
if self.app.is_legacy is False:
self.canvas.graph_event_disconnect('mouse_press', self.on_canvas_click)
self.canvas.graph_event_disconnect('mouse_move', self.on_canvas_move)
self.canvas.graph_event_disconnect('mouse_release', self.on_grb_click_release)
else:
self.canvas.graph_event_disconnect(self.mp)
self.canvas.graph_event_disconnect(self.mm)
self.canvas.graph_event_disconnect(self.mr)
try:
self.app.ui.popmenu_copy.triggered.disconnect(self.on_copy_button)
@ -3654,6 +3681,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.deactivate_grb_editor()
self.activate_grb_editor()
# reset the tool table
self.apertures_table.clear()
self.apertures_table.setHorizontalHeaderLabels(['#', _('Code'), _('Type'), _('Size'), _('Dim')])
self.last_aperture_selected = None
# create a reference to the source object
self.gerber_obj = orig_grb_obj
self.gerber_obj_options = orig_grb_obj.options
@ -3702,6 +3735,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
# list of clear geos that are to be applied to the entire file
global_clear_geo = []
# create one big geometry made out of all 'negative' (clear) polygons
for apid in self.gerber_obj.apertures:
# first check if we have any clear_geometry (LPC) and if yes added it to the global_clear_geo
if 'geometry' in self.gerber_obj.apertures[apid]:
@ -3710,8 +3744,19 @@ class FlatCAMGrbEditor(QtCore.QObject):
global_clear_geo.append(elem['clear'])
log.warning("Found %d clear polygons." % len(global_clear_geo))
global_clear_geo = MultiPolygon(global_clear_geo)
if isinstance(global_clear_geo, Polygon):
global_clear_geo = list(global_clear_geo)
# for debugging
# for geo in global_clear_geo:
# self.shapes.add(shape=geo, color='black', face_color='#000000'+'AF', layer=0, tolerance=self.tolerance)
# self.shapes.redraw()
# we subtract the big "negative" (clear) geometry from each solid polygon but only the part of clear geometry
# that fits inside the solid. otherwise we may loose the solid
for apid in self.gerber_obj.apertures:
temp_elem = []
temp_solid_geometry= []
if 'geometry' in self.gerber_obj.apertures[apid]:
# for elem in self.gerber_obj.apertures[apid]['geometry']:
# if 'solid' in elem:
@ -3742,9 +3787,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
# temp_elem.append(deepcopy(new_elem))
for elem in self.gerber_obj.apertures[apid]['geometry']:
new_elem = dict()
if 'solid' in elem:
solid_geo = elem['solid']
for clear_geo in global_clear_geo:
# Make sure that the clear_geo is within the solid_geo otherwise we loose
# the solid_geometry. We want for clear_geometry just to cut into solid_geometry not to
@ -3757,15 +3802,15 @@ class FlatCAMGrbEditor(QtCore.QObject):
new_elem['clear'] = elem['clear']
if 'follow' in elem:
new_elem['follow'] = elem['follow']
temp_elem.append(deepcopy(new_elem))
temp_solid_geometry.append(deepcopy(new_elem))
self.gerber_obj.apertures[apid]['geometry'] = deepcopy(temp_elem)
self.gerber_obj.apertures[apid]['geometry'] = deepcopy(temp_solid_geometry)
log.warning("Polygon difference done for %d apertures." % len(self.gerber_obj.apertures))
# and then add it to the storage elements (each storage elements is a member of a list
def job_thread(aperture_id):
with self.app.proc_container.new('%s: %s %s...' %
(_("Adding aperture"), str(aperture_id), _("geo"))):
with self.app.proc_container.new('%s: %s ...' %
(_("Adding geometry for aperture"), str(aperture_id))):
storage_elem = []
self.storage_dict[aperture_id] = {}
@ -3781,6 +3826,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.storage_dict[aperture_id][k] = self.gerber_obj.apertures[aperture_id][k]
except Exception as e:
log.debug("FlatCAMGrbEditor.edit_fcgerber().job_thread() --> %s" % str(e))
# Check promises and clear if exists
while True:
try:
@ -3789,6 +3835,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
except ValueError:
break
# we create a job work each aperture, job that work in a threaded way to store the geometry in local storage
# as DrawToolShapes
for ap_id in self.gerber_obj.apertures:
self.grb_plot_promises.append(ap_id)
self.app.worker_task.emit({'fcn': job_thread, 'params': [ap_id]})
@ -3831,19 +3879,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
new_grb_name = self.edited_obj_name + "_edit"
self.app.worker_task.emit({'fcn': self.new_edited_gerber,
'params': [new_grb_name]})
# reset the tool table
self.apertures_table.clear()
self.apertures_table.setHorizontalHeaderLabels(['#', _('Code'), _('Type'), _('Size'), _('Dim')])
self.last_aperture_selected = None
# restore GUI to the Selected TAB
# Remove anything else in the GUI
self.app.ui.selected_scroll_area.takeWidget()
# Switch notebook to Selected page
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
'params': [new_grb_name, self.storage_dict]})
@staticmethod
def update_options(obj):
@ -3861,12 +3897,13 @@ class FlatCAMGrbEditor(QtCore.QObject):
obj.options = dict()
return True
def new_edited_gerber(self, outname):
def new_edited_gerber(self, outname, aperture_storage):
"""
Creates a new Gerber object for the edited Gerber. Thread-safe.
:param outname: Name of the resulting object. None causes the name to be that of the file.
:type outname: str
:param aperture_storage: a dictionary that holds all the objects geometry
:return: None
"""
@ -3874,13 +3911,14 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.gerber_obj.options['name'].upper())
out_name = outname
storage_dict = aperture_storage
local_storage_dict = dict()
for aperture in self.storage_dict:
if 'geometry' in self.storage_dict[aperture]:
for aperture in storage_dict:
if 'geometry' in storage_dict[aperture]:
# add aperture only if it has geometry
if len(self.storage_dict[aperture]['geometry']) > 0:
local_storage_dict[aperture] = deepcopy(self.storage_dict[aperture])
if len(storage_dict[aperture]['geometry']) > 0:
local_storage_dict[aperture] = deepcopy(storage_dict[aperture])
# How the object should be initialized
def obj_init(grb_obj, app_obj):
@ -3969,7 +4007,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
try:
self.app.new_object("gerber", outname, obj_init)
except Exception as e:
log.error("Error on object creation: %s" % str(e))
log.error("Error on Edited object creation: %s" % str(e))
self.app.progress.emit(100)
return
@ -4116,20 +4154,23 @@ class FlatCAMGrbEditor(QtCore.QObject):
:param event: Event object dispatched by VisPy
:return: None
"""
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
self.pos = self.canvas.translate_coords(event.pos)
self.pos = self.canvas.translate_coords(event_pos)
if self.app.grid_status() == True:
self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1])
self.app.app_cursor.enabled = True
# Update cursor
self.app.app_cursor.set_data(np.asarray([(self.pos[0], self.pos[1])]), symbol='++', edge_color='black',
size=20)
else:
self.pos = (self.pos[0], self.pos[1])
self.app.app_cursor.enabled = False
if event.button is 1:
if event.button == 1:
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0))
@ -4180,8 +4221,16 @@ class FlatCAMGrbEditor(QtCore.QObject):
def on_grb_click_release(self, event):
self.modifiers = QtWidgets.QApplication.keyboardModifiers()
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
pos_canvas = self.canvas.translate_coords(event.pos)
pos_canvas = self.canvas.translate_coords(event_pos)
if self.app.grid_status() == True:
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
else:
@ -4190,7 +4239,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
# if the released mouse button was RMB then test if it was a panning motion or not, if not it was a context
# canvas menu
try:
if event.button == 2: # right click
if event.button == right_button: # right click
if self.app.ui.popMenu.mouse_is_panning is False:
if self.in_action is False:
try:
@ -4271,8 +4320,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.delete_selection_shape()
for storage in self.storage_dict:
try:
for obj in self.storage_dict[storage]['geometry']:
for obj in self.storage_dict[storage]['geometry']:
if 'solid' in obj.geo:
geometric_data = obj.geo['solid']
if (sel_type is True and poly_selection.contains(geometric_data)) or \
(sel_type is False and poly_selection.intersects(geometric_data)):
@ -4286,8 +4335,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
else:
self.selected.append(obj)
sel_aperture.add(storage)
except KeyError:
pass
try:
self.apertures_table.cellPressed.disconnect()
except Exception as e:
@ -4314,8 +4362,16 @@ class FlatCAMGrbEditor(QtCore.QObject):
:param event: Event object dispatched by VisPy SceneCavas
:return: None
"""
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
pos_canvas = self.canvas.translate_coords(event.pos)
pos_canvas = self.canvas.translate_coords(event_pos)
event.xdata, event.ydata = pos_canvas[0], pos_canvas[1]
self.x = event.xdata
@ -4324,7 +4380,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.ui.popMenu.mouse_is_panning = False
# if the RMB is clicked and mouse is moving over plot then 'panning_action' is True
if event.button == 2 and event.is_dragging == 1:
if event.button == right_button and event_is_dragging == 1:
self.app.ui.popMenu.mouse_is_panning = True
return
@ -4340,11 +4396,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
# # ## Snap coordinates
if self.app.grid_status() == True:
x, y = self.app.geo_editor.snap(x, y)
self.app.app_cursor.enabled = True
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
else:
self.app.app_cursor.enabled = False
self.snap_x = x
self.snap_y = y
@ -4371,7 +4425,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.draw_utility_geometry(geo=geo)
# # ## Selection area on canvas section # ##
if event.is_dragging == 1 and event.button == 1:
if event_is_dragging == 1 and event.button == 1:
# I make an exception for FCRegion and FCTrack because clicking and dragging while making regions can
# create strange issues like missing a point in a track/region
if isinstance(self.active_tool, FCRegion) or isinstance(self.active_tool, FCTrack):
@ -4420,34 +4474,32 @@ class FlatCAMGrbEditor(QtCore.QObject):
:rtype: None
"""
with self.app.proc_container.new("Plotting"):
self.shapes.clear(update=True)
for storage in self.storage_dict:
try:
for elem in self.storage_dict[storage]['geometry']:
for elem in self.storage_dict[storage]['geometry']:
if 'solid' in elem.geo:
geometric_data = elem.geo['solid']
if geometric_data is None:
continue
if elem in self.selected:
self.plot_shape(geometry=geometric_data,
color=self.app.defaults['global_sel_draw_color'],
color=self.app.defaults['global_sel_draw_color'] + 'FF',
linewidth=2)
continue
self.plot_shape(geometry=geometric_data,
color=self.app.defaults['global_draw_color'])
except KeyError:
pass
else:
self.plot_shape(geometry=geometric_data,
color=self.app.defaults['global_draw_color'] + 'FF')
for elem in self.utility:
geometric_data = elem.geo['solid']
self.plot_shape(geometry=geometric_data, linewidth=1)
continue
if self.utility:
for elem in self.utility:
geometric_data = elem.geo['solid']
self.plot_shape(geometry=geometric_data, linewidth=1)
continue
self.shapes.redraw()
def plot_shape(self, geometry=None, color='black', linewidth=1):
def plot_shape(self, geometry=None, color='#000000FF', linewidth=1):
"""
Plots a geometric object or list of objects without rendering. Plotted objects
are returned as a list. This allows for efficient/animated rendering.
@ -4463,10 +4515,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
try:
self.shapes.add(shape=geometry.geo, color=color, face_color=color, layer=0, tolerance=self.tolerance)
except AttributeError:
except AttributeError as e:
if type(geometry) == Point:
return
self.shapes.add(shape=geometry, color=color, face_color=color+'AF', layer=0, tolerance=self.tolerance)
if len(color) == 9:
color = color[:7] + 'AF'
self.shapes.add(shape=geometry, color=color, face_color=color, layer=0, tolerance=self.tolerance)
def start_delayed_plot(self, check_period):
"""
@ -4785,7 +4839,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
except Exception as e:
lower_threshold_val = 0.0
if area < float(upper_threshold_val) and area > float(lower_threshold_val):
if float(upper_threshold_val) > area > float(lower_threshold_val):
current_pos = geo_el['solid'].exterior.coords[-1]
text_elem = '%.4f' % area
text.append(text_elem)
@ -4794,7 +4848,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
if text:
self.ma_annotation.set(text=text, pos=position, visible=True,
font_size=self.app.defaults["cncjob_annotation_fontsize"],
color=self.app.defaults["global_sel_draw_color"])
color='#000000FF')
self.app.inform.emit('[success] %s' %
_("Polygon areas marked."))
else:

File diff suppressed because it is too large Load Diff

View File

@ -152,10 +152,10 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
except Exception as e:
pass
def vis_connect(self, event_name, callback):
def graph_event_connect(self, event_name, callback):
return getattr(self.events, event_name).connect(callback)
def vis_disconnect(self, event_name, callback=None):
def graph_event_disconnect(self, event_name, callback=None):
if callback is None:
getattr(self.events, event_name).disconnect()
else:

File diff suppressed because it is too large Load Diff

4724
flatcamGUI/PreferencesUI.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -298,6 +298,11 @@ class CutOut(FlatCAMTool):
# if mouse is dragging set the object True
self.mouse_is_dragging = False
# event handlers references
self.kp = None
self.mm = None
self.mr = None
# hold the mouse position here
self.x_pos = None
self.y_pos = None
@ -780,13 +785,21 @@ class CutOut(FlatCAMTool):
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve Geometry object"), name))
return "Could not retrieve object: %s" % name
self.app.plotcanvas.vis_disconnect('key_press', self.app.ui.keyPressEvent)
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.vis_connect('key_press', self.on_key_press)
self.app.plotcanvas.vis_connect('mouse_move', self.on_mouse_move)
self.app.plotcanvas.vis_connect('mouse_release', self.on_mouse_click_release)
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('key_press', self.app.ui.keyPressEvent)
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
else:
self.app.plotcanvas.graph_event_disconnect(self.app.kp)
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
self.app.plotcanvas.graph_event_disconnect(self.app.mm)
self.kp = self.app.plotcanvas.graph_event_connect('key_press', self.on_key_press)
self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_click_release)
def on_manual_cutout(self, click_pos):
name = self.man_object_combo.currentText()
@ -923,33 +936,46 @@ class CutOut(FlatCAMTool):
# To be called after clicking on the plot.
def on_mouse_click_release(self, event):
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
try:
x = float(event_pos[0])
y = float(event_pos[1])
except TypeError:
return
event_pos = (x, y)
# do paint single only for left mouse clicks
if event.button == 1:
self.app.inform.emit(_("Making manual bridge gap..."))
pos = self.app.plotcanvas.translate_coords(event.pos)
pos = self.app.plotcanvas.translate_coords(event_pos)
self.on_manual_cutout(click_pos=pos)
# self.app.plotcanvas.vis_disconnect('key_press', self.on_key_press)
# self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move)
# self.app.plotcanvas.vis_disconnect('mouse_release', self.on_mouse_click_release)
# self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent)
# self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
# self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
# self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
# self.app.geo_editor.tool_shape.clear(update=True)
# self.app.geo_editor.tool_shape.enabled = False
# self.gapFinished.emit()
# if RMB then we exit
elif event.button == 2 and self.mouse_is_dragging is False:
self.app.plotcanvas.vis_disconnect('key_press', self.on_key_press)
self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move)
self.app.plotcanvas.vis_disconnect('mouse_release', self.on_mouse_click_release)
self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent)
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
elif event.button == right_button and self.mouse_is_dragging is False:
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('key_press', self.on_key_press)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release)
else:
self.app.plotcanvas.graph_event_disconnect(self.kp)
self.app.plotcanvas.graph_event_disconnect(self.mm)
self.app.plotcanvas.graph_event_disconnect(self.mr)
self.app.kp = self.app.plotcanvas.graph_event_connect('key_press', self.app.ui.keyPressEvent)
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot)
self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot)
# Remove any previous utility shape
self.app.geo_editor.tool_shape.clear(update=True)
@ -959,10 +985,26 @@ class CutOut(FlatCAMTool):
self.app.on_mouse_move_over_plot(event=event)
pos = self.canvas.translate_coords(event.pos)
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
try:
x = float(event_pos[0])
y = float(event_pos[1])
except TypeError:
return
event_pos = (x, y)
pos = self.canvas.translate_coords(event_pos)
event.xdata, event.ydata = pos[0], pos[1]
if event.is_dragging is True:
if event_is_dragging is True:
self.mouse_is_dragging = True
else:
self.mouse_is_dragging = False
@ -1058,19 +1100,43 @@ class CutOut(FlatCAMTool):
# events from the GUI are of type QKeyEvent
elif type(event) == QtGui.QKeyEvent:
key = event.key()
elif isinstance(event, mpl_key_event): # MatPlotLib key events are trickier to interpret than the rest
key = event.key
key = QtGui.QKeySequence(key)
# check for modifiers
key_string = key.toString().lower()
if '+' in key_string:
mod, __, key_text = key_string.rpartition('+')
if mod.lower() == 'ctrl':
modifiers = QtCore.Qt.ControlModifier
elif mod.lower() == 'alt':
modifiers = QtCore.Qt.AltModifier
elif mod.lower() == 'shift':
modifiers = QtCore.Qt.ShiftModifier
else:
modifiers = QtCore.Qt.NoModifier
key = QtGui.QKeySequence(key_text)
# events from Vispy are of type KeyEvent
else:
key = event.key
# Escape = Deselect All
if key == QtCore.Qt.Key_Escape or key == 'Escape':
self.app.plotcanvas.vis_disconnect('key_press', self.on_key_press)
self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move)
self.app.plotcanvas.vis_disconnect('mouse_release', self.on_mouse_click_release)
self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent)
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('key_press', self.on_key_press)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release)
else:
self.app.plotcanvas.graph_event_disconnect(self.kp)
self.app.plotcanvas.graph_event_disconnect(self.mm)
self.app.plotcanvas.graph_event_disconnect(self.mr)
self.app.kp = self.app.plotcanvas.graph_event_connect('key_press', self.app.ui.keyPressEvent)
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot)
self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot)
# Remove any previous utility shape
self.app.geo_editor.tool_shape.clear(update=True)

View File

@ -45,10 +45,10 @@ class Measurement(FlatCAMTool):
self.units_value = QtWidgets.QLabel("%s" % str({'mm': _("METRIC (mm)"), 'in': _("INCH (in)")}[self.units]))
self.units_value.setDisabled(True)
self.start_label = QtWidgets.QLabel("<b>%s</b> %s:" % (_('Start'), _('Coords')))
self.start_label = QtWidgets.QLabel("%s:" % _('Start Coords'))
self.start_label.setToolTip(_("This is measuring Start point coordinates."))
self.stop_label = QtWidgets.QLabel("<b>%s</b> %s:" % (_('Stop'), _('Coords')))
self.stop_label = QtWidgets.QLabel("%s:" % _('Stop Coords'))
self.stop_label.setToolTip(_("This is the measuring Stop point coordinates."))
self.distance_x_label = QtWidgets.QLabel('%s:' % _("Dx"))
@ -113,7 +113,11 @@ class Measurement(FlatCAMTool):
self.original_call_source = 'app'
# VisPy visuals
self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)
if self.app.is_legacy is False:
self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)
else:
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.sel_shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='measurement')
self.measure_btn.clicked.connect(self.activate_measure_tool)
@ -178,26 +182,49 @@ class Measurement(FlatCAMTool):
# we can connect the app mouse events to the measurement tool
# NEVER DISCONNECT THOSE before connecting some other handlers; it breaks something in VisPy
self.canvas.vis_connect('mouse_move', self.on_mouse_move_meas)
self.canvas.vis_connect('mouse_release', self.on_mouse_click_release)
self.mm = self.canvas.graph_event_connect('mouse_move', self.on_mouse_move_meas)
self.mr = self.canvas.graph_event_connect('mouse_release', self.on_mouse_click_release)
# we disconnect the mouse/key handlers from wherever the measurement tool was called
if self.app.call_source == 'app':
self.canvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.canvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.canvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
if self.app.is_legacy is False:
self.canvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.canvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.canvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
else:
self.canvas.graph_event_disconnect(self.app.mm)
self.canvas.graph_event_disconnect(self.app.mp)
self.canvas.graph_event_disconnect(self.app.mr)
elif self.app.call_source == 'geo_editor':
self.canvas.vis_disconnect('mouse_move', self.app.geo_editor.on_canvas_move)
self.canvas.vis_disconnect('mouse_press', self.app.geo_editor.on_canvas_click)
self.canvas.vis_disconnect('mouse_release', self.app.geo_editor.on_geo_click_release)
if self.app.is_legacy is False:
self.canvas.graph_event_disconnect('mouse_move', self.app.geo_editor.on_canvas_move)
self.canvas.graph_event_disconnect('mouse_press', self.app.geo_editor.on_canvas_click)
self.canvas.graph_event_disconnect('mouse_release', self.app.geo_editor.on_geo_click_release)
else:
self.canvas.graph_event_disconnect(self.app.geo_editor.mm)
self.canvas.graph_event_disconnect(self.app.geo_editor.mp)
self.canvas.graph_event_disconnect(self.app.geo_editor.mr)
elif self.app.call_source == 'exc_editor':
self.canvas.vis_disconnect('mouse_move', self.app.exc_editor.on_canvas_move)
self.canvas.vis_disconnect('mouse_press', self.app.exc_editor.on_canvas_click)
self.canvas.vis_disconnect('mouse_release', self.app.exc_editor.on_exc_click_release)
if self.app.is_legacy is False:
self.canvas.graph_event_disconnect('mouse_move', self.app.exc_editor.on_canvas_move)
self.canvas.graph_event_disconnect('mouse_press', self.app.exc_editor.on_canvas_click)
self.canvas.graph_event_disconnect('mouse_release', self.app.exc_editor.on_exc_click_release)
else:
self.canvas.graph_event_disconnect(self.app.exc_editor.mm)
self.canvas.graph_event_disconnect(self.app.exc_editor.mp)
self.canvas.graph_event_disconnect(self.app.exc_editor.mr)
elif self.app.call_source == 'grb_editor':
self.canvas.vis_disconnect('mouse_move', self.app.grb_editor.on_canvas_move)
self.canvas.vis_disconnect('mouse_press', self.app.grb_editor.on_canvas_click)
self.canvas.vis_disconnect('mouse_release', self.app.grb_editor.on_grb_click_release)
if self.app.is_legacy is False:
self.canvas.graph_event_disconnect('mouse_move', self.app.grb_editor.on_canvas_move)
self.canvas.graph_event_disconnect('mouse_press', self.app.grb_editor.on_canvas_click)
self.canvas.graph_event_disconnect('mouse_release', self.app.grb_editor.on_grb_click_release)
else:
self.canvas.graph_event_disconnect(self.app.grb_editor.mm)
self.canvas.graph_event_disconnect(self.app.grb_editor.mp)
self.canvas.graph_event_disconnect(self.app.grb_editor.mr)
self.app.call_source = 'measurement'
@ -210,25 +237,35 @@ class Measurement(FlatCAMTool):
self.app.call_source = copy(self.original_call_source)
if self.original_call_source == 'app':
self.canvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.canvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.canvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.mm = self.canvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.mp = self.canvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.mr = self.canvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
elif self.original_call_source == 'geo_editor':
self.canvas.vis_connect('mouse_move', self.app.geo_editor.on_canvas_move)
self.canvas.vis_connect('mouse_press', self.app.geo_editor.on_canvas_click)
self.canvas.vis_connect('mouse_release', self.app.geo_editor.on_geo_click_release)
self.app.geo_editor.mm = self.canvas.graph_event_connect('mouse_move', self.app.geo_editor.on_canvas_move)
self.app.geo_editor.mp = self.canvas.graph_event_connect('mouse_press', self.app.geo_editor.on_canvas_click)
self.app.geo_editor.mr = self.canvas.graph_event_connect('mouse_release',
self.app.geo_editor.on_geo_click_release)
elif self.original_call_source == 'exc_editor':
self.canvas.vis_connect('mouse_move', self.app.exc_editor.on_canvas_move)
self.canvas.vis_connect('mouse_press', self.app.exc_editor.on_canvas_click)
self.canvas.vis_connect('mouse_release', self.app.exc_editor.on_exc_click_release)
self.app.exc_editor.mm = self.canvas.graph_event_connect('mouse_move', self.app.exc_editor.on_canvas_move)
self.app.exc_editor.mp = self.canvas.graph_event_connect('mouse_press', self.app.exc_editor.on_canvas_click)
self.app.exc_editor.mr = self.canvas.graph_event_connect('mouse_release',
self.app.exc_editor.on_exc_click_release)
elif self.original_call_source == 'grb_editor':
self.canvas.vis_connect('mouse_move', self.app.grb_editor.on_canvas_move)
self.canvas.vis_connect('mouse_press', self.app.grb_editor.on_canvas_click)
self.canvas.vis_connect('mouse_release', self.app.grb_editor.on_grb_click_release)
self.app.grb_editor.mm = self.canvas.graph_event_connect('mouse_move', self.app.grb_editor.on_canvas_move)
self.app.grb_editor.mp = self.canvas.graph_event_connect('mouse_press', self.app.grb_editor.on_canvas_click)
self.app.grb_editor.mr = self.canvas.graph_event_connect('mouse_release',
self.app.grb_editor.on_grb_click_release)
# disconnect the mouse/key events from functions of measurement tool
self.canvas.vis_disconnect('mouse_move', self.on_mouse_move_meas)
self.canvas.vis_disconnect('mouse_release', self.on_mouse_click_release)
if self.app.is_legacy is False:
self.canvas.graph_event_disconnect('mouse_move', self.on_mouse_move_meas)
self.canvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release)
else:
self.canvas.graph_event_disconnect(self.mm)
self.canvas.graph_event_disconnect(self.mr)
# self.app.ui.notebook.setTabText(2, _("Tools"))
# self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
@ -247,7 +284,13 @@ class Measurement(FlatCAMTool):
log.debug("Measuring Tool --> mouse click release")
if event.button == 1:
pos_canvas = self.canvas.translate_coords(event.pos)
if self.app.is_legacy is False:
event_pos = event.pos
else:
event_pos = (event.xdata, event.ydata)
pos_canvas = self.canvas.translate_coords(event_pos)
# if GRID is active we need to get the snapped positions
if self.app.grid_status() == True:
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
@ -267,8 +310,7 @@ class Measurement(FlatCAMTool):
if len(self.points) == 1:
self.start_entry.set_value("(%.4f, %.4f)" % pos)
self.app.inform.emit(_("MEASURING: Click on the Destination point ..."))
if len(self.points) == 2:
elif len(self.points) == 2:
dx = self.points[1][0] - self.points[0][0]
dy = self.points[1][1] - self.points[0][1]
d = sqrt(dx ** 2 + dy ** 2)
@ -280,47 +322,68 @@ class Measurement(FlatCAMTool):
self.distance_x_entry.set_value('%.4f' % abs(dx))
self.distance_y_entry.set_value('%.4f' % abs(dy))
self.total_distance_entry.set_value('%.4f' % abs(d))
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (pos[0], pos[1]))
self.app.ui.rel_position_label.setText("<b>Dx</b>: {0:.4f}&nbsp;&nbsp; <b>Dy</b>: "
"{0:.4f}&nbsp;&nbsp;&nbsp;&nbsp;".format(pos[0], pos[1]))
self.deactivate_measure_tool()
def on_mouse_move_meas(self, event):
try: # May fail in case mouse not within axes
pos_canvas = self.app.plotcanvas.translate_coords(event.pos)
if self.app.is_legacy is False:
event_pos = event.pos
else:
event_pos = (event.xdata, event.ydata)
try:
x = float(event_pos[0])
y = float(event_pos[1])
except TypeError:
return
pos_canvas = self.app.plotcanvas.translate_coords((x, y))
if self.app.grid_status() == True:
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
self.app.app_cursor.enabled = True
# Update cursor
self.app.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
symbol='++', edge_color='black', size=20)
else:
pos = (pos_canvas[0], pos_canvas[1])
self.app.app_cursor.enabled = False
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: {0:.4f}&nbsp;&nbsp; "
"<b>Y</b>: {0:.4f}".format(pos[0], pos[1]))
if self.rel_point1 is not None:
dx = pos[0] - self.rel_point1[0]
dy = pos[1] - self.rel_point1[1]
dx = pos[0] - float(self.rel_point1[0])
dy = pos[1] - float(self.rel_point1[1])
else:
dx = pos[0]
dy = pos[1]
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"<b>Y</b>: %.4f" % (pos[0], pos[1]))
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
self.app.ui.rel_position_label.setText("<b>Dx</b>: {0:.4f}&nbsp;&nbsp; <b>Dy</b>: "
"{0:.4f}&nbsp;&nbsp;&nbsp;&nbsp;".format(dx, dy))
# update utility geometry
if len(self.points) == 1:
self.utility_geometry(pos=pos)
except Exception as e:
log.debug("Measurement.on_mouse_move_meas() --> %s" % str(e))
self.app.ui.position_label.setText("")
self.app.ui.rel_position_label.setText("")
def utility_geometry(self, pos):
# first delete old shape
self.delete_shape()
# second draw the new shape of the utility geometry
self.meas_line = LineString([pos, self.points[0]])
self.sel_shapes.add(self.meas_line, color='black', update=True, layer=0, tolerance=None)
meas_line = LineString([pos, self.points[0]])
color = '#00000000'
self.sel_shapes.add(meas_line, color=color, update=True, layer=0, tolerance=None)
if self.app.is_legacy is True:
self.sel_shapes.redraw()
def delete_shape(self):
self.sel_shapes.clear()

View File

@ -44,7 +44,11 @@ class ToolMove(FlatCAMTool):
self.old_coords = []
# VisPy visuals
self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)
if self.app.is_legacy is False:
self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)
else:
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.sel_shapes = ShapeCollectionLegacy(obj=self, app=self.app, name="move")
self.replot_signal[list].connect(self.replot)
@ -62,10 +66,16 @@ class ToolMove(FlatCAMTool):
if self.isVisible():
self.setVisible(False)
self.app.plotcanvas.vis_disconnect('mouse_move', self.on_move)
self.app.plotcanvas.vis_disconnect('mouse_press', self.on_left_click)
self.app.plotcanvas.vis_disconnect('key_release', self.on_key_press)
self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent)
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_move)
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.on_left_click)
self.app.plotcanvas.graph_event_disconnect('key_release', self.on_key_press)
self.app.plotcanvas.graph_event_connect('key_press', self.app.ui.keyPressEvent)
else:
self.app.plotcanvas.graph_event_disconnect(self.mm)
self.app.plotcanvas.graph_event_disconnect(self.mp)
self.app.plotcanvas.graph_event_disconnect(self.kr)
self.app.kr = self.app.plotcanvas.graph_event_connect('key_press', self.app.ui.keyPressEvent)
self.clicked_move = 0
@ -95,9 +105,14 @@ class ToolMove(FlatCAMTool):
# this is necessary because right mouse click and middle mouse click
# are used for panning on the canvas
if self.app.is_legacy is False:
event_pos = event.pos
else:
event_pos = (event.xdata, event.ydata)
if event.button == 1:
if self.clicked_move == 0:
pos_canvas = self.app.plotcanvas.translate_coords(event.pos)
pos_canvas = self.app.plotcanvas.translate_coords(event_pos)
# if GRID is active we need to get the snapped positions
if self.app.grid_status() == True:
@ -114,7 +129,7 @@ class ToolMove(FlatCAMTool):
if self.clicked_move == 1:
try:
pos_canvas = self.app.plotcanvas.translate_coords(event.pos)
pos_canvas = self.app.plotcanvas.translate_coords(event_pos)
# delete the selection bounding box
self.delete_shape()
@ -174,7 +189,8 @@ class ToolMove(FlatCAMTool):
self.toggle()
return
except TypeError:
except TypeError as e:
log.debug("ToolMove.on_left_click() --> %s" % str(e))
self.app.inform.emit('[ERROR_NOTCL] %s' %
_('ToolMove.on_left_click() --> Error when mouse left click.'))
return
@ -191,7 +207,19 @@ class ToolMove(FlatCAMTool):
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
def on_move(self, event):
pos_canvas = self.app.plotcanvas.translate_coords(event.pos)
if self.app.is_legacy is False:
event_pos = event.pos
else:
event_pos = (event.xdata, event.ydata)
try:
x = float(event_pos[0])
y = float(event_pos[1])
except TypeError:
return
pos_canvas = self.app.plotcanvas.translate_coords((x, y))
# if GRID is active we need to get the snapped positions
if self.app.grid_status() == True:
@ -228,9 +256,9 @@ class ToolMove(FlatCAMTool):
self.toggle()
else:
# if we have an object selected then we can safely activate the mouse events
self.app.plotcanvas.vis_connect('mouse_move', self.on_move)
self.app.plotcanvas.vis_connect('mouse_press', self.on_left_click)
self.app.plotcanvas.vis_connect('key_release', self.on_key_press)
self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_move)
self.mp = self.app.plotcanvas.graph_event_connect('mouse_press', self.on_left_click)
self.kr = self.app.plotcanvas.graph_event_connect('key_release', self.on_key_press)
# first get a bounding box to fit all
for obj in obj_list:
xmin, ymin, xmax, ymax = obj.bounds()
@ -249,8 +277,12 @@ class ToolMove(FlatCAMTool):
p2 = (xmaximal, yminimal)
p3 = (xmaximal, ymaximal)
p4 = (xminimal, ymaximal)
self.old_coords = [p1, p2, p3, p4]
self.draw_shape(self.old_coords)
self.draw_shape(Polygon(self.old_coords))
if self.app.is_legacy is True:
self.sel_shapes.redraw()
def update_sel_bbox(self, pos):
self.delete_shape()
@ -259,24 +291,30 @@ class ToolMove(FlatCAMTool):
pt2 = (self.old_coords[1][0] + pos[0], self.old_coords[1][1] + pos[1])
pt3 = (self.old_coords[2][0] + pos[0], self.old_coords[2][1] + pos[1])
pt4 = (self.old_coords[3][0] + pos[0], self.old_coords[3][1] + pos[1])
self.draw_shape(Polygon([pt1, pt2, pt3, pt4]))
self.draw_shape([pt1, pt2, pt3, pt4])
if self.app.is_legacy is True:
self.sel_shapes.redraw()
def delete_shape(self):
self.sel_shapes.clear()
self.sel_shapes.redraw()
def draw_shape(self, coords):
self.sel_rect = Polygon(coords)
if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
self.sel_rect = self.sel_rect.buffer(-0.1)
self.sel_rect = self.sel_rect.buffer(0.2)
else:
self.sel_rect = self.sel_rect.buffer(-0.00393)
self.sel_rect = self.sel_rect.buffer(0.00787)
def draw_shape(self, shape):
blue_t = Color('blue')
blue_t.alpha = 0.2
self.sel_shapes.add(self.sel_rect, color='blue', face_color=blue_t, update=True, layer=0, tolerance=None)
if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
proc_shape = shape.buffer(-0.1)
proc_shape = proc_shape.buffer(0.2)
else:
proc_shape = shape.buffer(-0.00393)
proc_shape = proc_shape.buffer(0.00787)
# face = Color('blue')
# face.alpha = 0.2
face = '#0000FFAF' + str(hex(int(0.2 * 255)))[2:]
outline = '#0000FFAF'
self.sel_shapes.add(proc_shape, color=outline, face_color=face, update=True, layer=0, tolerance=None)
# end of file

View File

@ -470,10 +470,21 @@ class NonCopperClear(FlatCAMTool, Gerber):
self.bound_obj_name = ""
self.bound_obj = None
self.ncc_dia_list = []
self.iso_dia_list = []
self.has_offset = None
self.o_name = None
self.overlap = None
self.connect = None
self.contour = None
self.rest = None
self.first_click = False
self.cursor_pos = None
self.mouse_is_dragging = False
self.mm = None
self.mr = None
# store here solid_geometry when there are tool with isolation job
self.solid_geometry = []
@ -1057,27 +1068,27 @@ class NonCopperClear(FlatCAMTool, Gerber):
self.app.report_usage(_("on_paint_button_click"))
try:
overlap = float(self.ncc_overlap_entry.get_value())
self.overlap = float(self.ncc_overlap_entry.get_value())
except ValueError:
# try to convert comma to decimal point. if it's still not working error message and return
try:
overlap = float(self.ncc_overlap_entry.get_value().replace(',', '.'))
self.overlap = float(self.ncc_overlap_entry.get_value().replace(',', '.'))
except ValueError:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, "
"use a number."))
return
if overlap >= 1 or overlap < 0:
if self.overlap >= 1 or self.overlap < 0:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Overlap value must be between "
"0 (inclusive) and 1 (exclusive), "))
return
connect = self.ncc_connect_cb.get_value()
contour = self.ncc_contour_cb.get_value()
self.connect = self.ncc_connect_cb.get_value()
self.contour = self.ncc_contour_cb.get_value()
has_offset = self.ncc_choice_offset_cb.isChecked()
self.has_offset = self.ncc_choice_offset_cb.isChecked()
rest = self.ncc_rest_cb.get_value()
self.rest = self.ncc_rest_cb.get_value()
self.obj_name = self.object_combo.currentText()
# Get source object.
@ -1092,34 +1103,34 @@ class NonCopperClear(FlatCAMTool, Gerber):
return
# use the selected tools in the tool table; get diameters for non-copper clear
iso_dia_list = list()
self.iso_dia_list = list()
# use the selected tools in the tool table; get diameters for non-copper clear
ncc_dia_list = list()
self.ncc_dia_list = list()
if self.tools_table.selectedItems():
for x in self.tools_table.selectedItems():
try:
tooldia = float(self.tools_table.item(x.row(), 1).text())
self.tooldia = float(self.tools_table.item(x.row(), 1).text())
except ValueError:
# try to convert comma to decimal point. if it's still not working error message and return
try:
tooldia = float(self.tools_table.item(x.row(), 1).text().replace(',', '.'))
self.tooldia = float(self.tools_table.item(x.row(), 1).text().replace(',', '.'))
except ValueError:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong Tool Dia value format entered, "
"use a number."))
continue
if self.tools_table.cellWidget(x.row(), 4).currentText() == 'iso_op':
iso_dia_list.append(tooldia)
self.iso_dia_list.append(self.tooldia)
else:
ncc_dia_list.append(tooldia)
self.ncc_dia_list.append(self.tooldia)
else:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("No selected tools in Tool Table."))
return
o_name = '%s_ncc' % self.obj_name
self.o_name = '%s_ncc' % self.obj_name
select_method = self.reference_radio.get_value()
if select_method == 'itself':
self.select_method = self.reference_radio.get_value()
if self.select_method == 'itself':
self.bound_obj_name = self.object_combo.currentText()
# Get source object.
try:
@ -1129,138 +1140,29 @@ class NonCopperClear(FlatCAMTool, Gerber):
return "Could not retrieve object: %s" % self.obj_name
self.clear_copper(ncc_obj=self.ncc_obj,
ncctooldia=ncc_dia_list,
isotooldia=iso_dia_list,
has_offset=has_offset,
outname=o_name,
overlap=overlap,
connect=connect,
contour=contour,
rest=rest)
elif select_method == 'area':
ncctooldia=self.ncc_dia_list,
isotooldia=self.iso_dia_list,
has_offset=self.has_offset,
outname=self.o_name,
overlap=self.overlap,
connect=self.connect,
contour=self.contour,
rest=self.rest)
elif self.select_method == 'area':
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the start point of the area."))
# use the first tool in the tool table; get the diameter
# tooldia = float('%.4f' % float(self.tools_table.item(0, 1).text()))
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
else:
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
self.app.plotcanvas.graph_event_disconnect(self.app.mm)
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
# To be called after clicking on the plot.
def on_mouse_release(event):
# do clear area only for left mouse clicks
if event.button == 1:
if self.first_click is False:
self.first_click = True
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the end point of the paint area."))
self.cursor_pos = self.app.plotcanvas.translate_coords(event.pos)
if self.app.grid_status() == True:
self.cursor_pos = self.app.geo_editor.snap(self.cursor_pos[0], self.cursor_pos[1])
else:
self.app.inform.emit(_("Zone added. Click to start adding next zone or right click to finish."))
self.app.delete_selection_shape()
curr_pos = self.app.plotcanvas.translate_coords(event.pos)
if self.app.grid_status() == True:
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
x0, y0 = self.cursor_pos[0], self.cursor_pos[1]
x1, y1 = curr_pos[0], curr_pos[1]
pt1 = (x0, y0)
pt2 = (x1, y0)
pt3 = (x1, y1)
pt4 = (x0, y1)
self.sel_rect.append(Polygon([pt1, pt2, pt3, pt4]))
self.first_click = False
return
# modifiers = QtWidgets.QApplication.keyboardModifiers()
#
# if modifiers == QtCore.Qt.ShiftModifier:
# mod_key = 'Shift'
# elif modifiers == QtCore.Qt.ControlModifier:
# mod_key = 'Control'
# else:
# mod_key = None
#
# if mod_key == self.app.defaults["global_mselect_key"]:
# self.first_click = False
# return
#
# self.sel_rect = cascaded_union(self.sel_rect)
# self.clear_copper(ncc_obj=self.ncc_obj,
# sel_obj=self.bound_obj,
# ncctooldia=ncc_dia_list,
# isotooldia=iso_dia_list,
# has_offset=has_offset,
# outname=o_name,
# overlap=overlap,
# connect=connect,
# contour=contour,
# rest=rest)
#
# self.app.plotcanvas.vis_disconnect('mouse_release', on_mouse_release)
# self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move)
#
# self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
# self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
# self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
elif event.button == 2 and self.mouse_is_dragging == False:
self.first_click = False
self.app.plotcanvas.vis_disconnect('mouse_release', on_mouse_release)
self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move)
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
if len(self.sel_rect) == 0:
return
self.sel_rect = cascaded_union(self.sel_rect)
self.clear_copper(ncc_obj=self.ncc_obj,
sel_obj=self.bound_obj,
ncctooldia=ncc_dia_list,
isotooldia=iso_dia_list,
has_offset=has_offset,
outname=o_name,
overlap=overlap,
connect=connect,
contour=contour,
rest=rest)
# called on mouse move
def on_mouse_move(event):
curr_pos = self.app.plotcanvas.translate_coords(event.pos)
self.app.app_cursor.enabled = False
# detect mouse dragging motion
if event.is_dragging is True:
self.mouse_is_dragging = True
else:
self.mouse_is_dragging = False
# update the cursor position
if self.app.grid_status() == True:
self.app.app_cursor.enabled = True
# Update cursor
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color='black', size=20)
# draw the utility geometry
if self.first_click:
self.app.delete_selection_shape()
self.app.draw_moving_selection_shape(old_coords=(self.cursor_pos[0], self.cursor_pos[1]),
coords=(curr_pos[0], curr_pos[1]),
face_alpha=0.0)
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_connect('mouse_release', on_mouse_release)
self.app.plotcanvas.vis_connect('mouse_move', on_mouse_move)
elif select_method == 'box':
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release)
self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
elif self.select_method == 'box':
self.bound_obj_name = self.box_combo.currentText()
# Get source object.
try:
@ -1271,14 +1173,133 @@ class NonCopperClear(FlatCAMTool, Gerber):
self.clear_copper(ncc_obj=self.ncc_obj,
sel_obj=self.bound_obj,
ncctooldia=ncc_dia_list,
isotooldia=iso_dia_list,
has_offset=has_offset,
outname=o_name,
overlap=overlap,
connect=connect,
contour=contour,
rest=rest)
ncctooldia=self.ncc_dia_list,
isotooldia=self.iso_dia_list,
has_offset=self.has_offset,
outname=self.o_name,
overlap=self.overlap,
connect=self.connect,
contour=self.contour,
rest=self.rest)
# To be called after clicking on the plot.
def on_mouse_release(self, event):
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
event_pos = self.app.plotcanvas.translate_coords(event_pos)
# do clear area only for left mouse clicks
if event.button == 1:
if self.first_click is False:
self.first_click = True
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the end point of the paint area."))
self.cursor_pos = self.app.plotcanvas.translate_coords(event_pos)
if self.app.grid_status() == True:
self.cursor_pos = self.app.geo_editor.snap(event_pos[0], event_pos[1])
else:
self.app.inform.emit(_("Zone added. Click to start adding next zone or right click to finish."))
self.app.delete_selection_shape()
if self.app.grid_status() == True:
curr_pos = self.app.geo_editor.snap(event_pos[0], event_pos[1])
else:
curr_pos = (event_pos[0], event_pos[1])
x0, y0 = self.cursor_pos[0], self.cursor_pos[1]
x1, y1 = curr_pos[0], curr_pos[1]
pt1 = (x0, y0)
pt2 = (x1, y0)
pt3 = (x1, y1)
pt4 = (x0, y1)
self.sel_rect.append(Polygon([pt1, pt2, pt3, pt4]))
self.first_click = False
return
elif event.button == right_button and self.mouse_is_dragging == False:
self.first_click = False
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_release)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
else:
self.app.plotcanvas.graph_event_disconnect(self.mr)
self.app.plotcanvas.graph_event_disconnect(self.mm)
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
self.app.on_mouse_click_over_plot)
self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move',
self.app.on_mouse_move_over_plot)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot)
if len(self.sel_rect) == 0:
return
self.sel_rect = cascaded_union(self.sel_rect)
self.clear_copper(ncc_obj=self.ncc_obj,
sel_obj=self.bound_obj,
ncctooldia=self.ncc_dia_list,
isotooldia=self.iso_dia_list,
has_offset=self.has_offset,
outname=self.o_name,
overlap=self.overlap,
connect=self.connect,
contour=self.contour,
rest=self.rest)
# called on mouse move
def on_mouse_move(self, event):
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
curr_pos = self.app.plotcanvas.translate_coords(event_pos)
# detect mouse dragging motion
if event_is_dragging is True:
self.mouse_is_dragging = True
else:
self.mouse_is_dragging = False
# update the cursor position
if self.app.grid_status() == True:
# Update cursor
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color='black', size=20)
# update the positions on status bar
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"<b>Y</b>: %.4f" % (curr_pos[0], curr_pos[1]))
if self.cursor_pos is None:
self.cursor_pos = (0, 0)
dx = curr_pos[0] - float(self.cursor_pos[0])
dy = curr_pos[1] - float(self.cursor_pos[1])
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
# draw the utility geometry
if self.first_click:
self.app.delete_selection_shape()
self.app.draw_moving_selection_shape(old_coords=(self.cursor_pos[0], self.cursor_pos[1]),
coords=(curr_pos[0], curr_pos[1]))
def clear_copper(self, ncc_obj,
sel_obj=None,

View File

@ -357,6 +357,13 @@ class ToolPaint(FlatCAMTool, Gerber):
self.bound_obj_name = ""
self.bound_obj = None
self.tooldia_list = []
self.sel_rect = None
self.o_name = None
self.overlap = None
self.connect = None
self.contour = None
self.units = ''
self.paint_tools = {}
self.tooluid = 0
@ -364,6 +371,9 @@ class ToolPaint(FlatCAMTool, Gerber):
self.cursor_pos = None
self.mouse_is_dragging = False
self.mm = None
self.mp = None
self.sel_rect = []
# store here the default data for Geometry Data
@ -916,17 +926,17 @@ class ToolPaint(FlatCAMTool, Gerber):
self.app.inform.emit(_("Paint Tool. Reading parameters."))
try:
overlap = float(self.paintoverlap_entry.get_value())
self.overlap = float(self.paintoverlap_entry.get_value())
except ValueError:
# try to convert comma to decimal point. if it's still not working error message and return
try:
overlap = float(self.paintoverlap_entry.get_value().replace(',', '.'))
self.overlap = float(self.paintoverlap_entry.get_value().replace(',', '.'))
except ValueError:
self.app.inform.emit('[ERROR_NOTCL] %s' %
_("Wrong value format entered, use a number."))
return
if overlap >= 1 or overlap < 0:
if self.overlap >= 1 or self.overlap < 0:
self.app.inform.emit('[ERROR_NOTCL] %s' %
_("Overlap value must be between 0 (inclusive) and 1 (exclusive)"))
return
@ -934,9 +944,9 @@ class ToolPaint(FlatCAMTool, Gerber):
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Click inside the desired polygon."))
connect = self.pathconnect_cb.get_value()
contour = self.paintcontour_cb.get_value()
select_method = self.selectmethod_combo.get_value()
self.connect = self.pathconnect_cb.get_value()
self.contour = self.paintcontour_cb.get_value()
self.select_method = self.selectmethod_combo.get_value()
self.obj_name = self.obj_combo.currentText()
@ -966,34 +976,34 @@ class ToolPaint(FlatCAMTool, Gerber):
o_name = '%s_multitool_paint' % self.obj_name
# use the selected tools in the tool table; get diameters
tooldia_list = list()
self.tooldia_list = list()
if self.tools_table.selectedItems():
for x in self.tools_table.selectedItems():
try:
tooldia = float(self.tools_table.item(x.row(), 1).text())
self.tooldia = float(self.tools_table.item(x.row(), 1).text())
except ValueError:
# try to convert comma to decimal point. if it's still not working error message and return
try:
tooldia = float(self.tools_table.item(x.row(), 1).text().replace(',', '.'))
self.tooldia = float(self.tools_table.item(x.row(), 1).text().replace(',', '.'))
except ValueError:
self.app.inform.emit('[ERROR_NOTCL] %s' %
_("Wrong value format entered, use a number."))
continue
tooldia_list.append(tooldia)
self.tooldia_list.append(self.tooldia)
else:
self.app.inform.emit('[ERROR_NOTCL] %s' %
_("No selected tools in Tool Table."))
return
if select_method == "all":
if self.select_method == "all":
self.paint_poly_all(self.paint_obj,
tooldia=tooldia_list,
outname=o_name,
overlap=overlap,
connect=connect,
contour=contour)
tooldia=self.tooldia_list,
outname=self.o_name,
overlap=self.overlap,
connect=self.connect,
contour=self.contour)
elif select_method == "single":
elif self.select_method == "single":
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Click inside the desired polygon."))
@ -1005,7 +1015,10 @@ class ToolPaint(FlatCAMTool, Gerber):
# do paint single only for left mouse clicks
if event.button == 1:
self.app.inform.emit(_("Painting polygon..."))
self.app.plotcanvas.vis_disconnect('mouse_press', doit)
if self.app.is_legacy:
self.app.plotcanvas.graph_event_disconnect('mouse_press', doit)
else:
self.app.plotcanvas.graph_event_disconnect(self.mp)
pos = self.app.plotcanvas.translate_coords(event.pos)
if self.app.grid_status() == True:
@ -1013,137 +1026,40 @@ class ToolPaint(FlatCAMTool, Gerber):
self.paint_poly(self.paint_obj,
inside_pt=[pos[0], pos[1]],
tooldia=tooldia_list,
overlap=overlap,
connect=connect,
contour=contour)
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
tooldia=self.tooldia_list,
overlap=self.overlap,
connect=self.connect,
contour=self.contour)
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
self.app.on_mouse_click_over_plot)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_connect('mouse_press', doit)
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
else:
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
self.mp = self.app.plotcanvas.graph_event_connect('mouse_press', doit)
elif select_method == "area":
elif self.select_method == "area":
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Click the start point of the paint area."))
# use the first tool in the tool table; get the diameter
# tooldia = float('%.4f' % float(self.tools_table.item(0, 1).text()))
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
else:
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
self.app.plotcanvas.graph_event_disconnect(self.app.mm)
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
# To be called after clicking on the plot.
def on_mouse_release(event):
# do paint single only for left mouse clicks
if event.button == 1:
if not self.first_click:
self.first_click = True
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Click the end point of the paint area."))
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release)
self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
self.cursor_pos = self.app.plotcanvas.translate_coords(event.pos)
if self.app.grid_status() == True:
self.cursor_pos = self.app.geo_editor.snap(self.cursor_pos[0], self.cursor_pos[1])
else:
self.app.inform.emit(_("Zone added. Click to start adding next zone or right click to finish."))
self.app.delete_selection_shape()
curr_pos = self.app.plotcanvas.translate_coords(event.pos)
if self.app.grid_status() == True:
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
x0, y0 = self.cursor_pos[0], self.cursor_pos[1]
x1, y1 = curr_pos[0], curr_pos[1]
pt1 = (x0, y0)
pt2 = (x1, y0)
pt3 = (x1, y1)
pt4 = (x0, y1)
self.sel_rect.append(Polygon([pt1, pt2, pt3, pt4]))
self.first_click = False
return
# modifiers = QtWidgets.QApplication.keyboardModifiers()
#
# if modifiers == QtCore.Qt.ShiftModifier:
# mod_key = 'Shift'
# elif modifiers == QtCore.Qt.ControlModifier:
# mod_key = 'Control'
# else:
# mod_key = None
#
# if mod_key == self.app.defaults["global_mselect_key"]:
# self.first_click = False
# return
#
# self.sel_rect = cascaded_union(self.sel_rect)
# self.paint_poly_area(obj=self.paint_obj,
# tooldia=tooldia_list,
# sel_obj= self.sel_rect,
# outname=o_name,
# overlap=overlap,
# connect=connect,
# contour=contour)
#
# self.app.plotcanvas.vis_disconnect('mouse_release', on_mouse_release)
# self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move)
#
# self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
# self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
# self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
elif event.button == 2 and self.mouse_is_dragging is False:
self.first_click = False
self.app.plotcanvas.vis_disconnect('mouse_release', on_mouse_release)
self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move)
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
if len(self.sel_rect) == 0:
return
self.sel_rect = cascaded_union(self.sel_rect)
self.paint_poly_area(obj=self.paint_obj,
tooldia=tooldia_list,
sel_obj=self.sel_rect,
outname=o_name,
overlap=overlap,
connect=connect,
contour=contour)
# called on mouse move
def on_mouse_move(event):
curr_pos = self.app.plotcanvas.translate_coords(event.pos)
self.app.app_cursor.enabled = False
# detect mouse dragging motion
if event.is_dragging is True:
self.mouse_is_dragging = True
else:
self.mouse_is_dragging = False
# update the cursor position
if self.app.grid_status() == True:
self.app.app_cursor.enabled = True
# Update cursor
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color='black', size=20)
# draw the utility geometry
if self.first_click:
self.app.delete_selection_shape()
self.app.draw_moving_selection_shape(old_coords=(self.cursor_pos[0], self.cursor_pos[1]),
coords=(curr_pos[0], curr_pos[1]),
face_alpha=0.0)
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.plotcanvas.vis_connect('mouse_release', on_mouse_release)
self.app.plotcanvas.vis_connect('mouse_move', on_mouse_move)
elif select_method == 'ref':
elif self.select_method == 'ref':
self.bound_obj_name = self.box_combo.currentText()
# Get source object.
try:
@ -1156,11 +1072,137 @@ class ToolPaint(FlatCAMTool, Gerber):
self.paint_poly_ref(obj=self.paint_obj,
sel_obj=self.bound_obj,
tooldia=tooldia_list,
overlap=overlap,
outname=o_name,
connect=connect,
contour=contour)
tooldia=self.tooldia_list,
overlap=self.overlap,
outname=self.o_name,
connect=self.connect,
contour=self.contour)
# To be called after clicking on the plot.
def on_mouse_release(self, event):
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
try:
x = float(event_pos[0])
y = float(event_pos[1])
except TypeError:
return
event_pos = (x, y)
# do paint single only for left mouse clicks
if event.button == 1:
if not self.first_click:
self.first_click = True
self.app.inform.emit('[WARNING_NOTCL] %s' %
_("Click the end point of the paint area."))
self.cursor_pos = self.app.plotcanvas.translate_coords(event_pos)
if self.app.grid_status() == True:
self.cursor_pos = self.app.geo_editor.snap(self.cursor_pos[0], self.cursor_pos[1])
else:
self.app.inform.emit(_("Zone added. Click to start adding next zone or right click to finish."))
self.app.delete_selection_shape()
curr_pos = self.app.plotcanvas.translate_coords(event_pos)
if self.app.grid_status() == True:
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
x0, y0 = self.cursor_pos[0], self.cursor_pos[1]
x1, y1 = curr_pos[0], curr_pos[1]
pt1 = (x0, y0)
pt2 = (x1, y0)
pt3 = (x1, y1)
pt4 = (x0, y1)
self.sel_rect.append(Polygon([pt1, pt2, pt3, pt4]))
self.first_click = False
return
elif event.button == right_button and self.mouse_is_dragging is False:
self.first_click = False
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_release)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
else:
self.app.plotcanvas.graph_event_disconnect(self.mr)
self.app.plotcanvas.graph_event_disconnect(self.mm)
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
self.app.on_mouse_click_over_plot)
self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move',
self.app.on_mouse_move_over_plot)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot)
if len(self.sel_rect) == 0:
return
self.sel_rect = cascaded_union(self.sel_rect)
self.paint_poly_area(obj=self.paint_obj,
tooldia=self.tooldia_list,
sel_obj=self.sel_rect,
outname=self.o_name,
overlap=self.overlap,
connect=self.connect,
contour=self.contour)
# called on mouse move
def on_mouse_move(self, event):
if self.app.is_legacy is False:
event_pos = event.pos
event_is_dragging = event.is_dragging
right_button = 2
else:
event_pos = (event.xdata, event.ydata)
event_is_dragging = self.app.plotcanvas.is_dragging
right_button = 3
try:
x = float(event_pos[0])
y = float(event_pos[1])
except TypeError:
return
curr_pos = self.app.plotcanvas.translate_coords((x, y))
# detect mouse dragging motion
if event_is_dragging == 1:
self.mouse_is_dragging = True
else:
self.mouse_is_dragging = False
# update the cursor position
if self.app.grid_status() == True:
# Update cursor
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color='black', size=20)
# update the positions on status bar
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"<b>Y</b>: %.4f" % (curr_pos[0], curr_pos[1]))
if self.cursor_pos is None:
self.cursor_pos = (0, 0)
dx = curr_pos[0] - float(self.cursor_pos[0])
dy = curr_pos[1] - float(self.cursor_pos[1])
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
# draw the utility geometry
if self.first_click:
self.app.delete_selection_shape()
self.app.draw_moving_selection_shape(old_coords=(self.cursor_pos[0], self.cursor_pos[1]),
coords=(curr_pos[0], curr_pos[1]))
def paint_poly(self, obj,
inside_pt=None,
@ -1199,13 +1241,15 @@ class ToolPaint(FlatCAMTool, Gerber):
# poly = find_polygon(self.solid_geometry, inside_pt)
if isinstance(obj, FlatCAMGerber):
if self.app.defaults["gerber_buffering"] == 'no':
self.app.inform.emit('%s %s' %
(_("Paint Tool. Normal painting polygon task started."),
self.app.inform.emit('%s %s %s' %
(_("Paint Tool."), _("Normal painting polygon task started."),
_("Buffering geometry...")))
else:
self.app.inform.emit(_("Paint Tool. Normal painting polygon task started."))
self.app.inform.emit('%s %s' %
(_("Paint Tool."), _("Normal painting polygon task started.")))
else:
self.app.inform.emit(_("Paint Tool. Normal painting polygon task started."))
self.app.inform.emit('%s %s' %
(_("Paint Tool."), _("Normal painting polygon task started.")))
if isinstance(obj, FlatCAMGerber):
if self.app.defaults["tools_paint_plotting"] == 'progressive':
@ -1243,7 +1287,8 @@ class ToolPaint(FlatCAMTool, Gerber):
return
proc = self.app.proc_container.new(_("Painting polygon..."))
self.app.inform.emit('%s: %s' % (_("Paint Tool. Painting polygon at location"), str(inside_pt)))
self.app.inform.emit('%s %s: %s' %
(_("Paint Tool."), _("Painting polygon at location"), str(inside_pt)))
name = outname if outname is not None else self.obj_name + "_paint"
@ -1769,13 +1814,15 @@ class ToolPaint(FlatCAMTool, Gerber):
log.debug("Paint Tool. Rest machining painting all task started.")
if isinstance(obj, FlatCAMGerber):
if app_obj.defaults["gerber_buffering"] == 'no':
app_obj.inform.emit('%s %s' %
(_("Paint Tool. Rest machining painting all task started."),
app_obj.inform.emit('%s %s %s' %
(_("Paint Tool."), _("Rest machining painting all task started."),
_("Buffering geometry...")))
else:
app_obj.inform.emit(_("Paint Tool. Rest machining painting all task started."))
app_obj.inform.emit('%s %s' %
(_("Paint Tool."), _("Rest machining painting all task started.")))
else:
app_obj.inform.emit(_("Paint Tool. Rest machining painting all task started."))
app_obj.inform.emit('%s %s' %
(_("Paint Tool."), _("Rest machining painting all task started.")))
tool_dia = None
sorted_tools.sort(reverse=True)
@ -2056,13 +2103,16 @@ class ToolPaint(FlatCAMTool, Gerber):
log.debug("Paint Tool. Normal painting area task started.")
if isinstance(obj, FlatCAMGerber):
if app_obj.defaults["gerber_buffering"] == 'no':
app_obj.inform.emit('%s %s' %
(_("Paint Tool. Normal painting area task started."),
app_obj.inform.emit('%s %s %s' %
(_("Paint Tool."),
_("Normal painting area task started."),
_("Buffering geometry...")))
else:
app_obj.inform.emit(_("Paint Tool. Normal painting area task started."))
app_obj.inform.emit('%s %s' %
(_("Paint Tool."), _("Normal painting area task started.")))
else:
app_obj.inform.emit(_("Paint Tool. Normal painting area task started."))
app_obj.inform.emit('%s %s' %
(_("Paint Tool."), _("Normal painting area task started.")))
tool_dia = None
if order == 'fwd':
@ -2235,13 +2285,15 @@ class ToolPaint(FlatCAMTool, Gerber):
log.debug("Paint Tool. Rest machining painting area task started.")
if isinstance(obj, FlatCAMGerber):
if app_obj.defaults["gerber_buffering"] == 'no':
app_obj.inform.emit('%s %s' %
(_("Paint Tool. Rest machining painting area task started."),
app_obj.inform.emit('%s %s %s' %
(_("Paint Tool."),
_("Rest machining painting area task started."),
_("Buffering geometry...")))
else:
app_obj.inform.emit(_("Paint Tool. Rest machining painting area task started."))
else:
app_obj.inform.emit(_("Paint Tool. Rest machining painting area task started."))
app_obj.inform.emit('%s %s' %
(_("Paint Tool."), _("Rest machining painting area task started.")))
tool_dia = None
sorted_tools.sort(reverse=True)

View File

@ -772,8 +772,8 @@ class Panelize(FlatCAMTool):
currenty += lenghty
if panel_type == 'gerber':
self.app.inform.emit('%s %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)
@ -784,8 +784,8 @@ 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 %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)

View File

@ -311,7 +311,7 @@ class ToolSub(FlatCAMTool):
log.debug("Working on promise: %s" % str(apid))
with self.app.proc_container.new('%s %s %s...' % (_("Parsing aperture", str(apid), _("geometry")))):
with self.app.proc_container.new('%s: %s...' % (_("Parsing geometry for aperture", str(apid)))):
for geo_el in geo:
new_el = dict()
@ -520,7 +520,7 @@ class ToolSub(FlatCAMTool):
if tool == "single":
text = _("Parsing solid_geometry ...")
else:
text = '%s %s %s...' % (_("Parsing tool"), str(tool), _("geometry"))
text = '%s: %s...' % (_("Parsing solid_geometry for tool"), str(tool))
with self.app.proc_container.new(text):
# resulting paths are closed resulting into Polygons

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

@ -1,7 +1,13 @@
# This file contains python only requirements to be installed with pip
# Python pacakges that cannot be installed with pip (e.g. PyQt5, GDAL) are not included.
# Usage: pip install -r requirements.txt
numpy>=1.8
numpy>=1.11
matplotlib>=3.1
cycler>=0.10
python-dateutil>=2.1
kiwisolver>=1.0.1
six
setuptools
dill
rtree
pyopengl

View File

@ -14,6 +14,9 @@ apt-get install python3-tk
apt-get install libspatialindex-dev
apt-get install python3-gdal
apt-get install python3-lxml
pip3 install --upgrade cycler
pip3 install --upgrade python-dateutil
pip3 install --upgrade kiwisolver
pip3 install --upgrade dill
pip3 install --upgrade Shapely
pip3 install --upgrade vispy

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 30 KiB

BIN
share/active_2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
share/active_2_static.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

BIN
share/active_3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
share/active_3_static.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

BIN
share/active_4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
share/active_4_static.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

BIN
share/active_static.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

BIN
share/script14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

@ -42,5 +42,5 @@ class TclCommandPlotAll(TclCommand):
:param unnamed_args:
:return:
"""
self.app.plot_all()
if self.app.cmd_line_headless != 1:
self.app.plot_all()

View File

@ -42,10 +42,11 @@ class TclCommandPlotObjects(TclCommand):
:param unnamed_args:
:return:
"""
names = [x.strip() for x in args['names'].split(",")]
objs = []
for name in names:
objs.append(self.app.collection.get_by_name(name))
if self.app.cmd_line_headless != 1:
names = [x.strip() for x in args['names'].split(",")]
objs = []
for name in names:
objs.append(self.app.collection.get_by_name(name))
for obj in objs:
obj.plot()
for obj in objs:
obj.plot()

View File

@ -0,0 +1,47 @@
from ObjectCollection import *
from tclCommands.TclCommand import TclCommand
class TclCommandQuit(TclCommand):
"""
Tcl shell command to quit FlatCAM from Tcl shell.
example:
"""
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
aliases = ['quit_flatcam']
# Dictionary of types from Tcl command, needs to be ordered
arg_names = collections.OrderedDict([
])
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
option_types = collections.OrderedDict([
])
# array of mandatory options for current Tcl command: required = {'name','outname'}
required = []
# structured help for current command, args needs to be ordered
help = {
'main': "Tcl shell command to quit FlatCAM from Tcl shell.",
'args': collections.OrderedDict([
]),
'examples': ['quit_flatcam']
}
def execute(self, args, unnamed_args):
"""
:param args:
:param unnamed_args:
:return:
"""
self.app.quit_application()

View File

@ -48,6 +48,7 @@ import tclCommands.TclCommandPaint
import tclCommands.TclCommandPanelize
import tclCommands.TclCommandPlotAll
import tclCommands.TclCommandPlotObjects
import tclCommands.TclCommandQuit
import tclCommands.TclCommandSaveProject
import tclCommands.TclCommandSaveSys
import tclCommands.TclCommandScale

158
tests/titlebar_custom.py Normal file
View File

@ -0,0 +1,158 @@
#########################################################
## customize Title bar
## dotpy.ir
## iraj.jelo@gmail.com
#########################################################
import sys
from PyQt5 import QtWidgets, QtGui
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
class TitleBar(QtWidgets.QDialog):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.setWindowFlags(Qt.FramelessWindowHint)
css = """
QWidget{
Background: #0000FF;
color:white;
font:12px bold;
font-weight:bold;
border-radius: 1px;
height: 11px;
}
QDialog{
Background-image:url('img/titlebar bg.png');
font-size:12px;
color: black;
}
QToolButton{
Background:#AA00AA;
font-size:11px;
}
QToolButton:hover{
Background: #FF00FF;
font-size:11px;
}
"""
self.setAutoFillBackground(True)
self.setBackgroundRole(QtGui.QPalette.Highlight)
self.setStyleSheet(css)
self.minimize=QtWidgets.QToolButton(self)
self.minimize.setIcon(QtGui.QIcon('img/min.png'))
self.maximize=QtWidgets.QToolButton(self)
self.maximize.setIcon(QtGui.QIcon('img/max.png'))
close=QtWidgets.QToolButton(self)
close.setIcon(QtGui.QIcon('img/close.png'))
self.minimize.setMinimumHeight(10)
close.setMinimumHeight(10)
self.maximize.setMinimumHeight(10)
label=QtWidgets.QLabel(self)
label.setText("Window Title")
self.setWindowTitle("Window Title")
hbox=QtWidgets.QHBoxLayout(self)
hbox.addWidget(label)
hbox.addWidget(self.minimize)
hbox.addWidget(self.maximize)
hbox.addWidget(close)
hbox.insertStretch(1,500)
hbox.setSpacing(0)
self.setSizePolicy(QtWidgets.QSizePolicy.Expanding,QtWidgets.QSizePolicy.Fixed)
self.maxNormal=False
close.clicked.connect(self.close)
self.minimize.clicked.connect(self.showSmall)
self.maximize.clicked.connect(self.showMaxRestore)
def showSmall(self):
box.showMinimized()
def showMaxRestore(self):
if(self.maxNormal):
box.showNormal()
self.maxNormal= False
self.maximize.setIcon(QtGui.QIcon('img/max.png'))
else:
box.showMaximized()
self.maxNormal = True
self.maximize.setIcon(QtGui.QIcon('img/max2.png'))
def close(self):
box.close()
def mousePressEvent(self,event):
if event.button() == Qt.LeftButton:
box.moving = True
box.offset = event.pos()
if event.type() == QtCore.QEvent.MouseButtonDblClick:
self.showMaxRestore()
def mouseMoveEvent(self,event):
if box.isMaximized():
self.showMaxRestore()
box.move(event.globalPos() - box.offset)
else:
if box.moving:
box.move(event.globalPos()-box.offset)
class Frame(QtWidgets.QFrame):
def __init__(self, parent=None):
QtWidgets.QFrame.__init__(self, parent)
self.m_mouse_down= False
self.setFrameShape(QtWidgets.QFrame.StyledPanel)
css = """
QFrame{
Background: #FFFFF0;
color:white;
font:13px ;
font-weight:bold;
}
"""
self.setStyleSheet(css)
self.setWindowFlags(Qt.FramelessWindowHint)
self.setMouseTracking(True)
self.m_titleBar= TitleBar(self)
self.m_content= QtWidgets.QWidget(self)
vbox=QtWidgets.QVBoxLayout(self)
vbox.addWidget(self.m_titleBar)
vbox.setContentsMargins(0, 0, 0, 0)
vbox.setSpacing(0)
layout=QtWidgets.QVBoxLayout()
layout.addWidget(self.m_content)
layout.setContentsMargins(5, 5, 5, 5)
layout.setSpacing(0)
vbox.addLayout(layout)
# Allows you to access the content area of the frame
# where widgets and layouts can be added
def contentWidget(self):
return self.m_content
def titleBar(self):
return self.m_titleBar
def mousePressEvent(self,event):
self.m_old_pos = event.pos()
self.m_mouse_down = event.button()== Qt.LeftButton
def mouseMoveEvent(self,event):
x=event.x()
y=event.y()
def mouseReleaseEvent(self,event):
m_mouse_down=False
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
box = Frame()
box.move(60,60)
l=QtWidgets.QVBoxLayout(box.contentWidget())
l.setContentsMargins(0, 0, 0, 0)
edit=QtWidgets.QLabel("""I would've did anything for you to show you how much I adored you
But it's over now, it's too late to save our loveJust promise me you'll think of me
Every time you look up in the sky and see a star 'cuz I'm your star.""")
l.addWidget(edit)
box.show()
app.exec_()