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

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

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ from datetime import datetime
from flatcamGUI.ObjectUI import * from 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()")

View File

@ -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"

View File

@ -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:

View File

@ -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

View File

@ -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...")

4
descartes/__init__.py Normal file
View File

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

66
descartes/patch.py Normal file
View File

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

View File

@ -2012,8 +2012,14 @@ class FlatCAMExcEditor(QtCore.QObject):
self.exc_obj = None 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&nbsp;&nbsp; <b>Dy</b>: " self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0)) "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (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.

View File

@ -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&nbsp;&nbsp; <b>Dy</b>: " self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
@ -3649,8 +3672,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.defaults["global_point_clipboard_format"] % (self.pos[0], self.pos[1])) 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&nbsp;&nbsp; <b>Dy</b>: " self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy)) "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
if event.button == 1 and event.is_dragging and isinstance(self.active_tool, FCEraser): if event.button == 1 and event_is_dragging and isinstance(self.active_tool, FCEraser):
pass 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)

View File

@ -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&nbsp;&nbsp; <b>Dy</b>: " self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0)) "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (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:

File diff suppressed because it is too large Load Diff

View File

@ -152,10 +152,10 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
except Exception as e: 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:

File diff suppressed because it is too large Load Diff

4724
flatcamGUI/PreferencesUI.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -298,6 +298,11 @@ class CutOut(FlatCAMTool):
# if mouse is dragging set the object True # 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)

View File

@ -45,10 +45,10 @@ class Measurement(FlatCAMTool):
self.units_value = QtWidgets.QLabel("%s" % str({'mm': _("METRIC (mm)"), 'in': _("INCH (in)")}[self.units])) self.units_value = 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&nbsp;&nbsp; <b>Dy</b>: " self.app.ui.rel_position_label.setText("<b>Dx</b>: {0:.4f}&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (pos[0], pos[1])) "{0:.4f}&nbsp;&nbsp;&nbsp;&nbsp;".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("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: {0:.4f}&nbsp;&nbsp; "
"<b>Y</b>: {0:.4f}".format(pos[0], pos[1]))
if self.rel_point1 is not None: 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("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; " self.app.ui.rel_position_label.setText("<b>Dx</b>: {0:.4f}&nbsp;&nbsp; <b>Dy</b>: "
"<b>Y</b>: %.4f" % (pos[0], pos[1])) "{0:.4f}&nbsp;&nbsp;&nbsp;&nbsp;".format(dx, dy))
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (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()

View File

@ -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

View 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("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"<b>Y</b>: %.4f" % (curr_pos[0], curr_pos[1]))
if self.cursor_pos is None:
self.cursor_pos = (0, 0)
dx = curr_pos[0] - float(self.cursor_pos[0])
dy = curr_pos[1] - float(self.cursor_pos[1])
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
# draw the utility geometry
if self.first_click:
self.app.delete_selection_shape()
self.app.draw_moving_selection_shape(old_coords=(self.cursor_pos[0], self.cursor_pos[1]),
coords=(curr_pos[0], curr_pos[1]))
def clear_copper(self, ncc_obj, def clear_copper(self, ncc_obj,
sel_obj=None, sel_obj=None,

View File

@ -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("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"<b>Y</b>: %.4f" % (curr_pos[0], curr_pos[1]))
if self.cursor_pos is None:
self.cursor_pos = (0, 0)
dx = curr_pos[0] - float(self.cursor_pos[0])
dy = curr_pos[1] - float(self.cursor_pos[1])
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (dx, dy))
# draw the utility geometry
if self.first_click:
self.app.delete_selection_shape()
self.app.draw_moving_selection_shape(old_coords=(self.cursor_pos[0], self.cursor_pos[1]),
coords=(curr_pos[0], curr_pos[1]))
def paint_poly(self, obj, 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)

View File

@ -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)

View File

@ -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

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,13 @@
# This file contains python only requirements to be installed with pip # 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

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 30 KiB

BIN
share/active_2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
share/active_2_static.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

BIN
share/active_3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
share/active_3_static.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

BIN
share/active_4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
share/active_4_static.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

BIN
share/active_static.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

BIN
share/script14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

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

View File

@ -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:

View File

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

View File

@ -48,6 +48,7 @@ import tclCommands.TclCommandPaint
import tclCommands.TclCommandPanelize import tclCommands.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

158
tests/titlebar_custom.py Normal file
View File

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