jpcgt/flatcam/Beta слито с Beta
972
FlatCAMApp.py
|
@ -12,6 +12,7 @@ from datetime import datetime
|
||||||
|
|
||||||
from flatcamGUI.ObjectUI import *
|
from flatcamGUI.ObjectUI import *
|
||||||
from FlatCAMCommon import LoudDict
|
from FlatCAMCommon import LoudDict
|
||||||
|
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||||
from camlib import *
|
from camlib import *
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
@ -74,10 +75,17 @@ class FlatCAMObj(QtCore.QObject):
|
||||||
# store here the default data for Geometry Data
|
# store here the default data for Geometry Data
|
||||||
self.default_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.kind = None # Override with proper name
|
||||||
|
|
||||||
# self.shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene)
|
# self.shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene)
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.shapes = self.app.plotcanvas.new_shape_group()
|
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 = self.app.plotcanvas.new_shape_collection(layers=2)
|
||||||
self.mark_shapes = {}
|
self.mark_shapes = {}
|
||||||
|
@ -391,6 +399,7 @@ class FlatCAMObj(QtCore.QObject):
|
||||||
def worker_task(app_obj):
|
def worker_task(app_obj):
|
||||||
self.shapes.visible = value
|
self.shapes.visible = value
|
||||||
|
|
||||||
|
if self.app.is_legacy is False:
|
||||||
# Not all object types has annotations
|
# Not all object types has annotations
|
||||||
try:
|
try:
|
||||||
self.annotation.visible = value
|
self.annotation.visible = value
|
||||||
|
@ -627,8 +636,13 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
self.ui.create_buffer_button.hide()
|
self.ui.create_buffer_button.hide()
|
||||||
|
|
||||||
# add the shapes storage for marking apertures
|
# add the shapes storage for marking apertures
|
||||||
|
if self.app.is_legacy is False:
|
||||||
for ap_code in self.apertures:
|
for ap_code in self.apertures:
|
||||||
self.mark_shapes[ap_code] = self.app.plotcanvas.new_shape_collection(layers=2)
|
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
|
# set initial state of the aperture table and associated widgets
|
||||||
self.on_aperture_table_visibility_change()
|
self.on_aperture_table_visibility_change()
|
||||||
|
@ -1342,10 +1356,26 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
geometry = [geometry]
|
geometry = [geometry]
|
||||||
|
|
||||||
|
if self.app.is_legacy is False:
|
||||||
def random_color():
|
def random_color():
|
||||||
color = np.random.rand(4)
|
color = np.random.rand(4)
|
||||||
color[3] = 1
|
color[3] = 1
|
||||||
return color
|
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:
|
try:
|
||||||
if self.options["solid"]:
|
if self.options["solid"]:
|
||||||
|
@ -1380,11 +1410,14 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
self.shapes.redraw()
|
self.shapes.redraw()
|
||||||
except (ObjectDeleted, AttributeError):
|
except (ObjectDeleted, AttributeError):
|
||||||
self.shapes.clear(update=True)
|
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
|
# 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
|
:param kwargs: color and face_color
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
@ -1414,11 +1447,10 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
else:
|
else:
|
||||||
visibility = kwargs['visible']
|
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)
|
self.app.progress.emit(30)
|
||||||
|
|
||||||
def job_thread(app_obj):
|
def job_thread(app_obj):
|
||||||
self.app.progress.emit(30)
|
|
||||||
try:
|
try:
|
||||||
if aperture_to_plot_mark in self.apertures:
|
if aperture_to_plot_mark in self.apertures:
|
||||||
for elem in self.apertures[aperture_to_plot_mark]['geometry']:
|
for elem in self.apertures[aperture_to_plot_mark]['geometry']:
|
||||||
|
@ -1433,12 +1465,16 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
face_color=color, visible=visibility)
|
face_color=color, visible=visibility)
|
||||||
|
|
||||||
self.mark_shapes[aperture_to_plot_mark].redraw()
|
self.mark_shapes[aperture_to_plot_mark].redraw()
|
||||||
self.app.progress.emit(100)
|
|
||||||
|
|
||||||
except (ObjectDeleted, AttributeError):
|
except (ObjectDeleted, AttributeError):
|
||||||
self.clear_plot_apertures()
|
self.clear_plot_apertures()
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
|
||||||
|
if run_thread:
|
||||||
self.app.worker_task.emit({'fcn': job_thread, 'params': [self]})
|
self.app.worker_task.emit({'fcn': job_thread, 'params': [self]})
|
||||||
|
else:
|
||||||
|
job_thread(self)
|
||||||
|
|
||||||
def clear_plot_apertures(self, aperture='all'):
|
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():
|
if self.ui.apertures_table.cellWidget(cw_row, 5).isChecked():
|
||||||
self.marked_rows.append(True)
|
self.marked_rows.append(True)
|
||||||
# self.plot_aperture(color='#2d4606bf', marked_aperture=aperture, visible=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.plot_aperture(color=self.app.defaults['global_sel_draw_color'] + 'FF',
|
||||||
self.mark_shapes[aperture].redraw()
|
marked_aperture=aperture, visible=True, run_thread=True)
|
||||||
|
# self.mark_shapes[aperture].redraw()
|
||||||
else:
|
else:
|
||||||
self.marked_rows.append(False)
|
self.marked_rows.append(False)
|
||||||
self.clear_plot_apertures(aperture=aperture)
|
self.clear_plot_apertures(aperture=aperture)
|
||||||
|
@ -1519,7 +1556,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
if mark_all:
|
if mark_all:
|
||||||
for aperture in self.apertures:
|
for aperture in self.apertures:
|
||||||
# self.plot_aperture(color='#2d4606bf', marked_aperture=aperture, visible=True)
|
# 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)
|
marked_aperture=aperture, visible=True)
|
||||||
# HACK: enable/disable the grid for a better look
|
# HACK: enable/disable the grid for a better look
|
||||||
self.app.ui.grid_snap_btn.trigger()
|
self.app.ui.grid_snap_btn.trigger()
|
||||||
|
@ -5349,7 +5386,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
||||||
|
|
||||||
return factor
|
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']
|
visible = visible if visible else self.options['plot']
|
||||||
|
|
||||||
|
@ -5358,8 +5395,10 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
||||||
self.plot_element(sub_el)
|
self.plot_element(sub_el)
|
||||||
|
|
||||||
except TypeError: # Element is not iterable...
|
except TypeError: # Element is not iterable...
|
||||||
|
# if self.app.is_legacy is False:
|
||||||
self.add_shape(shape=element, color=color, visible=visible, layer=0)
|
self.add_shape(shape=element, color=color, visible=visible, layer=0)
|
||||||
|
|
||||||
|
|
||||||
def plot(self, visible=None, kind=None):
|
def plot(self, visible=None, kind=None):
|
||||||
"""
|
"""
|
||||||
Plot the object.
|
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=visible)
|
||||||
|
|
||||||
# self.plot_element(self.solid_geometry, visible=self.options['plot'])
|
# self.plot_element(self.solid_geometry, visible=self.options['plot'])
|
||||||
|
|
||||||
self.shapes.redraw()
|
self.shapes.redraw()
|
||||||
|
|
||||||
except (ObjectDeleted, AttributeError):
|
except (ObjectDeleted, AttributeError):
|
||||||
self.shapes.clear(update=True)
|
self.shapes.clear(update=True)
|
||||||
|
|
||||||
|
@ -5551,6 +5592,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
||||||
# from predecessors.
|
# from predecessors.
|
||||||
self.ser_attrs += ['options', 'kind', 'cnc_tools', 'multitool']
|
self.ser_attrs += ['options', 'kind', 'cnc_tools', 'multitool']
|
||||||
|
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.text_col = self.app.plotcanvas.new_text_collection()
|
self.text_col = self.app.plotcanvas.new_text_collection()
|
||||||
self.text_col.enabled = True
|
self.text_col.enabled = True
|
||||||
self.annotation = self.app.plotcanvas.new_text_group(collection=self.text_col)
|
self.annotation = self.app.plotcanvas.new_text_group(collection=self.text_col)
|
||||||
|
@ -5728,6 +5770,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
||||||
pass
|
pass
|
||||||
self.ui.annotation_cb.stateChanged.connect(self.on_annotation_change)
|
self.ui.annotation_cb.stateChanged.connect(self.on_annotation_change)
|
||||||
|
|
||||||
|
if self.app.is_legacy is False:
|
||||||
# set if to display text annotations
|
# set if to display text annotations
|
||||||
self.ui.annotation_cb.set_value(self.app.defaults["cncjob_annotation"])
|
self.ui.annotation_cb.set_value(self.app.defaults["cncjob_annotation"])
|
||||||
|
|
||||||
|
@ -6178,6 +6221,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
||||||
|
|
||||||
visible = visible if visible else self.options['plot']
|
visible = visible if visible else self.options['plot']
|
||||||
|
|
||||||
|
if self.app.is_legacy is False:
|
||||||
if self.ui.annotation_cb.get_value() and self.ui.plot_cb.get_value():
|
if self.ui.annotation_cb.get_value() and self.ui.plot_cb.get_value():
|
||||||
self.text_col.enabled = True
|
self.text_col.enabled = True
|
||||||
else:
|
else:
|
||||||
|
@ -6201,9 +6245,11 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
||||||
self.shapes.redraw()
|
self.shapes.redraw()
|
||||||
except (ObjectDeleted, AttributeError):
|
except (ObjectDeleted, AttributeError):
|
||||||
self.shapes.clear(update=True)
|
self.shapes.clear(update=True)
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.annotation.clear(update=True)
|
self.annotation.clear(update=True)
|
||||||
|
|
||||||
def on_annotation_change(self):
|
def on_annotation_change(self):
|
||||||
|
if self.app.is_legacy is False:
|
||||||
if self.ui.annotation_cb.get_value():
|
if self.ui.annotation_cb.get_value():
|
||||||
self.text_col.enabled = True
|
self.text_col.enabled = True
|
||||||
else:
|
else:
|
||||||
|
@ -6211,6 +6257,8 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
||||||
# kind = self.ui.cncplot_method_combo.get_value()
|
# kind = self.ui.cncplot_method_combo.get_value()
|
||||||
# self.plot(kind=kind)
|
# self.plot(kind=kind)
|
||||||
self.annotation.redraw()
|
self.annotation.redraw()
|
||||||
|
else:
|
||||||
|
self.inform.emit(_("Not available with the current Graphic Engine Legacy(2D)."))
|
||||||
|
|
||||||
def convert_units(self, units):
|
def convert_units(self, units):
|
||||||
log.debug("FlatCAMObj.FlatCAMECNCjob.convert_units()")
|
log.debug("FlatCAMObj.FlatCAMECNCjob.convert_units()")
|
||||||
|
|
|
@ -16,6 +16,7 @@ from PyQt5.QtCore import QSettings
|
||||||
from flatcamGUI.GUIElements import log
|
from flatcamGUI.GUIElements import log
|
||||||
import gettext
|
import gettext
|
||||||
|
|
||||||
|
|
||||||
# import builtins
|
# import builtins
|
||||||
#
|
#
|
||||||
# if '_' not in builtins.__dict__:
|
# if '_' not in builtins.__dict__:
|
||||||
|
@ -154,12 +155,13 @@ def apply_language(domain, lang=None):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
def restart_program(app):
|
def restart_program(app, ask=None):
|
||||||
"""Restarts the current program.
|
"""Restarts the current program.
|
||||||
Note: this function does not return. Any cleanup action (like
|
Note: this function does not return. Any cleanup action (like
|
||||||
saving data) must be done before calling this function.
|
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 = QtWidgets.QMessageBox()
|
||||||
msgbox.setText(_("There are files/objects modified in FlatCAM. "
|
msgbox.setText(_("There are files/objects modified in FlatCAM. "
|
||||||
"\n"
|
"\n"
|
||||||
|
|
|
@ -588,7 +588,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
||||||
self.app.all_objects_list = self.get_list()
|
self.app.all_objects_list = self.get_list()
|
||||||
|
|
||||||
self.endRemoveRows()
|
self.endRemoveRows()
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.app.plotcanvas.redraw()
|
self.app.plotcanvas.redraw()
|
||||||
|
|
||||||
if select_project:
|
if select_project:
|
||||||
|
|
82
README.md
|
@ -1,4 +1,4 @@
|
||||||
latCAM: 2D Computer-Aided PCB Manufacturing
|
FlatCAM: 2D Computer-Aided PCB Manufacturing
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
(c) 2014-2019 Juan Pablo Caram
|
(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
|
17.09.2019
|
||||||
|
|
||||||
- added more programmers that contributed to FlatCAM over the years, in the "About FlatCAM" -> Programmers window
|
- added more programmers that contributed to FlatCAM over the years, in the "About FlatCAM" -> Programmers window
|
||||||
|
|
10
camlib.py
|
@ -36,6 +36,10 @@ from shapely.wkt import dumps as sdumps
|
||||||
from shapely.geometry.base import BaseGeometry
|
from shapely.geometry.base import BaseGeometry
|
||||||
from shapely.geometry import shape
|
from shapely.geometry import shape
|
||||||
|
|
||||||
|
# needed for legacy mode
|
||||||
|
# Used for solid polygons in Matplotlib
|
||||||
|
from descartes.patch import PolygonPatch
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
from collections import Iterable
|
from collections import Iterable
|
||||||
|
|
||||||
|
@ -117,7 +121,11 @@ class Geometry(object):
|
||||||
self.old_disp_number = 0
|
self.old_disp_number = 0
|
||||||
self.el_count = 0
|
self.el_count = 0
|
||||||
|
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.temp_shapes = self.app.plotcanvas.new_shape_group()
|
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:
|
# if geo_steps_per_circle is None:
|
||||||
# geo_steps_per_circle = int(Geometry.defaults["geo_steps_per_circle"])
|
# geo_steps_per_circle = int(Geometry.defaults["geo_steps_per_circle"])
|
||||||
|
@ -3430,7 +3438,7 @@ class Gerber (Geometry):
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
log.warning("Joining %d polygons." % len(poly_buffer))
|
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:
|
if self.use_buffer_for_union:
|
||||||
log.debug("Union by buffer...")
|
log.debug("Union by buffer...")
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
"""Turn geometric objects into matplotlib patches"""
|
||||||
|
|
||||||
|
from descartes.patch import PolygonPatch
|
||||||
|
|
|
@ -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)
|
|
@ -2012,8 +2012,14 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
self.exc_obj = None
|
self.exc_obj = None
|
||||||
|
|
||||||
# VisPy Visuals
|
# VisPy Visuals
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
|
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
|
||||||
self.tool_shape = 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)
|
self.app.pool_recreated.connect(self.pool_recreated)
|
||||||
|
|
||||||
# Remove from scene
|
# Remove from scene
|
||||||
|
@ -2082,6 +2088,11 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
def entry2option(option, entry):
|
def entry2option(option, entry):
|
||||||
self.options[option] = float(entry.text())
|
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
|
# store the status of the editor so the Delete at object level will not work until the edit is finished
|
||||||
self.editor_active = False
|
self.editor_active = False
|
||||||
log.debug("Initialization of the FlatCAM Excellon Editor is finished ...")
|
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
|
row_to_be_selected = int(key) - 1
|
||||||
self.last_tool_selected = int(key)
|
self.last_tool_selected = int(key)
|
||||||
break
|
break
|
||||||
|
try:
|
||||||
self.tools_table_exc.selectRow(row_to_be_selected)
|
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):
|
def on_tool_delete(self, dia=None):
|
||||||
self.is_modified = True
|
self.is_modified = True
|
||||||
|
@ -2791,16 +2804,23 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
|
|
||||||
# first connect to new, then disconnect the old handlers
|
# first connect to new, then disconnect the old handlers
|
||||||
# don't ask why but if there is nothing connected I've seen issues
|
# 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.mp = self.canvas.graph_event_connect('mouse_press', self.on_canvas_click)
|
||||||
self.canvas.vis_connect('mouse_move', self.on_canvas_move)
|
self.mm = self.canvas.graph_event_connect('mouse_move', self.on_canvas_move)
|
||||||
self.canvas.vis_connect('mouse_release', self.on_exc_click_release)
|
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
|
# make sure that the shortcuts key and mouse events will no longer be linked to the methods from FlatCAMApp
|
||||||
# but those from FlatCAMGeoEditor
|
# but those from FlatCAMGeoEditor
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
|
if self.app.is_legacy is False:
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
|
self.app.plotcanvas.graph_event_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.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_double_click', self.app.on_double_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_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.collection.view.clicked.disconnect()
|
||||||
|
|
||||||
self.app.ui.popmenu_copy.triggered.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
|
# we restore the key and mouse control to FlatCAMApp method
|
||||||
# first connect to new, then disconnect the old handlers
|
# first connect to new, then disconnect the old handlers
|
||||||
# don't ask why but if there is nothing connected I've seen issues
|
# 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.mp = self.app.plotcanvas.graph_event_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.mm = self.app.plotcanvas.graph_event_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.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
|
||||||
self.app.plotcanvas.vis_connect('mouse_double_click', self.app.on_double_click_over_plot)
|
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.app.collection.view.clicked.connect(self.app.collection.on_mouse_down)
|
||||||
|
|
||||||
self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
|
if self.app.is_legacy is False:
|
||||||
self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
|
self.canvas.graph_event_disconnect('mouse_press', self.on_canvas_click)
|
||||||
self.canvas.vis_disconnect('mouse_release', self.on_exc_click_release)
|
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:
|
try:
|
||||||
self.app.ui.popmenu_copy.triggered.disconnect(self.exc_copy_drills)
|
self.app.ui.popmenu_copy.triggered.disconnect(self.exc_copy_drills)
|
||||||
|
@ -2903,6 +2930,11 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
|
|
||||||
self.select_tool("drill_select")
|
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()
|
self.set_ui()
|
||||||
|
|
||||||
# now that we hava data, create the GUI interface and add it to the Tool Tab
|
# 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)
|
# element[1] of the tuple is a list of coordinates (a tuple themselves)
|
||||||
ordered_edited_points = sorted(zip(edited_points.keys(), edited_points.values()))
|
ordered_edited_points = sorted(zip(edited_points.keys(), edited_points.values()))
|
||||||
|
|
||||||
|
|
||||||
current_tool = 0
|
current_tool = 0
|
||||||
for tool_dia in ordered_edited_points:
|
for tool_dia in ordered_edited_points:
|
||||||
current_tool += 1
|
current_tool += 1
|
||||||
|
@ -3121,26 +3154,13 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
self.edited_obj_name += "_1"
|
self.edited_obj_name += "_1"
|
||||||
else:
|
else:
|
||||||
self.edited_obj_name += "_edit"
|
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
|
self.new_tool_offset = self.exc_obj.tool_offset
|
||||||
|
|
||||||
# reset the tool table
|
self.app.worker_task.emit({'fcn': self.new_edited_excellon,
|
||||||
self.tools_table_exc.clear()
|
'params': [self.edited_obj_name,
|
||||||
self.tools_table_exc.setHorizontalHeaderLabels(['#', _('Diameter'), 'D', 'S'])
|
self.new_drills,
|
||||||
self.last_tool_selected = None
|
self.new_slots,
|
||||||
|
self.new_tools]})
|
||||||
# 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)
|
|
||||||
|
|
||||||
def update_options(self, obj):
|
def update_options(self, obj):
|
||||||
try:
|
try:
|
||||||
|
@ -3157,7 +3177,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
obj.options = {}
|
obj.options = {}
|
||||||
return True
|
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.
|
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.app.log.debug("Update the Excellon object with edited content. Source is %s" %
|
||||||
self.exc_obj.options['name'])
|
self.exc_obj.options['name'])
|
||||||
|
|
||||||
|
new_drills = n_drills
|
||||||
|
new_slots = n_slots
|
||||||
|
new_tools = n_tools
|
||||||
|
|
||||||
# How the object should be initialized
|
# How the object should be initialized
|
||||||
def obj_init(excellon_obj, app_obj):
|
def obj_init(excellon_obj, app_obj):
|
||||||
|
|
||||||
# self.progress.emit(20)
|
# self.progress.emit(20)
|
||||||
excellon_obj.drills = self.new_drills
|
excellon_obj.drills = deepcopy(new_drills)
|
||||||
excellon_obj.tools = self.new_tools
|
excellon_obj.tools = deepcopy(new_tools)
|
||||||
excellon_obj.slots = self.new_slots
|
excellon_obj.slots = deepcopy(new_slots)
|
||||||
excellon_obj.tool_offset = self.new_tool_offset
|
excellon_obj.tool_offset = self.new_tool_offset
|
||||||
excellon_obj.options['name'] = outname
|
excellon_obj.options['name'] = outname
|
||||||
|
|
||||||
|
@ -3192,15 +3217,17 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
app_obj.inform.emit(msg)
|
app_obj.inform.emit(msg)
|
||||||
raise
|
raise
|
||||||
# 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.")):
|
with self.app.proc_container.new(_("Creating Excellon.")):
|
||||||
|
|
||||||
try:
|
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:
|
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)
|
self.app.progress.emit(100)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -3282,25 +3309,28 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
:param event: Event object dispatched by VisPy
|
:param event: Event object dispatched by VisPy
|
||||||
:return: None
|
: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:
|
if self.app.grid_status() == True:
|
||||||
self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1])
|
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:
|
else:
|
||||||
self.pos = (self.pos[0], self.pos[1])
|
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 <b>Dy</b>: "
|
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||||
"%.4f " % (0, 0))
|
"%.4f " % (0, 0))
|
||||||
|
|
||||||
# Selection with left mouse button
|
# 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
|
# Dispatch event to active_tool
|
||||||
# msg = self.active_tool.click(self.app.geo_editor.snap(event.xdata, event.ydata))
|
# 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]))
|
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
|
modifier_to_use = Qt.ControlModifier
|
||||||
else:
|
else:
|
||||||
modifier_to_use = Qt.ShiftModifier
|
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
|
# 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.
|
# in the selected list, we removed it. Therefore first click selects, second deselects.
|
||||||
if key_modifier == modifier_to_use:
|
if key_modifier == modifier_to_use:
|
||||||
|
@ -3422,7 +3453,17 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
:param event: Event object dispatched by VisPy SceneCavas
|
:param event: Event object dispatched by VisPy SceneCavas
|
||||||
:return: None
|
: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:
|
if self.app.grid_status() == True:
|
||||||
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
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
|
# 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
|
# canvas menu
|
||||||
try:
|
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.app.ui.popMenu.mouse_is_panning is False:
|
||||||
try:
|
try:
|
||||||
QtGui.QGuiApplication.restoreOverrideCursor()
|
QtGui.QGuiApplication.restoreOverrideCursor()
|
||||||
|
@ -3580,7 +3621,16 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
:return: None
|
: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]
|
event.xdata, event.ydata = pos[0], pos[1]
|
||||||
|
|
||||||
self.x = event.xdata
|
self.x = event.xdata
|
||||||
|
@ -3589,7 +3639,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
self.app.ui.popMenu.mouse_is_panning = False
|
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 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
|
self.app.ui.popMenu.mouse_is_panning = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -3605,11 +3655,9 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
# ## Snap coordinates
|
# ## Snap coordinates
|
||||||
if self.app.grid_status() == True:
|
if self.app.grid_status() == True:
|
||||||
x, y = self.app.geo_editor.snap(x, y)
|
x, y = self.app.geo_editor.snap(x, y)
|
||||||
self.app.app_cursor.enabled = True
|
|
||||||
# Update cursor
|
# Update cursor
|
||||||
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
|
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_x = x
|
||||||
self.snap_y = y
|
self.snap_y = y
|
||||||
|
@ -3636,7 +3684,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
self.draw_utility_geometry(geo=geo)
|
self.draw_utility_geometry(geo=geo)
|
||||||
|
|
||||||
# ## Selection area on canvas section # ##
|
# ## 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
|
# I make an exception for FCDrillAdd and FCDrillArray because clicking and dragging while making regions
|
||||||
# can create strange issues. Also for FCSlot and FCSlotArray
|
# can create strange issues. Also for FCSlot and FCSlotArray
|
||||||
if isinstance(self.active_tool, FCDrillAdd) or isinstance(self.active_tool, FCDrillArray) or \
|
if isinstance(self.active_tool, FCDrillAdd) or isinstance(self.active_tool, FCDrillArray) or \
|
||||||
|
@ -3718,10 +3766,10 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if shape_plus in self.selected:
|
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)
|
linewidth=2)
|
||||||
continue
|
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():
|
# for shape in self.storage.get_objects():
|
||||||
# if shape.geo is None: # TODO: This shouldn't have happened
|
# if shape.geo is None: # TODO: This shouldn't have happened
|
||||||
|
@ -3739,7 +3787,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
|
|
||||||
self.shapes.redraw()
|
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
|
Plots a geometric object or list of objects without rendering. Plotted objects
|
||||||
are returned as a list. This allows for efficient/animated rendering.
|
are returned as a list. This allows for efficient/animated rendering.
|
||||||
|
|
|
@ -3025,8 +3025,14 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
|
|
||||||
# VisPy visuals
|
# VisPy visuals
|
||||||
self.fcgeometry = None
|
self.fcgeometry = None
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
|
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
|
||||||
self.tool_shape = 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)
|
self.app.pool_recreated.connect(self.pool_recreated)
|
||||||
|
|
||||||
# Remove from scene
|
# Remove from scene
|
||||||
|
@ -3163,6 +3169,11 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
|
|
||||||
self.transform_complete.connect(self.on_transform_complete)
|
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
|
# store the status of the editor so the Delete at object level will not work until the edit is finished
|
||||||
self.editor_active = False
|
self.editor_active = False
|
||||||
log.debug("Initialization of the FlatCAM Geometry Editor is finished ...")
|
log.debug("Initialization of the FlatCAM Geometry Editor is finished ...")
|
||||||
|
@ -3271,7 +3282,6 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
# Disable visuals
|
# Disable visuals
|
||||||
self.shapes.enabled = False
|
self.shapes.enabled = False
|
||||||
self.tool_shape.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.setDisabled(True)
|
||||||
self.app.ui.geo_editor_menu.menuAction().setVisible(False)
|
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
|
# first connect to new, then disconnect the old handlers
|
||||||
# don't ask why but if there is nothing connected I've seen issues
|
# 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.mp = self.canvas.graph_event_connect('mouse_press', self.on_canvas_click)
|
||||||
self.canvas.vis_connect('mouse_move', self.on_canvas_move)
|
self.mm = self.canvas.graph_event_connect('mouse_move', self.on_canvas_move)
|
||||||
self.canvas.vis_connect('mouse_release', self.on_geo_click_release)
|
self.mr = self.canvas.graph_event_connect('mouse_release', self.on_geo_click_release)
|
||||||
|
|
||||||
|
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
|
# make sure that the shortcuts key and mouse events will no longer be linked to the methods from FlatCAMApp
|
||||||
# but those from FlatCAMGeoEditor
|
# but those from FlatCAMGeoEditor
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
|
self.app.plotcanvas.graph_event_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.graph_event_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.graph_event_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)
|
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.collection.view.clicked.disconnect()
|
||||||
self.app.ui.popmenu_copy.triggered.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
|
# we restore the key and mouse control to FlatCAMApp method
|
||||||
# first connect to new, then disconnect the old handlers
|
# first connect to new, then disconnect the old handlers
|
||||||
# don't ask why but if there is nothing connected I've seen issues
|
# 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.mp = self.app.plotcanvas.graph_event_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.mm = self.app.plotcanvas.graph_event_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.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
|
||||||
self.app.plotcanvas.vis_connect('mouse_double_click', self.app.on_double_click_over_plot)
|
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.app.collection.view.clicked.connect(self.app.collection.on_mouse_down)
|
||||||
|
|
||||||
self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
|
if self.app.is_legacy is False:
|
||||||
self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
|
self.canvas.graph_event_disconnect('mouse_press', self.on_canvas_click)
|
||||||
self.canvas.vis_disconnect('mouse_release', self.on_geo_click_release)
|
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:
|
try:
|
||||||
self.app.ui.popmenu_copy.triggered.disconnect(lambda: self.select_tool('copy'))
|
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
|
:param event: Event object dispatched by Matplotlib
|
||||||
:return: None
|
: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:
|
if self.app.grid_status() == True:
|
||||||
self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1])
|
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:
|
else:
|
||||||
self.pos = (self.pos[0], self.pos[1])
|
self.pos = (self.pos[0], self.pos[1])
|
||||||
self.app.app_cursor.enabled = False
|
|
||||||
|
|
||||||
if event.button == 1:
|
if event.button == 1:
|
||||||
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||||
|
@ -3649,8 +3672,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
self.app.defaults["global_point_clipboard_format"] % (self.pos[0], self.pos[1]))
|
self.app.defaults["global_point_clipboard_format"] % (self.pos[0], self.pos[1]))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# Selection with left mouse button
|
# 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
|
# Dispatch event to active_tool
|
||||||
self.active_tool.click(self.snap(self.pos[0], self.pos[1]))
|
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
|
:param event: Event object dispatched by VisPy SceneCavas
|
||||||
:return: None
|
: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]
|
event.xdata, event.ydata = pos[0], pos[1]
|
||||||
|
|
||||||
self.x = event.xdata
|
self.x = event.xdata
|
||||||
|
@ -3687,8 +3720,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
self.app.ui.popMenu.mouse_is_panning = False
|
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 the RMB is clicked and mouse is moving over plot then 'panning_action' is True
|
||||||
if event.button == 2:
|
if event.button == right_button:
|
||||||
if event.is_dragging:
|
if event_is_dragging:
|
||||||
self.app.ui.popMenu.mouse_is_panning = True
|
self.app.ui.popMenu.mouse_is_panning = True
|
||||||
# return
|
# return
|
||||||
else:
|
else:
|
||||||
|
@ -3706,11 +3739,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
# ### Snap coordinates ###
|
# ### Snap coordinates ###
|
||||||
if self.app.grid_status() == True:
|
if self.app.grid_status() == True:
|
||||||
x, y = self.snap(x, y)
|
x, y = self.snap(x, y)
|
||||||
self.app.app_cursor.enabled = True
|
|
||||||
# Update cursor
|
# Update cursor
|
||||||
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
|
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_x = x
|
||||||
self.snap_y = y
|
self.snap_y = y
|
||||||
|
@ -3728,7 +3759,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||||
"%.4f " % (dx, dy))
|
"%.4f " % (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
|
pass
|
||||||
else:
|
else:
|
||||||
# ### Utility geometry (animated) ###
|
# ### Utility geometry (animated) ###
|
||||||
|
@ -3740,7 +3771,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
|
|
||||||
# ### Selection area on canvas section ###
|
# ### Selection area on canvas section ###
|
||||||
dx = pos[0] - self.pos[0]
|
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()
|
self.app.delete_selection_shape()
|
||||||
if dx < 0:
|
if dx < 0:
|
||||||
self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x, y),
|
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
|
self.app.selection_type = None
|
||||||
|
|
||||||
def on_geo_click_release(self, event):
|
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:
|
if self.app.grid_status() == True:
|
||||||
pos = self.snap(pos_canvas[0], pos_canvas[1])
|
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.active_tool.click_release((self.pos[0], self.pos[1]))
|
||||||
# self.app.inform.emit(msg)
|
# self.app.inform.emit(msg)
|
||||||
self.replot()
|
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.app.ui.popMenu.mouse_is_panning == False:
|
||||||
if self.in_action is False:
|
if self.in_action is False:
|
||||||
try:
|
try:
|
||||||
|
@ -3943,7 +3983,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
# return [shape for shape in self.shape_buffer if shape["selected"]]
|
# return [shape for shape in self.shape_buffer if shape["selected"]]
|
||||||
return self.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
|
Plots a geometric object or list of objects without rendering. Plotted objects
|
||||||
are returned as a list. This allows for efficient/animated rendering.
|
are returned as a list. This allows for efficient/animated rendering.
|
||||||
|
@ -3961,7 +4001,6 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
try:
|
try:
|
||||||
for geo in geometry:
|
for geo in geometry:
|
||||||
plot_elements += self.plot_shape(geometry=geo, color=color, linewidth=linewidth)
|
plot_elements += self.plot_shape(geometry=geo, color=color, linewidth=linewidth)
|
||||||
|
|
||||||
# Non-iterable
|
# Non-iterable
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
|
||||||
|
@ -3999,10 +4038,10 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if shape in self.selected:
|
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
|
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:
|
for shape in self.utility:
|
||||||
self.plot_shape(geometry=shape.geo, linewidth=1)
|
self.plot_shape(geometry=shape.geo, linewidth=1)
|
||||||
|
|
|
@ -2607,8 +2607,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
self.ma_lower_threshold_entry = FCEntry()
|
self.ma_lower_threshold_entry = FCEntry()
|
||||||
self.ma_lower_threshold_entry.setValidator(QtGui.QDoubleValidator(0.0000, 9999.9999, 4))
|
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_lower_threshold_lbl, self.ma_lower_threshold_entry)
|
||||||
|
ma_form_layout.addRow(self.ma_upper_threshold_lbl, self.ma_upper_threshold_entry)
|
||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
hlay_ma = QtWidgets.QHBoxLayout()
|
hlay_ma = QtWidgets.QHBoxLayout()
|
||||||
|
@ -2821,12 +2821,27 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
self.gerber_obj_options = dict()
|
self.gerber_obj_options = dict()
|
||||||
|
|
||||||
# VisPy Visuals
|
# VisPy Visuals
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.shapes = self.canvas.new_shape_collection(layers=1)
|
self.shapes = self.canvas.new_shape_collection(layers=1)
|
||||||
self.tool_shape = 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()
|
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)
|
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
|
# Remove from scene
|
||||||
self.shapes.enabled = False
|
self.shapes.enabled = False
|
||||||
self.tool_shape.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.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.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_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_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.apsize_entry.set_value(self.app.defaults["gerber_editor_newsize"])
|
||||||
self.aptype_cb.set_value(self.app.defaults["gerber_editor_newtype"])
|
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
|
# first connect to new, then disconnect the old handlers
|
||||||
# don't ask why but if there is nothing connected I've seen issues
|
# 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.mp = self.canvas.graph_event_connect('mouse_press', self.on_canvas_click)
|
||||||
self.canvas.vis_connect('mouse_move', self.on_canvas_move)
|
self.mm = self.canvas.graph_event_connect('mouse_move', self.on_canvas_move)
|
||||||
self.canvas.vis_connect('mouse_release', self.on_grb_click_release)
|
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.collection.view.clicked.disconnect()
|
||||||
|
|
||||||
self.app.ui.popmenu_copy.triggered.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
|
# we restore the key and mouse control to FlatCAMApp method
|
||||||
# first connect to new, then disconnect the old handlers
|
# first connect to new, then disconnect the old handlers
|
||||||
# don't ask why but if there is nothing connected I've seen issues
|
# 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.app.mp = self.canvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot)
|
||||||
self.canvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
|
self.app.mm = self.canvas.graph_event_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.app.mr = self.canvas.graph_event_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.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.app.collection.view.clicked.connect(self.app.collection.on_mouse_down)
|
||||||
|
|
||||||
self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
|
if self.app.is_legacy is False:
|
||||||
self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
|
self.canvas.graph_event_disconnect('mouse_press', self.on_canvas_click)
|
||||||
self.canvas.vis_disconnect('mouse_release', self.on_grb_click_release)
|
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:
|
try:
|
||||||
self.app.ui.popmenu_copy.triggered.disconnect(self.on_copy_button)
|
self.app.ui.popmenu_copy.triggered.disconnect(self.on_copy_button)
|
||||||
|
@ -3654,6 +3681,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
self.deactivate_grb_editor()
|
self.deactivate_grb_editor()
|
||||||
self.activate_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
|
# create a reference to the source object
|
||||||
self.gerber_obj = orig_grb_obj
|
self.gerber_obj = orig_grb_obj
|
||||||
self.gerber_obj_options = orig_grb_obj.options
|
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
|
# list of clear geos that are to be applied to the entire file
|
||||||
global_clear_geo = []
|
global_clear_geo = []
|
||||||
|
|
||||||
|
# create one big geometry made out of all 'negative' (clear) polygons
|
||||||
for apid in self.gerber_obj.apertures:
|
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
|
# 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]:
|
if 'geometry' in self.gerber_obj.apertures[apid]:
|
||||||
|
@ -3710,8 +3744,19 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
global_clear_geo.append(elem['clear'])
|
global_clear_geo.append(elem['clear'])
|
||||||
log.warning("Found %d clear polygons." % len(global_clear_geo))
|
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:
|
for apid in self.gerber_obj.apertures:
|
||||||
temp_elem = []
|
temp_solid_geometry= []
|
||||||
if 'geometry' in self.gerber_obj.apertures[apid]:
|
if 'geometry' in self.gerber_obj.apertures[apid]:
|
||||||
# for elem in self.gerber_obj.apertures[apid]['geometry']:
|
# for elem in self.gerber_obj.apertures[apid]['geometry']:
|
||||||
# if 'solid' in elem:
|
# if 'solid' in elem:
|
||||||
|
@ -3742,9 +3787,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
# temp_elem.append(deepcopy(new_elem))
|
# temp_elem.append(deepcopy(new_elem))
|
||||||
for elem in self.gerber_obj.apertures[apid]['geometry']:
|
for elem in self.gerber_obj.apertures[apid]['geometry']:
|
||||||
new_elem = dict()
|
new_elem = dict()
|
||||||
|
|
||||||
if 'solid' in elem:
|
if 'solid' in elem:
|
||||||
solid_geo = elem['solid']
|
solid_geo = elem['solid']
|
||||||
|
|
||||||
for clear_geo in global_clear_geo:
|
for clear_geo in global_clear_geo:
|
||||||
# Make sure that the clear_geo is within the solid_geo otherwise we loose
|
# 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
|
# 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']
|
new_elem['clear'] = elem['clear']
|
||||||
if 'follow' in elem:
|
if 'follow' in elem:
|
||||||
new_elem['follow'] = elem['follow']
|
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))
|
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
|
# and then add it to the storage elements (each storage elements is a member of a list
|
||||||
def job_thread(aperture_id):
|
def job_thread(aperture_id):
|
||||||
with self.app.proc_container.new('%s: %s %s...' %
|
with self.app.proc_container.new('%s: %s ...' %
|
||||||
(_("Adding aperture"), str(aperture_id), _("geo"))):
|
(_("Adding geometry for aperture"), str(aperture_id))):
|
||||||
storage_elem = []
|
storage_elem = []
|
||||||
self.storage_dict[aperture_id] = {}
|
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]
|
self.storage_dict[aperture_id][k] = self.gerber_obj.apertures[aperture_id][k]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("FlatCAMGrbEditor.edit_fcgerber().job_thread() --> %s" % str(e))
|
log.debug("FlatCAMGrbEditor.edit_fcgerber().job_thread() --> %s" % str(e))
|
||||||
|
|
||||||
# Check promises and clear if exists
|
# Check promises and clear if exists
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@ -3789,6 +3835,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
break
|
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:
|
for ap_id in self.gerber_obj.apertures:
|
||||||
self.grb_plot_promises.append(ap_id)
|
self.grb_plot_promises.append(ap_id)
|
||||||
self.app.worker_task.emit({'fcn': job_thread, 'params': [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"
|
new_grb_name = self.edited_obj_name + "_edit"
|
||||||
|
|
||||||
self.app.worker_task.emit({'fcn': self.new_edited_gerber,
|
self.app.worker_task.emit({'fcn': self.new_edited_gerber,
|
||||||
'params': [new_grb_name]})
|
'params': [new_grb_name, self.storage_dict]})
|
||||||
|
|
||||||
# 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)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_options(obj):
|
def update_options(obj):
|
||||||
|
@ -3861,12 +3897,13 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
obj.options = dict()
|
obj.options = dict()
|
||||||
return True
|
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.
|
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.
|
:param outname: Name of the resulting object. None causes the name to be that of the file.
|
||||||
:type outname: str
|
:type outname: str
|
||||||
|
:param aperture_storage: a dictionary that holds all the objects geometry
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -3874,13 +3911,14 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
self.gerber_obj.options['name'].upper())
|
self.gerber_obj.options['name'].upper())
|
||||||
|
|
||||||
out_name = outname
|
out_name = outname
|
||||||
|
storage_dict = aperture_storage
|
||||||
|
|
||||||
local_storage_dict = dict()
|
local_storage_dict = dict()
|
||||||
for aperture in self.storage_dict:
|
for aperture in storage_dict:
|
||||||
if 'geometry' in self.storage_dict[aperture]:
|
if 'geometry' in storage_dict[aperture]:
|
||||||
# add aperture only if it has geometry
|
# add aperture only if it has geometry
|
||||||
if len(self.storage_dict[aperture]['geometry']) > 0:
|
if len(storage_dict[aperture]['geometry']) > 0:
|
||||||
local_storage_dict[aperture] = deepcopy(self.storage_dict[aperture])
|
local_storage_dict[aperture] = deepcopy(storage_dict[aperture])
|
||||||
|
|
||||||
# How the object should be initialized
|
# How the object should be initialized
|
||||||
def obj_init(grb_obj, app_obj):
|
def obj_init(grb_obj, app_obj):
|
||||||
|
@ -3969,7 +4007,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
try:
|
try:
|
||||||
self.app.new_object("gerber", outname, obj_init)
|
self.app.new_object("gerber", outname, obj_init)
|
||||||
except Exception as e:
|
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)
|
self.app.progress.emit(100)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -4116,20 +4154,23 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
:param event: Event object dispatched by VisPy
|
:param event: Event object dispatched by VisPy
|
||||||
:return: None
|
: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:
|
if self.app.grid_status() == True:
|
||||||
self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1])
|
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:
|
else:
|
||||||
self.pos = (self.pos[0], self.pos[1])
|
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 <b>Dy</b>: "
|
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||||
"%.4f " % (0, 0))
|
"%.4f " % (0, 0))
|
||||||
|
|
||||||
|
@ -4180,8 +4221,16 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
|
|
||||||
def on_grb_click_release(self, event):
|
def on_grb_click_release(self, event):
|
||||||
self.modifiers = QtWidgets.QApplication.keyboardModifiers()
|
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:
|
if self.app.grid_status() == True:
|
||||||
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
||||||
else:
|
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
|
# 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
|
# canvas menu
|
||||||
try:
|
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.app.ui.popMenu.mouse_is_panning is False:
|
||||||
if self.in_action is False:
|
if self.in_action is False:
|
||||||
try:
|
try:
|
||||||
|
@ -4271,8 +4320,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
|
|
||||||
self.app.delete_selection_shape()
|
self.app.delete_selection_shape()
|
||||||
for storage in self.storage_dict:
|
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']
|
geometric_data = obj.geo['solid']
|
||||||
if (sel_type is True and poly_selection.contains(geometric_data)) or \
|
if (sel_type is True and poly_selection.contains(geometric_data)) or \
|
||||||
(sel_type is False and poly_selection.intersects(geometric_data)):
|
(sel_type is False and poly_selection.intersects(geometric_data)):
|
||||||
|
@ -4286,8 +4335,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
else:
|
else:
|
||||||
self.selected.append(obj)
|
self.selected.append(obj)
|
||||||
sel_aperture.add(storage)
|
sel_aperture.add(storage)
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
try:
|
try:
|
||||||
self.apertures_table.cellPressed.disconnect()
|
self.apertures_table.cellPressed.disconnect()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -4314,8 +4362,16 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
:param event: Event object dispatched by VisPy SceneCavas
|
:param event: Event object dispatched by VisPy SceneCavas
|
||||||
:return: None
|
: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]
|
event.xdata, event.ydata = pos_canvas[0], pos_canvas[1]
|
||||||
|
|
||||||
self.x = event.xdata
|
self.x = event.xdata
|
||||||
|
@ -4324,7 +4380,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
self.app.ui.popMenu.mouse_is_panning = False
|
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 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
|
self.app.ui.popMenu.mouse_is_panning = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -4340,11 +4396,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
# # ## Snap coordinates
|
# # ## Snap coordinates
|
||||||
if self.app.grid_status() == True:
|
if self.app.grid_status() == True:
|
||||||
x, y = self.app.geo_editor.snap(x, y)
|
x, y = self.app.geo_editor.snap(x, y)
|
||||||
self.app.app_cursor.enabled = True
|
|
||||||
# Update cursor
|
# Update cursor
|
||||||
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
|
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_x = x
|
||||||
self.snap_y = y
|
self.snap_y = y
|
||||||
|
@ -4371,7 +4425,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
self.draw_utility_geometry(geo=geo)
|
self.draw_utility_geometry(geo=geo)
|
||||||
|
|
||||||
# # ## Selection area on canvas section # ##
|
# # ## 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
|
# 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
|
# create strange issues like missing a point in a track/region
|
||||||
if isinstance(self.active_tool, FCRegion) or isinstance(self.active_tool, FCTrack):
|
if isinstance(self.active_tool, FCRegion) or isinstance(self.active_tool, FCTrack):
|
||||||
|
@ -4420,26 +4474,24 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
with self.app.proc_container.new("Plotting"):
|
with self.app.proc_container.new("Plotting"):
|
||||||
|
|
||||||
self.shapes.clear(update=True)
|
self.shapes.clear(update=True)
|
||||||
|
|
||||||
for storage in self.storage_dict:
|
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']
|
geometric_data = elem.geo['solid']
|
||||||
if geometric_data is None:
|
if geometric_data is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if elem in self.selected:
|
if elem in self.selected:
|
||||||
self.plot_shape(geometry=geometric_data,
|
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)
|
linewidth=2)
|
||||||
continue
|
else:
|
||||||
self.plot_shape(geometry=geometric_data,
|
self.plot_shape(geometry=geometric_data,
|
||||||
color=self.app.defaults['global_draw_color'])
|
color=self.app.defaults['global_draw_color'] + 'FF')
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
if self.utility:
|
||||||
for elem in self.utility:
|
for elem in self.utility:
|
||||||
geometric_data = elem.geo['solid']
|
geometric_data = elem.geo['solid']
|
||||||
self.plot_shape(geometry=geometric_data, linewidth=1)
|
self.plot_shape(geometry=geometric_data, linewidth=1)
|
||||||
|
@ -4447,7 +4499,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
|
|
||||||
self.shapes.redraw()
|
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
|
Plots a geometric object or list of objects without rendering. Plotted objects
|
||||||
are returned as a list. This allows for efficient/animated rendering.
|
are returned as a list. This allows for efficient/animated rendering.
|
||||||
|
@ -4463,10 +4515,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.shapes.add(shape=geometry.geo, color=color, face_color=color, layer=0, tolerance=self.tolerance)
|
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:
|
if type(geometry) == Point:
|
||||||
return
|
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):
|
def start_delayed_plot(self, check_period):
|
||||||
"""
|
"""
|
||||||
|
@ -4785,7 +4839,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
lower_threshold_val = 0.0
|
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]
|
current_pos = geo_el['solid'].exterior.coords[-1]
|
||||||
text_elem = '%.4f' % area
|
text_elem = '%.4f' % area
|
||||||
text.append(text_elem)
|
text.append(text_elem)
|
||||||
|
@ -4794,7 +4848,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
||||||
if text:
|
if text:
|
||||||
self.ma_annotation.set(text=text, pos=position, visible=True,
|
self.ma_annotation.set(text=text, pos=position, visible=True,
|
||||||
font_size=self.app.defaults["cncjob_annotation_fontsize"],
|
font_size=self.app.defaults["cncjob_annotation_fontsize"],
|
||||||
color=self.app.defaults["global_sel_draw_color"])
|
color='#000000FF')
|
||||||
self.app.inform.emit('[success] %s' %
|
self.app.inform.emit('[success] %s' %
|
||||||
_("Polygon areas marked."))
|
_("Polygon areas marked."))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -152,10 +152,10 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def vis_connect(self, event_name, callback):
|
def graph_event_connect(self, event_name, callback):
|
||||||
return getattr(self.events, event_name).connect(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:
|
if callback is None:
|
||||||
getattr(self.events, event_name).disconnect()
|
getattr(self.events, event_name).disconnect()
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -298,6 +298,11 @@ class CutOut(FlatCAMTool):
|
||||||
# if mouse is dragging set the object True
|
# if mouse is dragging set the object True
|
||||||
self.mouse_is_dragging = False
|
self.mouse_is_dragging = False
|
||||||
|
|
||||||
|
# event handlers references
|
||||||
|
self.kp = None
|
||||||
|
self.mm = None
|
||||||
|
self.mr = None
|
||||||
|
|
||||||
# hold the mouse position here
|
# hold the mouse position here
|
||||||
self.x_pos = None
|
self.x_pos = None
|
||||||
self.y_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))
|
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve Geometry object"), name))
|
||||||
return "Could not retrieve object: %s" % name
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
self.app.plotcanvas.vis_disconnect('key_press', self.app.ui.keyPressEvent)
|
if self.app.is_legacy is False:
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
|
self.app.plotcanvas.graph_event_disconnect('key_press', self.app.ui.keyPressEvent)
|
||||||
self.app.plotcanvas.vis_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)
|
||||||
self.app.plotcanvas.vis_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.vis_connect('key_press', self.on_key_press)
|
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
|
||||||
self.app.plotcanvas.vis_connect('mouse_move', self.on_mouse_move)
|
else:
|
||||||
self.app.plotcanvas.vis_connect('mouse_release', self.on_mouse_click_release)
|
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):
|
def on_manual_cutout(self, click_pos):
|
||||||
name = self.man_object_combo.currentText()
|
name = self.man_object_combo.currentText()
|
||||||
|
@ -923,33 +936,46 @@ class CutOut(FlatCAMTool):
|
||||||
# To be called after clicking on the plot.
|
# To be called after clicking on the plot.
|
||||||
def on_mouse_click_release(self, event):
|
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
|
# do paint single only for left mouse clicks
|
||||||
if event.button == 1:
|
if event.button == 1:
|
||||||
self.app.inform.emit(_("Making manual bridge gap..."))
|
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.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
|
# if RMB then we exit
|
||||||
elif event.button == 2 and self.mouse_is_dragging is False:
|
elif event.button == right_button and self.mouse_is_dragging is False:
|
||||||
self.app.plotcanvas.vis_disconnect('key_press', self.on_key_press)
|
if self.app.is_legacy is False:
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move)
|
self.app.plotcanvas.graph_event_disconnect('key_press', self.on_key_press)
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_release', self.on_mouse_click_release)
|
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
|
||||||
self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent)
|
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release)
|
||||||
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
|
else:
|
||||||
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
|
self.app.plotcanvas.graph_event_disconnect(self.kp)
|
||||||
self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
|
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
|
# Remove any previous utility shape
|
||||||
self.app.geo_editor.tool_shape.clear(update=True)
|
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)
|
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]
|
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
|
self.mouse_is_dragging = True
|
||||||
else:
|
else:
|
||||||
self.mouse_is_dragging = False
|
self.mouse_is_dragging = False
|
||||||
|
@ -1058,19 +1100,43 @@ class CutOut(FlatCAMTool):
|
||||||
# events from the GUI are of type QKeyEvent
|
# events from the GUI are of type QKeyEvent
|
||||||
elif type(event) == QtGui.QKeyEvent:
|
elif type(event) == QtGui.QKeyEvent:
|
||||||
key = event.key()
|
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
|
# events from Vispy are of type KeyEvent
|
||||||
else:
|
else:
|
||||||
key = event.key
|
key = event.key
|
||||||
|
|
||||||
# Escape = Deselect All
|
# Escape = Deselect All
|
||||||
if key == QtCore.Qt.Key_Escape or key == 'Escape':
|
if key == QtCore.Qt.Key_Escape or key == 'Escape':
|
||||||
self.app.plotcanvas.vis_disconnect('key_press', self.on_key_press)
|
if self.app.is_legacy is False:
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move)
|
self.app.plotcanvas.graph_event_disconnect('key_press', self.on_key_press)
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_release', self.on_mouse_click_release)
|
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
|
||||||
self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent)
|
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release)
|
||||||
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
|
else:
|
||||||
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
|
self.app.plotcanvas.graph_event_disconnect(self.kp)
|
||||||
self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
|
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
|
# Remove any previous utility shape
|
||||||
self.app.geo_editor.tool_shape.clear(update=True)
|
self.app.geo_editor.tool_shape.clear(update=True)
|
||||||
|
|
|
@ -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 = QtWidgets.QLabel("%s" % str({'mm': _("METRIC (mm)"), 'in': _("INCH (in)")}[self.units]))
|
||||||
self.units_value.setDisabled(True)
|
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.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.stop_label.setToolTip(_("This is the measuring Stop point coordinates."))
|
||||||
|
|
||||||
self.distance_x_label = QtWidgets.QLabel('%s:' % _("Dx"))
|
self.distance_x_label = QtWidgets.QLabel('%s:' % _("Dx"))
|
||||||
|
@ -113,7 +113,11 @@ class Measurement(FlatCAMTool):
|
||||||
self.original_call_source = 'app'
|
self.original_call_source = 'app'
|
||||||
|
|
||||||
# VisPy visuals
|
# VisPy visuals
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)
|
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)
|
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
|
# we can connect the app mouse events to the measurement tool
|
||||||
# NEVER DISCONNECT THOSE before connecting some other handlers; it breaks something in VisPy
|
# 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.mm = self.canvas.graph_event_connect('mouse_move', self.on_mouse_move_meas)
|
||||||
self.canvas.vis_connect('mouse_release', self.on_mouse_click_release)
|
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
|
# we disconnect the mouse/key handlers from wherever the measurement tool was called
|
||||||
if self.app.call_source == 'app':
|
if self.app.call_source == 'app':
|
||||||
self.canvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
|
if self.app.is_legacy is False:
|
||||||
self.canvas.vis_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.vis_disconnect('mouse_release', self.app.on_mouse_click_release_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':
|
elif self.app.call_source == 'geo_editor':
|
||||||
self.canvas.vis_disconnect('mouse_move', self.app.geo_editor.on_canvas_move)
|
if self.app.is_legacy is False:
|
||||||
self.canvas.vis_disconnect('mouse_press', self.app.geo_editor.on_canvas_click)
|
self.canvas.graph_event_disconnect('mouse_move', self.app.geo_editor.on_canvas_move)
|
||||||
self.canvas.vis_disconnect('mouse_release', self.app.geo_editor.on_geo_click_release)
|
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':
|
elif self.app.call_source == 'exc_editor':
|
||||||
self.canvas.vis_disconnect('mouse_move', self.app.exc_editor.on_canvas_move)
|
if self.app.is_legacy is False:
|
||||||
self.canvas.vis_disconnect('mouse_press', self.app.exc_editor.on_canvas_click)
|
self.canvas.graph_event_disconnect('mouse_move', self.app.exc_editor.on_canvas_move)
|
||||||
self.canvas.vis_disconnect('mouse_release', self.app.exc_editor.on_exc_click_release)
|
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':
|
elif self.app.call_source == 'grb_editor':
|
||||||
self.canvas.vis_disconnect('mouse_move', self.app.grb_editor.on_canvas_move)
|
if self.app.is_legacy is False:
|
||||||
self.canvas.vis_disconnect('mouse_press', self.app.grb_editor.on_canvas_click)
|
self.canvas.graph_event_disconnect('mouse_move', self.app.grb_editor.on_canvas_move)
|
||||||
self.canvas.vis_disconnect('mouse_release', self.app.grb_editor.on_grb_click_release)
|
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'
|
self.app.call_source = 'measurement'
|
||||||
|
|
||||||
|
@ -210,25 +237,35 @@ class Measurement(FlatCAMTool):
|
||||||
|
|
||||||
self.app.call_source = copy(self.original_call_source)
|
self.app.call_source = copy(self.original_call_source)
|
||||||
if self.original_call_source == 'app':
|
if self.original_call_source == 'app':
|
||||||
self.canvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
|
self.app.mm = self.canvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot)
|
||||||
self.canvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
|
self.app.mp = self.canvas.graph_event_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.mr = self.canvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
|
||||||
|
|
||||||
elif self.original_call_source == 'geo_editor':
|
elif self.original_call_source == 'geo_editor':
|
||||||
self.canvas.vis_connect('mouse_move', self.app.geo_editor.on_canvas_move)
|
self.app.geo_editor.mm = self.canvas.graph_event_connect('mouse_move', self.app.geo_editor.on_canvas_move)
|
||||||
self.canvas.vis_connect('mouse_press', self.app.geo_editor.on_canvas_click)
|
self.app.geo_editor.mp = self.canvas.graph_event_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.mr = self.canvas.graph_event_connect('mouse_release',
|
||||||
|
self.app.geo_editor.on_geo_click_release)
|
||||||
|
|
||||||
elif self.original_call_source == 'exc_editor':
|
elif self.original_call_source == 'exc_editor':
|
||||||
self.canvas.vis_connect('mouse_move', self.app.exc_editor.on_canvas_move)
|
self.app.exc_editor.mm = self.canvas.graph_event_connect('mouse_move', self.app.exc_editor.on_canvas_move)
|
||||||
self.canvas.vis_connect('mouse_press', self.app.exc_editor.on_canvas_click)
|
self.app.exc_editor.mp = self.canvas.graph_event_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.mr = self.canvas.graph_event_connect('mouse_release',
|
||||||
|
self.app.exc_editor.on_exc_click_release)
|
||||||
|
|
||||||
elif self.original_call_source == 'grb_editor':
|
elif self.original_call_source == 'grb_editor':
|
||||||
self.canvas.vis_connect('mouse_move', self.app.grb_editor.on_canvas_move)
|
self.app.grb_editor.mm = self.canvas.graph_event_connect('mouse_move', self.app.grb_editor.on_canvas_move)
|
||||||
self.canvas.vis_connect('mouse_press', self.app.grb_editor.on_canvas_click)
|
self.app.grb_editor.mp = self.canvas.graph_event_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.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
|
# disconnect the mouse/key events from functions of measurement tool
|
||||||
self.canvas.vis_disconnect('mouse_move', self.on_mouse_move_meas)
|
if self.app.is_legacy is False:
|
||||||
self.canvas.vis_disconnect('mouse_release', self.on_mouse_click_release)
|
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.setTabText(2, _("Tools"))
|
||||||
# self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
# self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
||||||
|
@ -247,7 +284,13 @@ class Measurement(FlatCAMTool):
|
||||||
log.debug("Measuring Tool --> mouse click release")
|
log.debug("Measuring Tool --> mouse click release")
|
||||||
|
|
||||||
if event.button == 1:
|
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 GRID is active we need to get the snapped positions
|
||||||
if self.app.grid_status() == True:
|
if self.app.grid_status() == True:
|
||||||
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
||||||
|
@ -267,8 +310,7 @@ class Measurement(FlatCAMTool):
|
||||||
if len(self.points) == 1:
|
if len(self.points) == 1:
|
||||||
self.start_entry.set_value("(%.4f, %.4f)" % pos)
|
self.start_entry.set_value("(%.4f, %.4f)" % pos)
|
||||||
self.app.inform.emit(_("MEASURING: Click on the Destination point ..."))
|
self.app.inform.emit(_("MEASURING: Click on the Destination point ..."))
|
||||||
|
elif len(self.points) == 2:
|
||||||
if len(self.points) == 2:
|
|
||||||
dx = self.points[1][0] - self.points[0][0]
|
dx = self.points[1][0] - self.points[0][0]
|
||||||
dy = self.points[1][1] - self.points[0][1]
|
dy = self.points[1][1] - self.points[0][1]
|
||||||
d = sqrt(dx ** 2 + dy ** 2)
|
d = sqrt(dx ** 2 + dy ** 2)
|
||||||
|
@ -280,47 +322,68 @@ class Measurement(FlatCAMTool):
|
||||||
self.distance_x_entry.set_value('%.4f' % abs(dx))
|
self.distance_x_entry.set_value('%.4f' % abs(dx))
|
||||||
self.distance_y_entry.set_value('%.4f' % abs(dy))
|
self.distance_y_entry.set_value('%.4f' % abs(dy))
|
||||||
self.total_distance_entry.set_value('%.4f' % abs(d))
|
self.total_distance_entry.set_value('%.4f' % abs(d))
|
||||||
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
self.app.ui.rel_position_label.setText("<b>Dx</b>: {0:.4f} <b>Dy</b>: "
|
||||||
"%.4f " % (pos[0], pos[1]))
|
"{0:.4f} ".format(pos[0], pos[1]))
|
||||||
self.deactivate_measure_tool()
|
self.deactivate_measure_tool()
|
||||||
|
|
||||||
def on_mouse_move_meas(self, event):
|
def on_mouse_move_meas(self, event):
|
||||||
try: # May fail in case mouse not within axes
|
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:
|
if self.app.grid_status() == True:
|
||||||
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
||||||
self.app.app_cursor.enabled = True
|
|
||||||
# Update cursor
|
# Update cursor
|
||||||
self.app.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
|
self.app.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
|
||||||
symbol='++', edge_color='black', size=20)
|
symbol='++', edge_color='black', size=20)
|
||||||
else:
|
else:
|
||||||
pos = (pos_canvas[0], pos_canvas[1])
|
pos = (pos_canvas[0], pos_canvas[1])
|
||||||
self.app.app_cursor.enabled = False
|
|
||||||
|
self.app.ui.position_label.setText(" <b>X</b>: {0:.4f} "
|
||||||
|
"<b>Y</b>: {0:.4f}".format(pos[0], pos[1]))
|
||||||
|
|
||||||
if self.rel_point1 is not None:
|
if self.rel_point1 is not None:
|
||||||
dx = pos[0] - self.rel_point1[0]
|
dx = pos[0] - float(self.rel_point1[0])
|
||||||
dy = pos[1] - self.rel_point1[1]
|
dy = pos[1] - float(self.rel_point1[1])
|
||||||
else:
|
else:
|
||||||
dx = pos[0]
|
dx = pos[0]
|
||||||
dy = pos[1]
|
dy = pos[1]
|
||||||
|
|
||||||
self.app.ui.position_label.setText(" <b>X</b>: %.4f "
|
self.app.ui.rel_position_label.setText("<b>Dx</b>: {0:.4f} <b>Dy</b>: "
|
||||||
"<b>Y</b>: %.4f" % (pos[0], pos[1]))
|
"{0:.4f} ".format(dx, dy))
|
||||||
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
|
||||||
"%.4f " % (dx, dy))
|
|
||||||
# update utility geometry
|
# update utility geometry
|
||||||
|
|
||||||
if len(self.points) == 1:
|
if len(self.points) == 1:
|
||||||
self.utility_geometry(pos=pos)
|
self.utility_geometry(pos=pos)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
log.debug("Measurement.on_mouse_move_meas() --> %s" % str(e))
|
||||||
self.app.ui.position_label.setText("")
|
self.app.ui.position_label.setText("")
|
||||||
self.app.ui.rel_position_label.setText("")
|
self.app.ui.rel_position_label.setText("")
|
||||||
|
|
||||||
def utility_geometry(self, pos):
|
def utility_geometry(self, pos):
|
||||||
# first delete old shape
|
# first delete old shape
|
||||||
self.delete_shape()
|
self.delete_shape()
|
||||||
|
|
||||||
# second draw the new shape of the utility geometry
|
# second draw the new shape of the utility geometry
|
||||||
self.meas_line = LineString([pos, self.points[0]])
|
meas_line = LineString([pos, self.points[0]])
|
||||||
self.sel_shapes.add(self.meas_line, color='black', update=True, layer=0, tolerance=None)
|
|
||||||
|
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):
|
def delete_shape(self):
|
||||||
self.sel_shapes.clear()
|
self.sel_shapes.clear()
|
||||||
|
|
|
@ -44,7 +44,11 @@ class ToolMove(FlatCAMTool):
|
||||||
self.old_coords = []
|
self.old_coords = []
|
||||||
|
|
||||||
# VisPy visuals
|
# VisPy visuals
|
||||||
|
if self.app.is_legacy is False:
|
||||||
self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1)
|
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)
|
self.replot_signal[list].connect(self.replot)
|
||||||
|
|
||||||
|
@ -62,10 +66,16 @@ class ToolMove(FlatCAMTool):
|
||||||
if self.isVisible():
|
if self.isVisible():
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_move', self.on_move)
|
if self.app.is_legacy is False:
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_press', self.on_left_click)
|
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_move)
|
||||||
self.app.plotcanvas.vis_disconnect('key_release', self.on_key_press)
|
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.on_left_click)
|
||||||
self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent)
|
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
|
self.clicked_move = 0
|
||||||
|
|
||||||
|
@ -95,9 +105,14 @@ class ToolMove(FlatCAMTool):
|
||||||
# this is necessary because right mouse click and middle mouse click
|
# this is necessary because right mouse click and middle mouse click
|
||||||
# are used for panning on the canvas
|
# 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 event.button == 1:
|
||||||
if self.clicked_move == 0:
|
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 GRID is active we need to get the snapped positions
|
||||||
if self.app.grid_status() == True:
|
if self.app.grid_status() == True:
|
||||||
|
@ -114,7 +129,7 @@ class ToolMove(FlatCAMTool):
|
||||||
|
|
||||||
if self.clicked_move == 1:
|
if self.clicked_move == 1:
|
||||||
try:
|
try:
|
||||||
pos_canvas = self.app.plotcanvas.translate_coords(event.pos)
|
pos_canvas = self.app.plotcanvas.translate_coords(event_pos)
|
||||||
|
|
||||||
# delete the selection bounding box
|
# delete the selection bounding box
|
||||||
self.delete_shape()
|
self.delete_shape()
|
||||||
|
@ -174,7 +189,8 @@ class ToolMove(FlatCAMTool):
|
||||||
self.toggle()
|
self.toggle()
|
||||||
return
|
return
|
||||||
|
|
||||||
except TypeError:
|
except TypeError as e:
|
||||||
|
log.debug("ToolMove.on_left_click() --> %s" % str(e))
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||||
_('ToolMove.on_left_click() --> Error when mouse left click.'))
|
_('ToolMove.on_left_click() --> Error when mouse left click.'))
|
||||||
return
|
return
|
||||||
|
@ -191,7 +207,19 @@ class ToolMove(FlatCAMTool):
|
||||||
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
|
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
|
||||||
|
|
||||||
def on_move(self, event):
|
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 GRID is active we need to get the snapped positions
|
||||||
if self.app.grid_status() == True:
|
if self.app.grid_status() == True:
|
||||||
|
@ -228,9 +256,9 @@ class ToolMove(FlatCAMTool):
|
||||||
self.toggle()
|
self.toggle()
|
||||||
else:
|
else:
|
||||||
# if we have an object selected then we can safely activate the mouse events
|
# 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.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_move)
|
||||||
self.app.plotcanvas.vis_connect('mouse_press', self.on_left_click)
|
self.mp = self.app.plotcanvas.graph_event_connect('mouse_press', self.on_left_click)
|
||||||
self.app.plotcanvas.vis_connect('key_release', self.on_key_press)
|
self.kr = self.app.plotcanvas.graph_event_connect('key_release', self.on_key_press)
|
||||||
# first get a bounding box to fit all
|
# first get a bounding box to fit all
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
xmin, ymin, xmax, ymax = obj.bounds()
|
xmin, ymin, xmax, ymax = obj.bounds()
|
||||||
|
@ -249,8 +277,12 @@ class ToolMove(FlatCAMTool):
|
||||||
p2 = (xmaximal, yminimal)
|
p2 = (xmaximal, yminimal)
|
||||||
p3 = (xmaximal, ymaximal)
|
p3 = (xmaximal, ymaximal)
|
||||||
p4 = (xminimal, ymaximal)
|
p4 = (xminimal, ymaximal)
|
||||||
|
|
||||||
self.old_coords = [p1, p2, p3, p4]
|
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):
|
def update_sel_bbox(self, pos):
|
||||||
self.delete_shape()
|
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])
|
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])
|
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])
|
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):
|
def delete_shape(self):
|
||||||
self.sel_shapes.clear()
|
self.sel_shapes.clear()
|
||||||
self.sel_shapes.redraw()
|
self.sel_shapes.redraw()
|
||||||
|
|
||||||
def draw_shape(self, coords):
|
def draw_shape(self, shape):
|
||||||
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)
|
|
||||||
|
|
||||||
blue_t = Color('blue')
|
if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() == 'MM':
|
||||||
blue_t.alpha = 0.2
|
proc_shape = shape.buffer(-0.1)
|
||||||
self.sel_shapes.add(self.sel_rect, color='blue', face_color=blue_t, update=True, layer=0, tolerance=None)
|
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
|
# end of file
|
||||||
|
|
|
@ -470,10 +470,21 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
self.bound_obj_name = ""
|
self.bound_obj_name = ""
|
||||||
self.bound_obj = None
|
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.first_click = False
|
||||||
self.cursor_pos = None
|
self.cursor_pos = None
|
||||||
self.mouse_is_dragging = False
|
self.mouse_is_dragging = False
|
||||||
|
|
||||||
|
self.mm = None
|
||||||
|
self.mr = None
|
||||||
# store here solid_geometry when there are tool with isolation job
|
# store here solid_geometry when there are tool with isolation job
|
||||||
self.solid_geometry = []
|
self.solid_geometry = []
|
||||||
|
|
||||||
|
@ -1057,27 +1068,27 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
self.app.report_usage(_("on_paint_button_click"))
|
self.app.report_usage(_("on_paint_button_click"))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
overlap = float(self.ncc_overlap_entry.get_value())
|
self.overlap = float(self.ncc_overlap_entry.get_value())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# try to convert comma to decimal point. if it's still not working error message and return
|
# try to convert comma to decimal point. if it's still not working error message and return
|
||||||
try:
|
try:
|
||||||
overlap = float(self.ncc_overlap_entry.get_value().replace(',', '.'))
|
self.overlap = float(self.ncc_overlap_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, "
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, "
|
||||||
"use a number."))
|
"use a number."))
|
||||||
return
|
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 "
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Overlap value must be between "
|
||||||
"0 (inclusive) and 1 (exclusive), "))
|
"0 (inclusive) and 1 (exclusive), "))
|
||||||
return
|
return
|
||||||
|
|
||||||
connect = self.ncc_connect_cb.get_value()
|
self.connect = self.ncc_connect_cb.get_value()
|
||||||
contour = self.ncc_contour_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()
|
self.obj_name = self.object_combo.currentText()
|
||||||
# Get source object.
|
# Get source object.
|
||||||
|
@ -1092,34 +1103,34 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
return
|
return
|
||||||
|
|
||||||
# use the selected tools in the tool table; get diameters for non-copper clear
|
# 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
|
# 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():
|
if self.tools_table.selectedItems():
|
||||||
for x in self.tools_table.selectedItems():
|
for x in self.tools_table.selectedItems():
|
||||||
try:
|
try:
|
||||||
tooldia = float(self.tools_table.item(x.row(), 1).text())
|
self.tooldia = float(self.tools_table.item(x.row(), 1).text())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# try to convert comma to decimal point. if it's still not working error message and return
|
# try to convert comma to decimal point. if it's still not working error message and return
|
||||||
try:
|
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:
|
except ValueError:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong Tool Dia value format entered, "
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong Tool Dia value format entered, "
|
||||||
"use a number."))
|
"use a number."))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self.tools_table.cellWidget(x.row(), 4).currentText() == 'iso_op':
|
if self.tools_table.cellWidget(x.row(), 4).currentText() == 'iso_op':
|
||||||
iso_dia_list.append(tooldia)
|
self.iso_dia_list.append(self.tooldia)
|
||||||
else:
|
else:
|
||||||
ncc_dia_list.append(tooldia)
|
self.ncc_dia_list.append(self.tooldia)
|
||||||
else:
|
else:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("No selected tools in Tool Table."))
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("No selected tools in Tool Table."))
|
||||||
return
|
return
|
||||||
|
|
||||||
o_name = '%s_ncc' % self.obj_name
|
self.o_name = '%s_ncc' % self.obj_name
|
||||||
|
|
||||||
select_method = self.reference_radio.get_value()
|
self.select_method = self.reference_radio.get_value()
|
||||||
if select_method == 'itself':
|
if self.select_method == 'itself':
|
||||||
self.bound_obj_name = self.object_combo.currentText()
|
self.bound_obj_name = self.object_combo.currentText()
|
||||||
# Get source object.
|
# Get source object.
|
||||||
try:
|
try:
|
||||||
|
@ -1129,138 +1140,29 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
return "Could not retrieve object: %s" % self.obj_name
|
return "Could not retrieve object: %s" % self.obj_name
|
||||||
|
|
||||||
self.clear_copper(ncc_obj=self.ncc_obj,
|
self.clear_copper(ncc_obj=self.ncc_obj,
|
||||||
ncctooldia=ncc_dia_list,
|
ncctooldia=self.ncc_dia_list,
|
||||||
isotooldia=iso_dia_list,
|
isotooldia=self.iso_dia_list,
|
||||||
has_offset=has_offset,
|
has_offset=self.has_offset,
|
||||||
outname=o_name,
|
outname=self.o_name,
|
||||||
overlap=overlap,
|
overlap=self.overlap,
|
||||||
connect=connect,
|
connect=self.connect,
|
||||||
contour=contour,
|
contour=self.contour,
|
||||||
rest=rest)
|
rest=self.rest)
|
||||||
elif select_method == 'area':
|
elif self.select_method == 'area':
|
||||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the start point of the 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
|
if self.app.is_legacy is False:
|
||||||
# tooldia = float('%.4f' % float(self.tools_table.item(0, 1).text()))
|
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)
|
||||||
# To be called after clicking on the plot.
|
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_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:
|
else:
|
||||||
self.app.inform.emit(_("Zone added. Click to start adding next zone or right click to finish."))
|
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
|
||||||
self.app.delete_selection_shape()
|
self.app.plotcanvas.graph_event_disconnect(self.app.mm)
|
||||||
|
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
|
||||||
|
|
||||||
curr_pos = self.app.plotcanvas.translate_coords(event.pos)
|
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release)
|
||||||
if self.app.grid_status() == True:
|
self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
|
||||||
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
|
elif self.select_method == 'box':
|
||||||
|
|
||||||
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.bound_obj_name = self.box_combo.currentText()
|
self.bound_obj_name = self.box_combo.currentText()
|
||||||
# Get source object.
|
# Get source object.
|
||||||
try:
|
try:
|
||||||
|
@ -1271,14 +1173,133 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
|
|
||||||
self.clear_copper(ncc_obj=self.ncc_obj,
|
self.clear_copper(ncc_obj=self.ncc_obj,
|
||||||
sel_obj=self.bound_obj,
|
sel_obj=self.bound_obj,
|
||||||
ncctooldia=ncc_dia_list,
|
ncctooldia=self.ncc_dia_list,
|
||||||
isotooldia=iso_dia_list,
|
isotooldia=self.iso_dia_list,
|
||||||
has_offset=has_offset,
|
has_offset=self.has_offset,
|
||||||
outname=o_name,
|
outname=self.o_name,
|
||||||
overlap=overlap,
|
overlap=self.overlap,
|
||||||
connect=connect,
|
connect=self.connect,
|
||||||
contour=contour,
|
contour=self.contour,
|
||||||
rest=rest)
|
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(" <b>X</b>: %.4f "
|
||||||
|
"<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 <b>Dy</b>: "
|
||||||
|
"%.4f " % (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,
|
def clear_copper(self, ncc_obj,
|
||||||
sel_obj=None,
|
sel_obj=None,
|
||||||
|
|
|
@ -357,6 +357,13 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
self.bound_obj_name = ""
|
self.bound_obj_name = ""
|
||||||
self.bound_obj = None
|
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.units = ''
|
||||||
self.paint_tools = {}
|
self.paint_tools = {}
|
||||||
self.tooluid = 0
|
self.tooluid = 0
|
||||||
|
@ -364,6 +371,9 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
self.cursor_pos = None
|
self.cursor_pos = None
|
||||||
self.mouse_is_dragging = False
|
self.mouse_is_dragging = False
|
||||||
|
|
||||||
|
self.mm = None
|
||||||
|
self.mp = None
|
||||||
|
|
||||||
self.sel_rect = []
|
self.sel_rect = []
|
||||||
|
|
||||||
# store here the default data for Geometry Data
|
# store here the default data for Geometry Data
|
||||||
|
@ -916,17 +926,17 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
self.app.inform.emit(_("Paint Tool. Reading parameters."))
|
self.app.inform.emit(_("Paint Tool. Reading parameters."))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
overlap = float(self.paintoverlap_entry.get_value())
|
self.overlap = float(self.paintoverlap_entry.get_value())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# try to convert comma to decimal point. if it's still not working error message and return
|
# try to convert comma to decimal point. if it's still not working error message and return
|
||||||
try:
|
try:
|
||||||
overlap = float(self.paintoverlap_entry.get_value().replace(',', '.'))
|
self.overlap = float(self.paintoverlap_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||||
_("Wrong value format entered, use a number."))
|
_("Wrong value format entered, use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if overlap >= 1 or overlap < 0:
|
if self.overlap >= 1 or self.overlap < 0:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||||
_("Overlap value must be between 0 (inclusive) and 1 (exclusive)"))
|
_("Overlap value must be between 0 (inclusive) and 1 (exclusive)"))
|
||||||
return
|
return
|
||||||
|
@ -934,9 +944,9 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
||||||
_("Click inside the desired polygon."))
|
_("Click inside the desired polygon."))
|
||||||
|
|
||||||
connect = self.pathconnect_cb.get_value()
|
self.connect = self.pathconnect_cb.get_value()
|
||||||
contour = self.paintcontour_cb.get_value()
|
self.contour = self.paintcontour_cb.get_value()
|
||||||
select_method = self.selectmethod_combo.get_value()
|
self.select_method = self.selectmethod_combo.get_value()
|
||||||
|
|
||||||
self.obj_name = self.obj_combo.currentText()
|
self.obj_name = self.obj_combo.currentText()
|
||||||
|
|
||||||
|
@ -966,34 +976,34 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
o_name = '%s_multitool_paint' % self.obj_name
|
o_name = '%s_multitool_paint' % self.obj_name
|
||||||
|
|
||||||
# use the selected tools in the tool table; get diameters
|
# use the selected tools in the tool table; get diameters
|
||||||
tooldia_list = list()
|
self.tooldia_list = list()
|
||||||
if self.tools_table.selectedItems():
|
if self.tools_table.selectedItems():
|
||||||
for x in self.tools_table.selectedItems():
|
for x in self.tools_table.selectedItems():
|
||||||
try:
|
try:
|
||||||
tooldia = float(self.tools_table.item(x.row(), 1).text())
|
self.tooldia = float(self.tools_table.item(x.row(), 1).text())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# try to convert comma to decimal point. if it's still not working error message and return
|
# try to convert comma to decimal point. if it's still not working error message and return
|
||||||
try:
|
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:
|
except ValueError:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||||
_("Wrong value format entered, use a number."))
|
_("Wrong value format entered, use a number."))
|
||||||
continue
|
continue
|
||||||
tooldia_list.append(tooldia)
|
self.tooldia_list.append(self.tooldia)
|
||||||
else:
|
else:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||||
_("No selected tools in Tool Table."))
|
_("No selected tools in Tool Table."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if select_method == "all":
|
if self.select_method == "all":
|
||||||
self.paint_poly_all(self.paint_obj,
|
self.paint_poly_all(self.paint_obj,
|
||||||
tooldia=tooldia_list,
|
tooldia=self.tooldia_list,
|
||||||
outname=o_name,
|
outname=self.o_name,
|
||||||
overlap=overlap,
|
overlap=self.overlap,
|
||||||
connect=connect,
|
connect=self.connect,
|
||||||
contour=contour)
|
contour=self.contour)
|
||||||
|
|
||||||
elif select_method == "single":
|
elif self.select_method == "single":
|
||||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
||||||
_("Click inside the desired polygon."))
|
_("Click inside the desired polygon."))
|
||||||
|
|
||||||
|
@ -1005,7 +1015,10 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
# do paint single only for left mouse clicks
|
# do paint single only for left mouse clicks
|
||||||
if event.button == 1:
|
if event.button == 1:
|
||||||
self.app.inform.emit(_("Painting polygon..."))
|
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)
|
pos = self.app.plotcanvas.translate_coords(event.pos)
|
||||||
if self.app.grid_status() == True:
|
if self.app.grid_status() == True:
|
||||||
|
@ -1013,137 +1026,40 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
|
|
||||||
self.paint_poly(self.paint_obj,
|
self.paint_poly(self.paint_obj,
|
||||||
inside_pt=[pos[0], pos[1]],
|
inside_pt=[pos[0], pos[1]],
|
||||||
tooldia=tooldia_list,
|
tooldia=self.tooldia_list,
|
||||||
overlap=overlap,
|
overlap=self.overlap,
|
||||||
connect=connect,
|
connect=self.connect,
|
||||||
contour=contour)
|
contour=self.contour)
|
||||||
self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
|
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
|
||||||
self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
|
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)
|
if self.app.is_legacy is False:
|
||||||
self.app.plotcanvas.vis_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.vis_connect('mouse_press', doit)
|
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' %
|
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
||||||
_("Click the start point of the paint area."))
|
_("Click the start point of the paint area."))
|
||||||
|
|
||||||
# use the first tool in the tool table; get the diameter
|
if self.app.is_legacy is False:
|
||||||
# tooldia = float('%.4f' % float(self.tools_table.item(0, 1).text()))
|
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)
|
||||||
# To be called after clicking on the plot.
|
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_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.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:
|
else:
|
||||||
self.app.inform.emit(_("Zone added. Click to start adding next zone or right click to finish."))
|
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
|
||||||
self.app.delete_selection_shape()
|
self.app.plotcanvas.graph_event_disconnect(self.app.mm)
|
||||||
|
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
|
||||||
|
|
||||||
curr_pos = self.app.plotcanvas.translate_coords(event.pos)
|
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release)
|
||||||
if self.app.grid_status() == True:
|
self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
|
||||||
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
|
|
||||||
|
|
||||||
x0, y0 = self.cursor_pos[0], self.cursor_pos[1]
|
elif self.select_method == 'ref':
|
||||||
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':
|
|
||||||
self.bound_obj_name = self.box_combo.currentText()
|
self.bound_obj_name = self.box_combo.currentText()
|
||||||
# Get source object.
|
# Get source object.
|
||||||
try:
|
try:
|
||||||
|
@ -1156,11 +1072,137 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
|
|
||||||
self.paint_poly_ref(obj=self.paint_obj,
|
self.paint_poly_ref(obj=self.paint_obj,
|
||||||
sel_obj=self.bound_obj,
|
sel_obj=self.bound_obj,
|
||||||
tooldia=tooldia_list,
|
tooldia=self.tooldia_list,
|
||||||
overlap=overlap,
|
overlap=self.overlap,
|
||||||
outname=o_name,
|
outname=self.o_name,
|
||||||
connect=connect,
|
connect=self.connect,
|
||||||
contour=contour)
|
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(" <b>X</b>: %.4f "
|
||||||
|
"<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 <b>Dy</b>: "
|
||||||
|
"%.4f " % (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,
|
def paint_poly(self, obj,
|
||||||
inside_pt=None,
|
inside_pt=None,
|
||||||
|
@ -1199,13 +1241,15 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
# poly = find_polygon(self.solid_geometry, inside_pt)
|
# poly = find_polygon(self.solid_geometry, inside_pt)
|
||||||
if isinstance(obj, FlatCAMGerber):
|
if isinstance(obj, FlatCAMGerber):
|
||||||
if self.app.defaults["gerber_buffering"] == 'no':
|
if self.app.defaults["gerber_buffering"] == 'no':
|
||||||
self.app.inform.emit('%s %s' %
|
self.app.inform.emit('%s %s %s' %
|
||||||
(_("Paint Tool. Normal painting polygon task started."),
|
(_("Paint Tool."), _("Normal painting polygon task started."),
|
||||||
_("Buffering geometry...")))
|
_("Buffering geometry...")))
|
||||||
else:
|
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:
|
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 isinstance(obj, FlatCAMGerber):
|
||||||
if self.app.defaults["tools_paint_plotting"] == 'progressive':
|
if self.app.defaults["tools_paint_plotting"] == 'progressive':
|
||||||
|
@ -1243,7 +1287,8 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
return
|
return
|
||||||
|
|
||||||
proc = self.app.proc_container.new(_("Painting polygon..."))
|
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"
|
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.")
|
log.debug("Paint Tool. Rest machining painting all task started.")
|
||||||
if isinstance(obj, FlatCAMGerber):
|
if isinstance(obj, FlatCAMGerber):
|
||||||
if app_obj.defaults["gerber_buffering"] == 'no':
|
if app_obj.defaults["gerber_buffering"] == 'no':
|
||||||
app_obj.inform.emit('%s %s' %
|
app_obj.inform.emit('%s %s %s' %
|
||||||
(_("Paint Tool. Rest machining painting all task started."),
|
(_("Paint Tool."), _("Rest machining painting all task started."),
|
||||||
_("Buffering geometry...")))
|
_("Buffering geometry...")))
|
||||||
else:
|
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:
|
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
|
tool_dia = None
|
||||||
sorted_tools.sort(reverse=True)
|
sorted_tools.sort(reverse=True)
|
||||||
|
@ -2056,13 +2103,16 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
log.debug("Paint Tool. Normal painting area task started.")
|
log.debug("Paint Tool. Normal painting area task started.")
|
||||||
if isinstance(obj, FlatCAMGerber):
|
if isinstance(obj, FlatCAMGerber):
|
||||||
if app_obj.defaults["gerber_buffering"] == 'no':
|
if app_obj.defaults["gerber_buffering"] == 'no':
|
||||||
app_obj.inform.emit('%s %s' %
|
app_obj.inform.emit('%s %s %s' %
|
||||||
(_("Paint Tool. Normal painting area task started."),
|
(_("Paint Tool."),
|
||||||
|
_("Normal painting area task started."),
|
||||||
_("Buffering geometry...")))
|
_("Buffering geometry...")))
|
||||||
else:
|
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:
|
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
|
tool_dia = None
|
||||||
if order == 'fwd':
|
if order == 'fwd':
|
||||||
|
@ -2235,13 +2285,15 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
log.debug("Paint Tool. Rest machining painting area task started.")
|
log.debug("Paint Tool. Rest machining painting area task started.")
|
||||||
if isinstance(obj, FlatCAMGerber):
|
if isinstance(obj, FlatCAMGerber):
|
||||||
if app_obj.defaults["gerber_buffering"] == 'no':
|
if app_obj.defaults["gerber_buffering"] == 'no':
|
||||||
app_obj.inform.emit('%s %s' %
|
app_obj.inform.emit('%s %s %s' %
|
||||||
(_("Paint Tool. Rest machining painting area task started."),
|
(_("Paint Tool."),
|
||||||
|
_("Rest machining painting area task started."),
|
||||||
_("Buffering geometry...")))
|
_("Buffering geometry...")))
|
||||||
else:
|
else:
|
||||||
app_obj.inform.emit(_("Paint Tool. Rest machining painting area task started."))
|
app_obj.inform.emit(_("Paint Tool. Rest machining painting area task started."))
|
||||||
else:
|
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
|
tool_dia = None
|
||||||
sorted_tools.sort(reverse=True)
|
sorted_tools.sort(reverse=True)
|
||||||
|
|
|
@ -772,8 +772,8 @@ class Panelize(FlatCAMTool):
|
||||||
currenty += lenghty
|
currenty += lenghty
|
||||||
|
|
||||||
if panel_type == 'gerber':
|
if panel_type == 'gerber':
|
||||||
self.app.inform.emit('%s %s' %
|
self.app.inform.emit('%s' %
|
||||||
(_("Generating panel ..."), _("Adding the Gerber code.")))
|
_("Generating panel ... Adding the Gerber code."))
|
||||||
obj_fin.source_file = self.app.export_gerber(obj_name=self.outname, filename=None,
|
obj_fin.source_file = self.app.export_gerber(obj_name=self.outname, filename=None,
|
||||||
local_use=obj_fin, use_thread=False)
|
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.")
|
# app_obj.log.debug("Finished creating a cascaded union for the panel.")
|
||||||
self.app.proc_container.update_view_text('')
|
self.app.proc_container.update_view_text('')
|
||||||
|
|
||||||
self.app.inform.emit('%s %s: %d' %
|
self.app.inform.emit('%s: %d' %
|
||||||
(_("Generating panel ..."), _("Spawning copies"), (int(rows * columns))))
|
(_("Generating panel... Spawning copies"), (int(rows * columns))))
|
||||||
if isinstance(panel_obj, FlatCAMExcellon):
|
if isinstance(panel_obj, FlatCAMExcellon):
|
||||||
self.app.progress.emit(50)
|
self.app.progress.emit(50)
|
||||||
self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True)
|
self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True)
|
||||||
|
|
|
@ -311,7 +311,7 @@ class ToolSub(FlatCAMTool):
|
||||||
|
|
||||||
log.debug("Working on promise: %s" % str(apid))
|
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:
|
for geo_el in geo:
|
||||||
new_el = dict()
|
new_el = dict()
|
||||||
|
|
||||||
|
@ -520,7 +520,7 @@ class ToolSub(FlatCAMTool):
|
||||||
if tool == "single":
|
if tool == "single":
|
||||||
text = _("Parsing solid_geometry ...")
|
text = _("Parsing solid_geometry ...")
|
||||||
else:
|
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):
|
with self.app.proc_container.new(text):
|
||||||
# resulting paths are closed resulting into Polygons
|
# resulting paths are closed resulting into Polygons
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
# This file contains python only requirements to be installed with pip
|
# 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.
|
# Python pacakges that cannot be installed with pip (e.g. PyQt5, GDAL) are not included.
|
||||||
# Usage: pip install -r requirements.txt
|
# 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
|
dill
|
||||||
rtree
|
rtree
|
||||||
pyopengl
|
pyopengl
|
||||||
|
|
|
@ -14,6 +14,9 @@ apt-get install python3-tk
|
||||||
apt-get install libspatialindex-dev
|
apt-get install libspatialindex-dev
|
||||||
apt-get install python3-gdal
|
apt-get install python3-gdal
|
||||||
apt-get install python3-lxml
|
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 dill
|
||||||
pip3 install --upgrade Shapely
|
pip3 install --upgrade Shapely
|
||||||
pip3 install --upgrade vispy
|
pip3 install --upgrade vispy
|
||||||
|
|
BIN
share/active.gif
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 389 B |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 489 B |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 281 B |
After Width: | Height: | Size: 306 B |
Before Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 831 B |
After Width: | Height: | Size: 247 B |
BIN
share/splash.png
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 85 KiB |
|
@ -42,5 +42,5 @@ class TclCommandPlotAll(TclCommand):
|
||||||
:param unnamed_args:
|
:param unnamed_args:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
if self.app.cmd_line_headless != 1:
|
||||||
self.app.plot_all()
|
self.app.plot_all()
|
||||||
|
|
|
@ -42,6 +42,7 @@ class TclCommandPlotObjects(TclCommand):
|
||||||
:param unnamed_args:
|
:param unnamed_args:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
if self.app.cmd_line_headless != 1:
|
||||||
names = [x.strip() for x in args['names'].split(",")]
|
names = [x.strip() for x in args['names'].split(",")]
|
||||||
objs = []
|
objs = []
|
||||||
for name in names:
|
for name in names:
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -48,6 +48,7 @@ import tclCommands.TclCommandPaint
|
||||||
import tclCommands.TclCommandPanelize
|
import tclCommands.TclCommandPanelize
|
||||||
import tclCommands.TclCommandPlotAll
|
import tclCommands.TclCommandPlotAll
|
||||||
import tclCommands.TclCommandPlotObjects
|
import tclCommands.TclCommandPlotObjects
|
||||||
|
import tclCommands.TclCommandQuit
|
||||||
import tclCommands.TclCommandSaveProject
|
import tclCommands.TclCommandSaveProject
|
||||||
import tclCommands.TclCommandSaveSys
|
import tclCommands.TclCommandSaveSys
|
||||||
import tclCommands.TclCommandScale
|
import tclCommands.TclCommandScale
|
||||||
|
|
|
@ -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_()
|