Merged in marius_stanciu/flatcam_beta/Beta (pull request #300)
Beta 8.992
This commit is contained in:
commit
bea3fbe488
79
CHANGELOG.md
79
CHANGELOG.md
|
@ -7,11 +7,28 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
=================================================
|
||||
|
||||
27.04.2020
|
||||
|
||||
- finished the moving of all Tcl Shell stuff out of the FlatCAAMApp class to flatcamTools.ToolShell class
|
||||
- updated the requirements.txt file to request that the Shapely package needs to be at least version 1.7.0 as it is needed in the latest versions of FlatCAM beta
|
||||
- some TOOD cleanups
|
||||
- minor changes
|
||||
- replaced the testing if instance of FlatCAMObj with testing the obj.kind attribute
|
||||
- removed the import of the whole FlatCAMApp file only for the usage of GracefulException
|
||||
- remove the import of FlatCAMApp and used alternate ways
|
||||
- optimized the imports in some files
|
||||
- moved the Bookmarksmanager and ToolDB classes into their own files
|
||||
- solved some bugs that were not so visible in the Editors and HPGL parser
|
||||
- split the FlatCAMObj file into multiple files located in the flatcamObjects folder and renamed the contained classes with names more suggestive
|
||||
- updated the Google Translation for the German language
|
||||
- added support for Hungarian language - no translation for now
|
||||
|
||||
25.04.2020
|
||||
|
||||
- ensured that on Graceful Exit (CTRL+ALT+X key combo) if using Progressive Plotting, the eventual residual plotted lines are deleted. This apply for Tool NCC and Tool Paint
|
||||
- fixed links in Attributions tab in Help -> About FlatCAM to be able to open external links.
|
||||
- updated Google Translations for French and Spanish languages
|
||||
- added some '\n' chars in the Help Tcl command to make the help more readable
|
||||
|
||||
24.04.2020
|
||||
|
||||
|
@ -282,7 +299,7 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
12.02.2020
|
||||
|
||||
- working on fixing a bug in FlatCAMGeometry.merge() - FIXED issue #380
|
||||
- working on fixing a bug in GeometryObject.merge() - FIXED issue #380
|
||||
- fixed bug: when deleting a FlatCAMCNCJob with annotations enabled, the annotations are not deleted from canvas; fixed issue #379
|
||||
- fixed bug: creating a new project while a project is open and it contain CNCJob annotations and/or Gerber mark shapes, did not delete them from canvas
|
||||
|
||||
|
@ -637,7 +654,7 @@ CHANGELOG for FlatCAM beta
|
|||
- modified the Jump To method such that now allows relative jump from the current mouse location
|
||||
- fixed the Defaults upgrade overwriting the new version number with the old one
|
||||
- fixed issue with clear_polygon3() - the one who makes 'lines' and fixed the NCC Tool
|
||||
- some small changes in the FlatCAMGeometry.on_tool_add() method
|
||||
- some small changes in the GeometryObject.on_tool_add() method
|
||||
- made sure that in Geometry Editor the self.app.mouse attribute is updated with the current mouse position (x, y)
|
||||
- updated the preprocessor files
|
||||
- fixed the HPGL preprocessor
|
||||
|
@ -680,7 +697,7 @@ CHANGELOG for FlatCAM beta
|
|||
- changed the Scale Entry in Object UI to FCEntry() GUI element in order to allow expressions to be entered. E.g: 1/25.4
|
||||
- some small changes in the Scale button handler in FlatCAMObj() class
|
||||
- added option to save objects as PDF files in File -> Save menu
|
||||
- optimized the FlatCAMGerber.clear_plot_apertures() method
|
||||
- optimized the GerberObject.clear_plot_apertures() method
|
||||
- some changes in the ObjectUI and for the Geometry UI
|
||||
- finished a very rough and limited HPGL2 file import
|
||||
|
||||
|
@ -710,7 +727,7 @@ CHANGELOG for FlatCAM beta
|
|||
- reverted this change: "selected object in Project used to ask twice for UI build" because it will not build the UI when a tab is closed for Document object and the object is selected
|
||||
- fixed issue after Geometry object edit; the GCode made from an edited object did not reflect the changes in the object
|
||||
- in Object UI, the Scale FCDoubleSpinner will no longer work for Return key press due of issues of unwanted scaling on focusOut event
|
||||
- in FlatCAMGeometry fixed the scale and offset methods to always process the self.solid_geometry
|
||||
- in GeometryObject fixed the scale and offset methods to always process the self.solid_geometry
|
||||
- Calibration Tool - finished the calibrated object creation method
|
||||
- updated the POT file
|
||||
- fixed an error in the German PO file
|
||||
|
@ -801,7 +818,7 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
28.11.2019
|
||||
|
||||
- small fixes in NCC Tool and in the FlatCAMGeometry class
|
||||
- small fixes in NCC Tool and in the GeometryObject class
|
||||
|
||||
27.11.2019
|
||||
|
||||
|
@ -819,7 +836,7 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
- In Gerber isolation changed the UI
|
||||
- in Gerber isolation added the option to selectively isolate only certain polygons
|
||||
- made some optimizations in FlatCAMGerber.isolate() method
|
||||
- made some optimizations in GerberObject.isolate() method
|
||||
- updated the 'single' isolation of Gerber polygons to remove the polygon if clicked on it and it is already in the list of single polygons to be isolated
|
||||
- clicking to add a polygon when doing Single type isolation will add a blue shape marking the selected polygon, second click will remove that shape
|
||||
- fixed bugs in Paint Tool when painting single polygon
|
||||
|
@ -830,7 +847,7 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
- in Tool Fiducials added a new fiducial type: chess pattern
|
||||
- work in Calibrate Excellon Tool
|
||||
- fixed the line numbers in the TextPlainEdit to fit all digits of the line number; activated the line numbers for FlatCAMScript objects too
|
||||
- fixed the line numbers in the TextPlainEdit to fit all digits of the line number; activated the line numbers for ScriptObject objects too
|
||||
- line numbers in the TextPlainEdit for the selected line are bold
|
||||
- made sure that the self.defaults dictionary is deepcopy-ed in the self.options dictionary
|
||||
- made sure that the units are read from the self.defaults and not from the GUI
|
||||
|
@ -842,7 +859,7 @@ CHANGELOG for FlatCAM beta
|
|||
- Tool Fiducials - updated the source_file object for the modified Gerber files
|
||||
- working on adding line numbers to the TextPlainEdit
|
||||
- GCode view now has line numbers
|
||||
- solved a bug that made selection of objects on canvas impossible if there is an object of type FlatCAMScript or FlatCAMDocument opened
|
||||
- solved a bug that made selection of objects on canvas impossible if there is an object of type ScriptObject or DocumentObject opened
|
||||
|
||||
21.11.2019
|
||||
|
||||
|
@ -899,7 +916,7 @@ CHANGELOG for FlatCAM beta
|
|||
- trying to improve the performance of View CNC Code command by using QPlainTextEdit; made the mods for it
|
||||
- when using the Find function in the TextEditor and the result reach the bottom of the document, the next find will be the first in the document (before it defaulted to the beginning of the document)
|
||||
- finished improving the show of text files in FlatCAM (CNC Code, Source files)
|
||||
- fixed an issue in the FlatCAMObj.FlatCAMGerber.convert_units() which needed to be updated after changes elsewhere
|
||||
- fixed an issue in the FlatCAMObj.GerberObject.convert_units() which needed to be updated after changes elsewhere
|
||||
|
||||
12.11.2019
|
||||
|
||||
|
@ -937,7 +954,7 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
- the "CRTL+S" key combo when the Preferences Tab is in focus will save the Preferences instead of saving the Project
|
||||
- fixed bug in the Paint Tool that did not allow choosing a Paint Method that was not Standard
|
||||
- made sure that in the FlatCAMGeometry.merge() all the source data is deepcopy-ed in the final object
|
||||
- made sure that in the GeometryObject.merge() all the source data is deepcopy-ed in the final object
|
||||
- the font color of the Preferences tab will change to red if settings are not saved and it will revert to default when saved
|
||||
- fixed issue #333. The Geometry Editor Paint tool was not working and using it resulted in an error
|
||||
|
||||
|
@ -1149,7 +1166,7 @@ CHANGELOG for FlatCAM beta
|
|||
- added a dark theme to FlatCAM (only for canvas). The selection is done in Edit -> Preferences -> General -> GUI Settings
|
||||
- updated the .POT file and worked a bit in the romanian translation
|
||||
- small changes: reduced the thickness of the axis in 3D mode from 3 pixels to 1 pixel
|
||||
- made sure that is the text in the source file of a FlatCAMDocument is HTML is loaded as such
|
||||
- made sure that is the text in the source file of a DocumentObject is HTML is loaded as such
|
||||
- added inverted icons
|
||||
|
||||
6.10.2019
|
||||
|
@ -1193,20 +1210,20 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
3.10.2019
|
||||
|
||||
- previously I've added the initial layout for the FlatCAMDocument object
|
||||
- added more editing features in the Selected Tab for the FlatCAMDocument object
|
||||
- previously I've added the initial layout for the DocumentObject object
|
||||
- added more editing features in the Selected Tab for the DocumentObject object
|
||||
|
||||
2.10.2019
|
||||
|
||||
- fixed bug in Geometry Editor that did not allow the copy of geometric elements
|
||||
- created a new class that holds all the Code Editor functionality and integrated as a Editor in FlatCAM, the location is in flatcamEditors folder
|
||||
- remade all the functions for view_source, scripts and view_code to use the new TextEditor class; now all the Code Editor tabs are being kept alive, before only one could be in an open state
|
||||
- changed the name of the new object FlatCAMNotes to a more general one FlatCAMDocument
|
||||
- changed the way a new FlatCAMScript object is made, the method that is processing the Tcl commands when the Run button is clicked is moved to the FlatCAMObj.FlatCAMScript() class
|
||||
- changed the name of the new object FlatCAMNotes to a more general one DocumentObject
|
||||
- changed the way a new ScriptObject object is made, the method that is processing the Tcl commands when the Run button is clicked is moved to the FlatCAMObj.ScriptObject() class
|
||||
- reused the Multiprocessing Pool declared in the App for the ToolRulesCheck() class
|
||||
- adapted the Project context menu for the new types of FLatCAM objects
|
||||
- modified the setup_recent_files to accommodate the new FlatCAM objects
|
||||
- made sure that when an FlatCAMScript object is deleted, it's associated Tab is closed
|
||||
- made sure that when an ScriptObject object is deleted, it's associated Tab is closed
|
||||
- fixed the FlatCMAScript object saving when project is saved (loading a project with this script object is not working yet)
|
||||
- fixed the FlatCMAScript object when loading it from a project
|
||||
|
||||
|
@ -1220,7 +1237,7 @@ CHANGELOG for FlatCAM beta
|
|||
- added new settings for the Gerber newly introduced feature to isolate with the V-Shape tools (tip dia, tip angle, tool_type and cut Z) in Edit -> Preferences -> Gerber Advanced
|
||||
- made those settings just added for Gerber, to be updated on object creation
|
||||
- added the Geo Tolerance parameter to those that are converted from MM to INCH
|
||||
- added two new FlatCAM objects: FlatCAMScript and FlatCAMNotes
|
||||
- added two new FlatCAM objects: ScriptObject and FlatCAMNotes
|
||||
|
||||
30.09.2019
|
||||
|
||||
|
@ -1443,7 +1460,7 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
15.09.2019
|
||||
|
||||
- refactored FlatCAMGeometry.mtool_gen_cncjob() method
|
||||
- refactored GeometryObject.mtool_gen_cncjob() method
|
||||
- fixed the TclCommandCncjob to work for multigeometry Geometry objects; still I had to fix the list of tools parameter, right now I am setting it to an empty list
|
||||
- update the Tcl Command isolate to be able to isolate exteriors, interiors besides the full isolation, using the iso_type parameter
|
||||
- fixed issue in ToolPaint that could not allow area painting of a geometry that was a list and not a Geometric element (polygon or MultiPolygon)
|
||||
|
@ -1819,7 +1836,7 @@ CHANGELOG for FlatCAM beta
|
|||
- done regression to solve the bug with multiple passes cutting from the copper features (I should remember not to make mods here)
|
||||
- if 'combine' is checked in Gerber isolation but there is only one pass, the resulting geometry will still be single geo
|
||||
- the 'passes' entry was changed to a IntSpinner so it will allow passes to be entered only in range (1, 999) - it will not allow entry of 0 which may create some issues
|
||||
- improved the FlatCAMGerber.isolate() function to work for geometry in the form of list and also in case that the elements of the list are LinearRings (like when doing the Exterior Isolation)
|
||||
- improved the GerberObject.isolate() function to work for geometry in the form of list and also in case that the elements of the list are LinearRings (like when doing the Exterior Isolation)
|
||||
- in NCC Tool made sure that at each run the old objects are deleted
|
||||
- fixed bug in camlib.Gerber.parse_lines() Gerber parser where for Allegro Gerber files the Gerber units were incorrectly detected
|
||||
- improved Mark Area Tool in Gerber Editor such that at each launch the previous markings are deleted
|
||||
|
@ -1914,7 +1931,7 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
19.07.2019
|
||||
|
||||
- fixed bug in FlatCAMObj.FlatCAMGeometry.ui_disconnect(); the widgets signals were not disconnected from handlers when required therefore the signals were connected in an exponential way
|
||||
- fixed bug in FlatCAMObj.GeometryObject.ui_disconnect(); the widgets signals were not disconnected from handlers when required therefore the signals were connected in an exponential way
|
||||
- some changes in the widgets used in the Selected tab for Geometry object
|
||||
- some PEP8 cleanup in FlatCAMObj.py
|
||||
- updated languages
|
||||
|
@ -2045,7 +2062,7 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
- fixed bug in ToolCutout where creating a cutout object geometry from another external isolation geometry failed
|
||||
- fixed bug in cncjob TclCommand where the gcode could not be correctly generated due of missing bounds params in obj.options dict
|
||||
- fixed a hardcoded tolerance in FlatCAMGeometry.generatecncjob() and in FlatCAMGeometry.mtool_gen_cncjob() to use the parameter from Preferences
|
||||
- fixed a hardcoded tolerance in GeometryObject.generatecncjob() and in GeometryObject.mtool_gen_cncjob() to use the parameter from Preferences
|
||||
- updated translations
|
||||
|
||||
5.06.2019
|
||||
|
@ -2219,7 +2236,7 @@ CHANGELOG for FlatCAM beta
|
|||
- fixed some bugs related to moving an Gerber object with the aperture table in view
|
||||
- added a new parameter in the Edit -> Preferences -> App Preferences named Geo Tolerance. This parameter control the level of geometric detail throughout FlatCAM. It directly influence the effect of Circle Steps parameter.
|
||||
- solved a bug in Excellon Editor that caused app crash when trying to edit a tool in Tool Table due of missing a tool offset
|
||||
- updated the ToolPanelize tool so the Gerber panel of type FlatCAMGerber can be isolated like any other FlatCAMGerber object
|
||||
- updated the ToolPanelize tool so the Gerber panel of type GerberObject can be isolated like any other GerberObject object
|
||||
- updated the ToolPanelize tool so it can be edited
|
||||
- modified the default values for toolchangez and endz parameters so they are now safe in all cases
|
||||
|
||||
|
@ -2703,7 +2720,7 @@ CHANGELOG for FlatCAM beta
|
|||
- added ability to mark individual apertures in Gerber file using the Gerber Aperture Table
|
||||
- more modifications for the Gerber UI layout; made 'follow' an advanced Gerber option
|
||||
- added in Preferences a new Category: Gerber Advanced Options. For now it controls the display of Gerber Aperture Table and the "follow" attribute4
|
||||
- fixed FlatCAMGerber.merge() to merge the self.apertures[ap]['solid_geometry'] too
|
||||
- fixed GerberObject.merge() to merge the self.apertures[ap]['solid_geometry'] too
|
||||
- started to work on a new feature that allow adding a ToolChange GCode macro - GUI added both in CNCJob Selected tab and in CNCJob Preferences
|
||||
- added a limited 'sort-of' Gerber Editor: it allows buffering and scaling of apertures
|
||||
|
||||
|
@ -2846,7 +2863,7 @@ CHANGELOG for FlatCAM beta
|
|||
- added total travel distance for CNCJob object created from Excellon Object in the CNCJob Selected tab
|
||||
- added 'FlatCAM ' prefix to any detached tab, for easy identification
|
||||
- remade the Grids context menu (right mouse button click on canvas). Now it has values linked to the units type (inch or mm). Added ability to add or delete grid values and they are persistent.
|
||||
- updated the function for the project context menu 'Generate CNC' menu entry (Action) to use the modernized function FlatCAMObj.FlatCAMGeometry.on_generatecnc_button_click()
|
||||
- updated the function for the project context menu 'Generate CNC' menu entry (Action) to use the modernized function FlatCAMObj.GeometryObject.on_generatecnc_button_click()
|
||||
- when linked, the grid snap on Y will copy the value in grid snap on X in real time
|
||||
- in Gerber aperture table now the values are displayed in the current units set in FlatCAM
|
||||
- added shortcut key 'J' (jump to location) in Editors and added an icon to the dialog popup window
|
||||
|
@ -2863,7 +2880,7 @@ CHANGELOG for FlatCAM beta
|
|||
- finished Gerber aperture table display
|
||||
- made the Gerber aperture table not visible as default and added a checkbox that can toggle the visibility
|
||||
- fixed issue with plotting in CNCJob; with Plot kind set to something else than 'all' when toggling Plot, it was defaulting to kind = 'all'
|
||||
- added (and commented) an experimental FlatCAMObj.FlatCAMGerber.plot_aperture()
|
||||
- added (and commented) an experimental FlatCAMObj.GerberObject.plot_aperture()
|
||||
|
||||
12.02.2019
|
||||
|
||||
|
@ -3052,7 +3069,7 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
28.01.2018
|
||||
|
||||
- fixed the FlatCAMGerber.merge() function
|
||||
- fixed the GerberObject.merge() function
|
||||
- added a new menu entry for the Gerber Join function: Edit -> Conversions -> "Join Gerber(s) to Gerber" allowing joining Gerber objects into a final Gerber object
|
||||
- moved Paint Tool defaults from Geometry section to the Tools section in Edit -> Preferences
|
||||
- added key shortcuts for Open Manual = F1 and for Open Online VideoHelp = F2
|
||||
|
@ -3075,13 +3092,13 @@ CHANGELOG for FlatCAM beta
|
|||
- added new entries to the Canvas context menu (Copy, Delete, Edit/Save, Move, New Excellon, New Geometry, New Project)
|
||||
- fixed GRBL_laser preprocessor file
|
||||
- updated function for copy of an Excellon object for the case when the object has slots
|
||||
- updated FlatCAMExcellon.merge() function to work in case some (or all) of the merged objects have slots
|
||||
- updated ExcellonObject.merge() function to work in case some (or all) of the merged objects have slots
|
||||
|
||||
25.01.2019
|
||||
|
||||
- deleted junk folders
|
||||
- remade the Panelize Tool: now it is much faster, it is multi-threaded, it works with multitool geometries and it works with multigeo geometries too.
|
||||
- made sure to copy the options attribute to the final object in the case of: FlatCAMGeometry.merge(), FlatCAMGerber.merge() and for the Panelize Tool
|
||||
- made sure to copy the options attribute to the final object in the case of: GeometryObject.merge(), GerberObject.merge() and for the Panelize Tool
|
||||
- modified the panelize TclCommand to take advantage of the new panelize() function; added a 'threaded' parameter (default value is 1) which controls the execution of the panelize TclCommand: threaded or non-threaded
|
||||
- fixed TclCommand Cutout
|
||||
- added a new TclCommand named CutoutAny. Keyword: cutout_any
|
||||
|
@ -3164,7 +3181,7 @@ CHANGELOG for FlatCAM beta
|
|||
- fixed the initial text in the ToolShell
|
||||
- reactivated the version check in case the release is not BETA; FlatCAMApp.App has now a beta object that when set True the application will show in the Title and help-> About that is Beta (and it disable version checking)
|
||||
- added a new name (mine: for good and/or bad) to the contributors list
|
||||
- fixed the Join function to work on Gerber and Excellon, Gerber and Gerber, Excellon and Excelon combination of objects. The merged property is the solid_geometry and the result is a FlatCAMGeometry object.
|
||||
- fixed the Join function to work on Gerber and Excellon, Gerber and Gerber, Excellon and Excelon combination of objects. The merged property is the solid_geometry and the result is a GeometryObject object.
|
||||
|
||||
3.01.2019
|
||||
|
||||
|
@ -3246,8 +3263,8 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
18.12.2018
|
||||
|
||||
- small changes in FlatCAMGeometry.plot()
|
||||
- updated the FlatCAMGeometry.merge() function and the Join Geometry feature to accommodate the different types of geometries: singlegeo and multigeo type
|
||||
- small changes in GeometryObject.plot()
|
||||
- updated the GeometryObject.merge() function and the Join Geometry feature to accommodate the different types of geometries: singlegeo and multigeo type
|
||||
- added Conversion submenu in Edit where I moved the Join features and added the Convert from MultiGeo to SingleGeo type and the reverse
|
||||
- added Copy Tool (on a selection of tools) feature in Geometry Object UI
|
||||
- fixed the bounds() method for the MultiGeo geometry object so the canvas selection is working and also the Properties Tool
|
||||
|
|
577
FlatCAMApp.py
577
FlatCAMApp.py
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,381 @@
|
|||
from PyQt5 import QtGui, QtCore, QtWidgets
|
||||
from flatcamGUI.GUIElements import FCTable, FCEntry, FCButton, FCFileSaveDialog
|
||||
|
||||
import sys
|
||||
import webbrowser
|
||||
|
||||
from copy import deepcopy
|
||||
from datetime import datetime
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class BookmarkManager(QtWidgets.QWidget):
|
||||
|
||||
mark_rows = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, app, storage, parent=None):
|
||||
super(BookmarkManager, self).__init__(parent)
|
||||
|
||||
self.app = app
|
||||
|
||||
assert isinstance(storage, dict), "Storage argument is not a dictionary"
|
||||
|
||||
self.bm_dict = deepcopy(storage)
|
||||
|
||||
# Icon and title
|
||||
# self.setWindowIcon(parent.app_icon)
|
||||
# self.setWindowTitle(_("Bookmark Manager"))
|
||||
# self.resize(600, 400)
|
||||
|
||||
# title = QtWidgets.QLabel(
|
||||
# "<font size=8><B>FlatCAM</B></font><BR>"
|
||||
# )
|
||||
# title.setOpenExternalLinks(True)
|
||||
|
||||
# layouts
|
||||
layout = QtWidgets.QVBoxLayout()
|
||||
self.setLayout(layout)
|
||||
|
||||
table_hlay = QtWidgets.QHBoxLayout()
|
||||
layout.addLayout(table_hlay)
|
||||
|
||||
self.table_widget = FCTable(drag_drop=True, protected_rows=[0, 1])
|
||||
self.table_widget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
table_hlay.addWidget(self.table_widget)
|
||||
|
||||
self.table_widget.setColumnCount(3)
|
||||
self.table_widget.setColumnWidth(0, 20)
|
||||
self.table_widget.setHorizontalHeaderLabels(
|
||||
[
|
||||
'#',
|
||||
_('Title'),
|
||||
_('Web Link')
|
||||
]
|
||||
)
|
||||
self.table_widget.horizontalHeaderItem(0).setToolTip(
|
||||
_("Index.\n"
|
||||
"The rows in gray color will populate the Bookmarks menu.\n"
|
||||
"The number of gray colored rows is set in Preferences."))
|
||||
self.table_widget.horizontalHeaderItem(1).setToolTip(
|
||||
_("Description of the link that is set as an menu action.\n"
|
||||
"Try to keep it short because it is installed as a menu item."))
|
||||
self.table_widget.horizontalHeaderItem(2).setToolTip(
|
||||
_("Web Link. E.g: https://your_website.org "))
|
||||
|
||||
# pal = QtGui.QPalette()
|
||||
# pal.setColor(QtGui.QPalette.Background, Qt.white)
|
||||
|
||||
# New Bookmark
|
||||
new_vlay = QtWidgets.QVBoxLayout()
|
||||
layout.addLayout(new_vlay)
|
||||
|
||||
new_title_lbl = QtWidgets.QLabel('<b>%s</b>' % _("New Bookmark"))
|
||||
new_vlay.addWidget(new_title_lbl)
|
||||
|
||||
form0 = QtWidgets.QFormLayout()
|
||||
new_vlay.addLayout(form0)
|
||||
|
||||
title_lbl = QtWidgets.QLabel('%s:' % _("Title"))
|
||||
self.title_entry = FCEntry()
|
||||
form0.addRow(title_lbl, self.title_entry)
|
||||
|
||||
link_lbl = QtWidgets.QLabel('%s:' % _("Web Link"))
|
||||
self.link_entry = FCEntry()
|
||||
self.link_entry.set_value('http://')
|
||||
form0.addRow(link_lbl, self.link_entry)
|
||||
|
||||
# Buttons Layout
|
||||
button_hlay = QtWidgets.QHBoxLayout()
|
||||
layout.addLayout(button_hlay)
|
||||
|
||||
add_entry_btn = FCButton(_("Add Entry"))
|
||||
remove_entry_btn = FCButton(_("Remove Entry"))
|
||||
export_list_btn = FCButton(_("Export List"))
|
||||
import_list_btn = FCButton(_("Import List"))
|
||||
# closebtn = QtWidgets.QPushButton(_("Close"))
|
||||
|
||||
# button_hlay.addStretch()
|
||||
button_hlay.addWidget(add_entry_btn)
|
||||
button_hlay.addWidget(remove_entry_btn)
|
||||
|
||||
button_hlay.addWidget(export_list_btn)
|
||||
button_hlay.addWidget(import_list_btn)
|
||||
# button_hlay.addWidget(closebtn)
|
||||
# ##############################################################################
|
||||
# ######################## SIGNALS #############################################
|
||||
# ##############################################################################
|
||||
|
||||
add_entry_btn.clicked.connect(self.on_add_entry)
|
||||
remove_entry_btn.clicked.connect(self.on_remove_entry)
|
||||
export_list_btn.clicked.connect(self.on_export_bookmarks)
|
||||
import_list_btn.clicked.connect(self.on_import_bookmarks)
|
||||
self.title_entry.returnPressed.connect(self.on_add_entry)
|
||||
self.link_entry.returnPressed.connect(self.on_add_entry)
|
||||
# closebtn.clicked.connect(self.accept)
|
||||
|
||||
self.table_widget.drag_drop_sig.connect(self.mark_table_rows_for_actions)
|
||||
self.build_bm_ui()
|
||||
|
||||
def build_bm_ui(self):
|
||||
|
||||
self.table_widget.setRowCount(len(self.bm_dict))
|
||||
|
||||
nr_crt = 0
|
||||
sorted_bookmarks = sorted(list(self.bm_dict.items()), key=lambda x: int(x[0]))
|
||||
for entry, bookmark in sorted_bookmarks:
|
||||
row = nr_crt
|
||||
nr_crt += 1
|
||||
|
||||
title = bookmark[0]
|
||||
weblink = bookmark[1]
|
||||
|
||||
id_item = QtWidgets.QTableWidgetItem('%d' % int(nr_crt))
|
||||
# id.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
||||
self.table_widget.setItem(row, 0, id_item) # Tool name/id
|
||||
|
||||
title_item = QtWidgets.QTableWidgetItem(title)
|
||||
self.table_widget.setItem(row, 1, title_item)
|
||||
|
||||
weblink_txt = QtWidgets.QTextBrowser()
|
||||
weblink_txt.setOpenExternalLinks(True)
|
||||
weblink_txt.setFrameStyle(QtWidgets.QFrame.NoFrame)
|
||||
weblink_txt.document().setDefaultStyleSheet("a{ text-decoration: none; }")
|
||||
|
||||
weblink_txt.setHtml('<a href=%s>%s</a>' % (weblink, weblink))
|
||||
|
||||
self.table_widget.setCellWidget(row, 2, weblink_txt)
|
||||
|
||||
vertical_header = self.table_widget.verticalHeader()
|
||||
vertical_header.hide()
|
||||
|
||||
horizontal_header = self.table_widget.horizontalHeader()
|
||||
horizontal_header.setMinimumSectionSize(10)
|
||||
horizontal_header.setDefaultSectionSize(70)
|
||||
horizontal_header.setSectionResizeMode(0, QtWidgets.QHeaderView.Fixed)
|
||||
horizontal_header.resizeSection(0, 20)
|
||||
horizontal_header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
|
||||
horizontal_header.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
|
||||
|
||||
self.mark_table_rows_for_actions()
|
||||
|
||||
self.app.defaults["global_bookmarks"].clear()
|
||||
for key, val in self.bm_dict.items():
|
||||
self.app.defaults["global_bookmarks"][key] = deepcopy(val)
|
||||
|
||||
def on_add_entry(self, **kwargs):
|
||||
"""
|
||||
Add a entry in the Bookmark Table and in the menu actions
|
||||
:return: None
|
||||
"""
|
||||
if 'title' in kwargs:
|
||||
title = kwargs['title']
|
||||
else:
|
||||
title = self.title_entry.get_value()
|
||||
if title == '':
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Title entry is empty."))
|
||||
return 'fail'
|
||||
|
||||
if 'link' in kwargs:
|
||||
link = kwargs['link']
|
||||
else:
|
||||
link = self.link_entry.get_value()
|
||||
|
||||
if link == 'http://':
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Web link entry is empty."))
|
||||
return 'fail'
|
||||
|
||||
# if 'http' not in link or 'https' not in link:
|
||||
# link = 'http://' + link
|
||||
|
||||
for bookmark in self.bm_dict.values():
|
||||
if title == bookmark[0] or link == bookmark[1]:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Either the Title or the Weblink already in the table."))
|
||||
return 'fail'
|
||||
|
||||
# for some reason if the last char in the weblink is a slash it does not make the link clickable
|
||||
# so I remove it
|
||||
if link[-1] == '/':
|
||||
link = link[:-1]
|
||||
# add the new entry to storage
|
||||
new_entry = len(self.bm_dict) + 1
|
||||
self.bm_dict[str(new_entry)] = [title, link]
|
||||
|
||||
# add the link to the menu but only if it is within the set limit
|
||||
bm_limit = int(self.app.defaults["global_bookmarks_limit"])
|
||||
if len(self.bm_dict) < bm_limit:
|
||||
act = QtWidgets.QAction(parent=self.app.ui.menuhelp_bookmarks)
|
||||
act.setText(title)
|
||||
act.setIcon(QtGui.QIcon(self.app.resource_location + '/link16.png'))
|
||||
act.triggered.connect(lambda: webbrowser.open(link))
|
||||
self.app.ui.menuhelp_bookmarks.insertAction(self.app.ui.menuhelp_bookmarks_manager, act)
|
||||
|
||||
self.app.inform.emit('[success] %s' % _("Bookmark added."))
|
||||
|
||||
# add the new entry to the bookmark manager table
|
||||
self.build_bm_ui()
|
||||
|
||||
def on_remove_entry(self):
|
||||
"""
|
||||
Remove an Entry in the Bookmark table and from the menu actions
|
||||
:return:
|
||||
"""
|
||||
index_list = []
|
||||
for model_index in self.table_widget.selectionModel().selectedRows():
|
||||
index = QtCore.QPersistentModelIndex(model_index)
|
||||
index_list.append(index)
|
||||
title_to_remove = self.table_widget.item(model_index.row(), 1).text()
|
||||
|
||||
if title_to_remove == 'FlatCAM' or title_to_remove == 'Backup Site':
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s.' % _("This bookmark can not be removed"))
|
||||
self.build_bm_ui()
|
||||
return
|
||||
else:
|
||||
for k, bookmark in list(self.bm_dict.items()):
|
||||
if title_to_remove == bookmark[0]:
|
||||
# remove from the storage
|
||||
self.bm_dict.pop(k, None)
|
||||
|
||||
for act in self.app.ui.menuhelp_bookmarks.actions():
|
||||
if act.text() == title_to_remove:
|
||||
# disconnect the signal
|
||||
try:
|
||||
act.triggered.disconnect()
|
||||
except TypeError:
|
||||
pass
|
||||
# remove the action from the menu
|
||||
self.app.ui.menuhelp_bookmarks.removeAction(act)
|
||||
|
||||
# house keeping: it pays to have keys increased by one
|
||||
new_key = 0
|
||||
new_dict = {}
|
||||
for k, v in self.bm_dict.items():
|
||||
# we start with key 1 so we can use the len(self.bm_dict)
|
||||
# when adding bookmarks (keys in bm_dict)
|
||||
new_key += 1
|
||||
new_dict[str(new_key)] = v
|
||||
|
||||
self.bm_dict = deepcopy(new_dict)
|
||||
new_dict.clear()
|
||||
|
||||
self.app.inform.emit('[success] %s' % _("Bookmark removed."))
|
||||
|
||||
# for index in index_list:
|
||||
# self.table_widget.model().removeRow(index.row())
|
||||
self.build_bm_ui()
|
||||
|
||||
def on_export_bookmarks(self):
|
||||
self.app.report_usage("on_export_bookmarks")
|
||||
self.app.log.debug("on_export_bookmarks()")
|
||||
|
||||
date = str(datetime.today()).rpartition('.')[0]
|
||||
date = ''.join(c for c in date if c not in ':-')
|
||||
date = date.replace(' ', '_')
|
||||
|
||||
filter__ = "Text File (*.TXT);;All Files (*.*)"
|
||||
filename, _f = FCFileSaveDialog.get_saved_filename( caption=_("Export FlatCAM Bookmarks"),
|
||||
directory='{l_save}/FlatCAM_{n}_{date}'.format(
|
||||
l_save=str(self.app.get_last_save_folder()),
|
||||
n=_("Bookmarks"),
|
||||
date=date),
|
||||
filter=filter__)
|
||||
|
||||
filename = str(filename)
|
||||
|
||||
if filename == "":
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
|
||||
return
|
||||
else:
|
||||
try:
|
||||
f = open(filename, 'w')
|
||||
f.close()
|
||||
except PermissionError:
|
||||
self.app.inform.emit('[WARNING] %s' %
|
||||
_("Permission denied, saving not possible.\n"
|
||||
"Most likely another app is holding the file open and not accessible."))
|
||||
return
|
||||
except IOError:
|
||||
self.app.log.debug('Creating a new bookmarks file ...')
|
||||
f = open(filename, 'w')
|
||||
f.close()
|
||||
except Exception:
|
||||
e = sys.exc_info()[0]
|
||||
self.app.log.error("Could not load defaults file.")
|
||||
self.app.log.error(str(e))
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Could not load bookmarks file."))
|
||||
return
|
||||
|
||||
# Save Bookmarks to a file
|
||||
try:
|
||||
with open(filename, "w") as f:
|
||||
for title, link in self.bm_dict.items():
|
||||
line2write = str(title) + ':' + str(link) + '\n'
|
||||
f.write(line2write)
|
||||
except Exception:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write bookmarks to file."))
|
||||
return
|
||||
self.app.inform.emit('[success] %s: %s' % (_("Exported bookmarks to"), filename))
|
||||
|
||||
def on_import_bookmarks(self):
|
||||
self.app.log.debug("on_import_bookmarks()")
|
||||
|
||||
filter_ = "Text File (*.txt);;All Files (*.*)"
|
||||
filename, _f = QtWidgets.QFileDialog.getOpenFileName(caption=_("Import FlatCAM Bookmarks"), filter=filter_)
|
||||
|
||||
filename = str(filename)
|
||||
|
||||
if filename == "":
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
|
||||
else:
|
||||
try:
|
||||
with open(filename) as f:
|
||||
bookmarks = f.readlines()
|
||||
except IOError:
|
||||
self.app.log.error("Could not load bookmarks file.")
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Could not load bookmarks file."))
|
||||
return
|
||||
|
||||
for line in bookmarks:
|
||||
proc_line = line.replace(' ', '').partition(':')
|
||||
self.on_add_entry(title=proc_line[0], link=proc_line[2])
|
||||
|
||||
self.app.inform.emit('[success] %s: %s' % (_("Imported Bookmarks from"), filename))
|
||||
|
||||
def mark_table_rows_for_actions(self):
|
||||
for row in range(self.table_widget.rowCount()):
|
||||
item_to_paint = self.table_widget.item(row, 0)
|
||||
if row < self.app.defaults["global_bookmarks_limit"]:
|
||||
item_to_paint.setBackground(QtGui.QColor('gray'))
|
||||
# item_to_paint.setForeground(QtGui.QColor('black'))
|
||||
else:
|
||||
item_to_paint.setBackground(QtGui.QColor('white'))
|
||||
# item_to_paint.setForeground(QtGui.QColor('black'))
|
||||
|
||||
def rebuild_actions(self):
|
||||
# rebuild the storage to reflect the order of the lines
|
||||
self.bm_dict.clear()
|
||||
for row in range(self.table_widget.rowCount()):
|
||||
title = self.table_widget.item(row, 1).text()
|
||||
wlink = self.table_widget.cellWidget(row, 2).toPlainText()
|
||||
|
||||
entry = int(row) + 1
|
||||
self.bm_dict.update(
|
||||
{
|
||||
str(entry): [title, wlink]
|
||||
}
|
||||
)
|
||||
|
||||
self.app.install_bookmarks(book_dict=self.bm_dict)
|
||||
|
||||
# def accept(self):
|
||||
# self.rebuild_actions()
|
||||
# super().accept()
|
||||
|
||||
def closeEvent(self, QCloseEvent):
|
||||
self.rebuild_actions()
|
||||
super().closeEvent(QCloseEvent)
|
2766
FlatCAMCommon.py
2766
FlatCAMCommon.py
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
8244
FlatCAMObj.py
8244
FlatCAMObj.py
File diff suppressed because it is too large
Load Diff
|
@ -12,8 +12,10 @@ from abc import ABCMeta, abstractmethod
|
|||
import math
|
||||
|
||||
# module-root dictionary of preprocessors
|
||||
import FlatCAMApp
|
||||
|
||||
import logging
|
||||
|
||||
log = logging.getLogger('base')
|
||||
preprocessors = {}
|
||||
|
||||
|
||||
|
@ -23,7 +25,7 @@ class ABCPostProcRegister(ABCMeta):
|
|||
newclass = super(ABCPostProcRegister, cls).__new__(cls, clsname, bases, attrs)
|
||||
if object not in bases:
|
||||
if newclass.__name__ in preprocessors:
|
||||
FlatCAMApp.App.log.warning('Preprocessor %s has been overriden' % newclass.__name__)
|
||||
log.warning('Preprocessor %s has been overriden' % newclass.__name__)
|
||||
preprocessors[newclass.__name__] = newclass() # here is your register function
|
||||
return newclass
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ languages_dict = {
|
|||
'en': 'English',
|
||||
'es': 'Spanish',
|
||||
'fr': 'French',
|
||||
'hu': 'Hungarian',
|
||||
'it': 'Italian',
|
||||
'ro': 'Romanian',
|
||||
'ru': 'Russian',
|
||||
|
|
|
@ -16,10 +16,15 @@ from PyQt5.QtCore import Qt, QSettings
|
|||
from PyQt5.QtGui import QColor
|
||||
# from PyQt5.QtCore import QModelIndex
|
||||
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry, FlatCAMExcellon, FlatCAMCNCjob, FlatCAMDocument, FlatCAMScript, \
|
||||
FlatCAMObj
|
||||
from flatcamObjects.FlatCAMObj import FlatCAMObj
|
||||
from flatcamObjects.FlatCAMCNCJob import CNCJobObject
|
||||
from flatcamObjects.FlatCAMDocument import DocumentObject
|
||||
from flatcamObjects.FlatCAMExcellon import ExcellonObject
|
||||
from flatcamObjects.FlatCAMGeometry import GeometryObject
|
||||
from flatcamObjects.FlatCAMGerber import GerberObject
|
||||
from flatcamObjects.FlatCAMScript import ScriptObject
|
||||
|
||||
import inspect # TODO: Remove
|
||||
import FlatCAMApp
|
||||
|
||||
import re
|
||||
import logging
|
||||
|
@ -234,12 +239,12 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
]
|
||||
|
||||
classdict = {
|
||||
"gerber": FlatCAMGerber,
|
||||
"excellon": FlatCAMExcellon,
|
||||
"cncjob": FlatCAMCNCjob,
|
||||
"geometry": FlatCAMGeometry,
|
||||
"script": FlatCAMScript,
|
||||
"document": FlatCAMDocument
|
||||
"gerber": GerberObject,
|
||||
"excellon": ExcellonObject,
|
||||
"cncjob": CNCJobObject,
|
||||
"geometry": GeometryObject,
|
||||
"script": ScriptObject,
|
||||
"document": DocumentObject
|
||||
}
|
||||
|
||||
icon_files = {
|
||||
|
@ -332,7 +337,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
self.update_list_signal.connect(self.on_update_list_signal)
|
||||
|
||||
def promise(self, obj_name):
|
||||
FlatCAMApp.App.log.debug("Object %s has been promised." % obj_name)
|
||||
log.debug("Object %s has been promised." % obj_name)
|
||||
self.promises.add(obj_name)
|
||||
|
||||
def has_promises(self):
|
||||
|
@ -349,7 +354,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
return len(self.plot_promises) > 0
|
||||
|
||||
def on_mouse_down(self, event):
|
||||
FlatCAMApp.App.log.debug("Mouse button pressed on list")
|
||||
log.debug("Mouse button pressed on list")
|
||||
|
||||
def on_menu_request(self, pos):
|
||||
|
||||
|
@ -373,17 +378,17 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
self.app.ui.menuprojectcolor.setEnabled(False)
|
||||
|
||||
for obj in self.get_selected():
|
||||
if type(obj) == FlatCAMGerber or type(obj) == FlatCAMExcellon:
|
||||
if type(obj) == GerberObject or type(obj) == ExcellonObject:
|
||||
self.app.ui.menuprojectcolor.setEnabled(True)
|
||||
|
||||
if type(obj) != FlatCAMGeometry:
|
||||
if type(obj) != GeometryObject:
|
||||
self.app.ui.menuprojectgeneratecnc.setVisible(False)
|
||||
if type(obj) != FlatCAMGeometry and type(obj) != FlatCAMExcellon and type(obj) != FlatCAMGerber:
|
||||
if type(obj) != GeometryObject and type(obj) != ExcellonObject and type(obj) != GerberObject:
|
||||
self.app.ui.menuprojectedit.setVisible(False)
|
||||
if type(obj) != FlatCAMGerber and type(obj) != FlatCAMExcellon and type(obj) != FlatCAMCNCjob:
|
||||
if type(obj) != GerberObject and type(obj) != ExcellonObject and type(obj) != CNCJobObject:
|
||||
self.app.ui.menuprojectviewsource.setVisible(False)
|
||||
if type(obj) != FlatCAMGerber and type(obj) != FlatCAMGeometry and type(obj) != FlatCAMExcellon and \
|
||||
type(obj) != FlatCAMCNCjob:
|
||||
if type(obj) != GerberObject and type(obj) != GeometryObject and type(obj) != ExcellonObject and \
|
||||
type(obj) != CNCJobObject:
|
||||
# meaning for Scripts and for Document type of FlatCAM object
|
||||
self.app.ui.menuprojectenable.setVisible(False)
|
||||
self.app.ui.menuprojectdisable.setVisible(False)
|
||||
|
@ -532,21 +537,21 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
# return QtWidgets.QAbstractItemModel.flags(self, index)
|
||||
|
||||
def append(self, obj, active=False, to_index=None):
|
||||
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + " --> OC.append()")
|
||||
log.debug(str(inspect.stack()[1][3]) + " --> OC.append()")
|
||||
|
||||
name = obj.options["name"]
|
||||
|
||||
# Check promises and clear if exists
|
||||
if name in self.promises:
|
||||
self.promises.remove(name)
|
||||
# FlatCAMApp.App.log.debug("Promised object %s became available." % name)
|
||||
# FlatCAMApp.App.log.debug("%d promised objects remaining." % len(self.promises))
|
||||
# log.debug("Promised object %s became available." % name)
|
||||
# log.debug("%d promised objects remaining." % len(self.promises))
|
||||
|
||||
# Prevent same name
|
||||
while name in self.get_names():
|
||||
# ## Create a new name
|
||||
# Ends with number?
|
||||
FlatCAMApp.App.log.debug("new_object(): Object name (%s) exists, changing." % name)
|
||||
log.debug("new_object(): Object name (%s) exists, changing." % name)
|
||||
match = re.search(r'(.*[^\d])?(\d+)$', name)
|
||||
if match: # Yes: Increment the number!
|
||||
base = match.group(1) or ''
|
||||
|
@ -596,7 +601,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
:rtype: list
|
||||
"""
|
||||
|
||||
# FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + " --> OC.get_names()")
|
||||
# log.debug(str(inspect.stack()[1][3]) + " --> OC.get_names()")
|
||||
return [x.options['name'] for x in self.get_list()]
|
||||
|
||||
def get_bounds(self):
|
||||
|
@ -606,7 +611,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
:return: [xmin, ymin, xmax, ymax]
|
||||
:rtype: list
|
||||
"""
|
||||
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_bounds()")
|
||||
log.debug(str(inspect.stack()[1][3]) + "--> OC.get_bounds()")
|
||||
|
||||
# TODO: Move the operation out of here.
|
||||
|
||||
|
@ -624,7 +629,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
xmax = max([xmax, gxmax])
|
||||
ymax = max([ymax, gymax])
|
||||
except Exception as e:
|
||||
FlatCAMApp.App.log.warning("DEV WARNING: Tried to get bounds of empty geometry. %s" % str(e))
|
||||
log.warning("DEV WARNING: Tried to get bounds of empty geometry. %s" % str(e))
|
||||
|
||||
return [xmin, ymin, xmax, ymax]
|
||||
|
||||
|
@ -638,7 +643,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
:return: The requested object or None if no such object.
|
||||
:rtype: FlatCAMObj or None
|
||||
"""
|
||||
# FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_by_name()")
|
||||
# log.debug(str(inspect.stack()[1][3]) + "--> OC.get_by_name()")
|
||||
|
||||
if isCaseSensitive is None or isCaseSensitive is True:
|
||||
for obj in self.get_list():
|
||||
|
@ -760,7 +765,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
self.app.all_objects_list = self.get_list()
|
||||
|
||||
def delete_all(self):
|
||||
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.delete_all()")
|
||||
log.debug(str(inspect.stack()[1][3]) + "--> OC.delete_all()")
|
||||
|
||||
self.app.object_status_changed.emit(None, 'delete_all', '')
|
||||
|
||||
|
@ -897,8 +902,15 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
self.set_inactive(name)
|
||||
|
||||
def on_list_selection_change(self, current, previous):
|
||||
# FlatCAMApp.App.log.debug("on_list_selection_change()")
|
||||
# FlatCAMApp.App.log.debug("Current: %s, Previous %s" % (str(current), str(previous)))
|
||||
"""
|
||||
|
||||
:param current: Current selected item
|
||||
:param previous: Previously selected item
|
||||
:return:
|
||||
"""
|
||||
|
||||
# log.debug("on_list_selection_change()")
|
||||
# log.debug("Current: %s, Previous %s" % (str(current), str(previous)))
|
||||
|
||||
try:
|
||||
obj = current.indexes()[0].internalPointer().obj
|
||||
|
@ -942,12 +954,12 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
)
|
||||
except IndexError:
|
||||
self.item_selected.emit('none')
|
||||
# FlatCAMApp.App.log.debug("on_list_selection_change(): Index Error (Nothing selected?)")
|
||||
# log.debug("on_list_selection_change(): Index Error (Nothing selected?)")
|
||||
self.app.inform.emit('')
|
||||
try:
|
||||
self.app.ui.selected_scroll_area.takeWidget()
|
||||
except Exception as e:
|
||||
FlatCAMApp.App.log.debug("Nothing to remove. %s" % str(e))
|
||||
log.debug("Nothing to remove. %s" % str(e))
|
||||
|
||||
self.app.setup_component_editor()
|
||||
return
|
||||
|
|
|
@ -12,7 +12,6 @@ from camlib import distance, arc, FlatCAMRTreeStorage
|
|||
from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, RadioSet, FCSpinner
|
||||
from flatcamEditors.FlatCAMGeoEditor import FCShapeTool, DrawTool, DrawToolShape, DrawToolUtilityShape, FlatCAMGeoEditor
|
||||
from flatcamParsers.ParseExcellon import Excellon
|
||||
import FlatCAMApp
|
||||
|
||||
from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon, Point
|
||||
import shapely.affinity as affinity
|
||||
|
@ -179,7 +178,7 @@ class FCDrillArray(FCShapeTool):
|
|||
|
||||
try:
|
||||
QtGui.QGuiApplication.restoreOverrideCursor()
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.cursor = QtGui.QCursor(QtGui.QPixmap(self.draw_app.app.resource_location + '/aero_drill_array.png'))
|
||||
|
@ -1516,7 +1515,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
draw_shape_idx = -1
|
||||
|
||||
def __init__(self, app):
|
||||
assert isinstance(app, FlatCAMApp.App), "Expected the app to be a FlatCAMApp.App, got %s" % type(app)
|
||||
# assert isinstance(app, FlatCAMApp.App), "Expected the app to be a FlatCAMApp.App, got %s" % type(app)
|
||||
|
||||
super(FlatCAMExcEditor, self).__init__()
|
||||
|
||||
|
@ -2230,8 +2229,8 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
# store the status of the editor so the Delete at object level will not work until the edit is finished
|
||||
self.editor_active = False
|
||||
|
||||
def entry2option(option, entry):
|
||||
self.options[option] = float(entry.text())
|
||||
# def entry2option(option, entry):
|
||||
# self.options[option] = float(entry.text())
|
||||
|
||||
# Event signals disconnect id holders
|
||||
self.mp = None
|
||||
|
@ -2388,7 +2387,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
|
||||
try:
|
||||
# Find no of slots for the current tool
|
||||
for slot in self.slots:
|
||||
for slot in self.slot_points_edit:
|
||||
if slot['tool'] == tool_no:
|
||||
slot_cnt += 1
|
||||
|
||||
|
@ -2661,15 +2660,13 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
# self.tools_table_exc.selectionModel().currentChanged.disconnect()
|
||||
|
||||
self.is_modified = True
|
||||
new_dia = None
|
||||
# new_dia = None
|
||||
|
||||
if self.tools_table_exc.currentItem() is not None:
|
||||
try:
|
||||
new_dia = float(self.tools_table_exc.currentItem().text())
|
||||
except ValueError as e:
|
||||
log.debug("FlatCAMExcEditor.on_tool_edit() --> %s" % str(e))
|
||||
self.tools_table_exc.setCurrentItem(None)
|
||||
return
|
||||
try:
|
||||
new_dia = float(self.tools_table_exc.currentItem().text())
|
||||
except ValueError as e:
|
||||
log.debug("FlatCAMExcEditor.on_tool_edit() --> %s" % str(e))
|
||||
return
|
||||
|
||||
row_of_item_changed = self.tools_table_exc.currentRow()
|
||||
# rows start with 0, tools start with 1 so we adjust the value by 1
|
||||
|
@ -3042,7 +3039,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
Imports the geometry from the given FlatCAM Excellon object
|
||||
into the editor.
|
||||
|
||||
:param exc_obj: FlatCAMExcellon object
|
||||
:param exc_obj: ExcellonObject object
|
||||
:return: None
|
||||
"""
|
||||
|
||||
|
@ -3118,7 +3115,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
"""
|
||||
Create a new Excellon object that contain the edited content of the source Excellon object
|
||||
|
||||
:param exc_obj: FlatCAMExcellon
|
||||
:param exc_obj: ExcellonObject
|
||||
:return: None
|
||||
"""
|
||||
|
||||
|
@ -3297,7 +3294,8 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
|
||||
return self.edited_obj_name
|
||||
|
||||
def update_options(self, obj):
|
||||
@staticmethod
|
||||
def update_options(obj):
|
||||
try:
|
||||
if not obj.options:
|
||||
obj.options = {}
|
||||
|
@ -3316,10 +3314,14 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
"""
|
||||
Creates a new Excellon object for the edited Excellon. Thread-safe.
|
||||
|
||||
:param outname: Name of the resulting object. None causes the
|
||||
name to be that of the file.
|
||||
:type outname: str
|
||||
:return: None
|
||||
:param outname: Name of the resulting object. None causes the
|
||||
name to be that of the file.
|
||||
:type outname: str
|
||||
|
||||
:param n_drills: The new Drills storage
|
||||
:param n_slots: The new Slots storage
|
||||
:param n_tools: The new Tools storage
|
||||
:return: None
|
||||
"""
|
||||
|
||||
self.app.log.debug("Update the Excellon object with edited content. Source is %s" %
|
||||
|
@ -3429,12 +3431,12 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
|
||||
self.replot()
|
||||
|
||||
def toolbar_tool_toggle(self, key):
|
||||
self.options[key] = self.sender().isChecked()
|
||||
if self.options[key] is True:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
# def toolbar_tool_toggle(self, key):
|
||||
# self.options[key] = self.sender().isChecked()
|
||||
# if self.options[key] is True:
|
||||
# return 1
|
||||
# else:
|
||||
# return 0
|
||||
|
||||
def on_canvas_click(self, event):
|
||||
"""
|
||||
|
@ -3446,12 +3448,12 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
"""
|
||||
if self.app.is_legacy is False:
|
||||
event_pos = event.pos
|
||||
event_is_dragging = event.is_dragging
|
||||
right_button = 2
|
||||
# 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_is_dragging = self.app.plotcanvas.is_dragging
|
||||
# right_button = 3
|
||||
|
||||
self.pos = self.canvas.translate_coords(event_pos)
|
||||
|
||||
|
@ -3575,8 +3577,8 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
|
||||
if isinstance(shape, DrawToolUtilityShape):
|
||||
self.utility.append(shape)
|
||||
else:
|
||||
self.storage.insert(shape) # TODO: Check performance
|
||||
# else:
|
||||
# self.storage.insert(shape)
|
||||
|
||||
def on_exc_click_release(self, event):
|
||||
"""
|
||||
|
@ -3591,11 +3593,11 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
|
||||
if self.app.is_legacy is False:
|
||||
event_pos = event.pos
|
||||
event_is_dragging = event.is_dragging
|
||||
# event_is_dragging = event.is_dragging
|
||||
right_button = 2
|
||||
else:
|
||||
event_pos = (event.xdata, event.ydata)
|
||||
event_is_dragging = self.app.plotcanvas.is_dragging
|
||||
# event_is_dragging = self.app.plotcanvas.is_dragging
|
||||
right_button = 3
|
||||
|
||||
pos_canvas = self.canvas.translate_coords(event_pos)
|
||||
|
@ -4027,7 +4029,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
del self.slot_points_edit[storage][0]
|
||||
|
||||
if del_shape in self.selected:
|
||||
self.selected.remove(del_shape) # TODO: Check performance
|
||||
self.selected.remove(del_shape)
|
||||
|
||||
def delete_utility_geometry(self):
|
||||
for_deletion = [util_shape for util_shape in self.utility]
|
||||
|
|
|
@ -20,7 +20,6 @@ from flatcamGUI.ObjectUI import RadioSet
|
|||
from flatcamGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \
|
||||
FCTable, FCDoubleSpinner, FCButton, EvalEntry2, FCInputDialog, FCTree
|
||||
from flatcamParsers.ParseFont import *
|
||||
import FlatCAMApp
|
||||
|
||||
from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon
|
||||
from shapely.ops import cascaded_union, unary_union, linemerge
|
||||
|
@ -88,8 +87,8 @@ class BufferSelectionTool(FlatCAMTool):
|
|||
self.buffer_corner_lbl.setToolTip(
|
||||
_("There are 3 types of corners:\n"
|
||||
" - 'Round': the corner is rounded for exterior buffer.\n"
|
||||
" - 'Square:' the corner is met in a sharp angle for exterior buffer.\n"
|
||||
" - 'Beveled:' the corner is a line that directly connects the features meeting in the corner")
|
||||
" - 'Square': the corner is met in a sharp angle for exterior buffer.\n"
|
||||
" - 'Beveled': the corner is a line that directly connects the features meeting in the corner")
|
||||
)
|
||||
self.buffer_corner_cb = FCComboBox()
|
||||
self.buffer_corner_cb.addItem(_("Round"))
|
||||
|
@ -3299,8 +3298,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
draw_shape_idx = -1
|
||||
|
||||
def __init__(self, app, disabled=False):
|
||||
assert isinstance(app, FlatCAMApp.App), \
|
||||
"Expected the app to be a FlatCAMApp.App, got %s" % type(app)
|
||||
# assert isinstance(app, FlatCAMApp.App), \
|
||||
# "Expected the app to be a FlatCAMApp.App, got %s" % type(app)
|
||||
|
||||
super(FlatCAMGeoEditor, self).__init__()
|
||||
|
||||
|
@ -4011,6 +4010,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
:return: Boolean. Status of the checkbox that toggled the Editor Tool
|
||||
"""
|
||||
cb_widget = self.sender()
|
||||
assert isinstance(cb_widget, QtWidgets.QAction), "Expected a QAction got %s" % type(cb_widget)
|
||||
self.options[key] = cb_widget.isChecked()
|
||||
|
||||
return 1 if self.options[key] is True else 0
|
||||
|
@ -4035,7 +4035,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
Imports the geometry from the given FlatCAM Geometry object
|
||||
into the editor.
|
||||
|
||||
:param fcgeometry: FlatCAMGeometry
|
||||
:param fcgeometry: GeometryObject
|
||||
:param multigeo_tool: A tool for the case of the edited geometry being of type 'multigeo'
|
||||
:return: None
|
||||
"""
|
||||
|
@ -4750,7 +4750,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
Transfers the geometry tool shape buffer to the selected geometry
|
||||
object. The geometry already in the object are removed.
|
||||
|
||||
:param fcgeometry: FlatCAMGeometry
|
||||
:param fcgeometry: GeometryObject
|
||||
:return: None
|
||||
"""
|
||||
if self.multigeo_tool:
|
||||
|
|
|
@ -21,7 +21,6 @@ from camlib import distance, arc, three_point_circle
|
|||
from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, FCSpinner, RadioSet, \
|
||||
EvalEntry2, FCInputDialog, FCButton, OptionalInputSection, FCCheckBox
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
import FlatCAMApp
|
||||
|
||||
import numpy as np
|
||||
from numpy.linalg import norm as numpy_norm
|
||||
|
@ -182,6 +181,7 @@ class FCShapeTool(DrawTool):
|
|||
|
||||
def __init__(self, draw_app):
|
||||
DrawTool.__init__(self, draw_app)
|
||||
self.name = None
|
||||
|
||||
def make(self):
|
||||
pass
|
||||
|
@ -199,7 +199,7 @@ class FCPad(FCShapeTool):
|
|||
|
||||
try:
|
||||
QtGui.QGuiApplication.restoreOverrideCursor()
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
self.cursor = QtGui.QCursor(QtGui.QPixmap(self.draw_app.app.resource_location + '/aero_circle.png'))
|
||||
QtGui.QGuiApplication.setOverrideCursor(self.cursor)
|
||||
|
@ -1415,7 +1415,7 @@ class FCDisc(FCShapeTool):
|
|||
|
||||
try:
|
||||
QtGui.QGuiApplication.restoreOverrideCursor()
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
self.cursor = QtGui.QCursor(QtGui.QPixmap(self.draw_app.app.resource_location + '/aero_disc.png'))
|
||||
QtGui.QGuiApplication.setOverrideCursor(self.cursor)
|
||||
|
@ -2422,8 +2422,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
mp_finished = QtCore.pyqtSignal(list)
|
||||
|
||||
def __init__(self, app):
|
||||
assert isinstance(app, FlatCAMApp.App), \
|
||||
"Expected the app to be a FlatCAMApp.App, got %s" % type(app)
|
||||
# assert isinstance(app, FlatCAMApp.App), \
|
||||
# "Expected the app to be a FlatCAMApp.App, got %s" % type(app)
|
||||
|
||||
super(FlatCAMGrbEditor, self).__init__()
|
||||
|
||||
|
@ -2621,8 +2621,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.buffer_corner_lbl.setToolTip(
|
||||
_("There are 3 types of corners:\n"
|
||||
" - 'Round': the corner is rounded.\n"
|
||||
" - 'Square:' the corner is met in a sharp angle.\n"
|
||||
" - 'Beveled:' the corner is a line that directly connects the features meeting in the corner")
|
||||
" - 'Square': the corner is met in a sharp angle.\n"
|
||||
" - 'Beveled': the corner is a line that directly connects the features meeting in the corner")
|
||||
)
|
||||
self.buffer_corner_cb = FCComboBox()
|
||||
self.buffer_corner_cb.addItem(_("Round"))
|
||||
|
@ -3479,7 +3479,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
current_table_dia_edited = float(self.apertures_table.currentItem().text())
|
||||
except ValueError as e:
|
||||
log.debug("FlatCAMExcEditor.on_tool_edit() --> %s" % str(e))
|
||||
self.apertures_table.setCurrentItem(None)
|
||||
# self.apertures_table.setCurrentItem(None)
|
||||
return
|
||||
|
||||
row_of_item_changed = self.apertures_table.currentRow()
|
||||
|
@ -3833,7 +3833,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
Imports the geometry found in self.apertures from the given FlatCAM Gerber object
|
||||
into the editor.
|
||||
|
||||
:param orig_grb_obj: FlatCAMExcellon
|
||||
:param orig_grb_obj: ExcellonObject
|
||||
:return: None
|
||||
"""
|
||||
|
||||
|
@ -3956,10 +3956,10 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
global_clear_geo = []
|
||||
|
||||
# create one big geometry made out of all 'negative' (clear) polygons
|
||||
for apid in app_obj.gerber_obj.apertures:
|
||||
for aper_id in app_obj.gerber_obj.apertures:
|
||||
# first check if we have any clear_geometry (LPC) and if yes added it to the global_clear_geo
|
||||
if 'geometry' in app_obj.gerber_obj.apertures[apid]:
|
||||
for elem in app_obj.gerber_obj.apertures[apid]['geometry']:
|
||||
if 'geometry' in app_obj.gerber_obj.apertures[aper_id]:
|
||||
for elem in app_obj.gerber_obj.apertures[aper_id]['geometry']:
|
||||
if 'clear' in elem:
|
||||
global_clear_geo.append(elem['clear'])
|
||||
log.warning("Found %d clear polygons." % len(global_clear_geo))
|
||||
|
@ -3967,7 +3967,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
if global_clear_geo:
|
||||
global_clear_geo = MultiPolygon(global_clear_geo)
|
||||
if isinstance(global_clear_geo, Polygon):
|
||||
global_clear_geo = list(global_clear_geo)
|
||||
global_clear_geo = [global_clear_geo]
|
||||
|
||||
# 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
|
||||
|
@ -3979,8 +3979,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
# solid_geo = elem['solid']
|
||||
# for clear_geo in global_clear_geo:
|
||||
# # Make sure that the clear_geo is within the solid_geo otherwise we loose
|
||||
# # the solid_geometry. We want for clear_geometry just to cut into solid_geometry not to
|
||||
# # delete it
|
||||
# # the solid_geometry. We want for clear_geometry just to cut
|
||||
# # into solid_geometry not to delete it
|
||||
# if clear_geo.within(solid_geo):
|
||||
# solid_geo = solid_geo.difference(clear_geo)
|
||||
# try:
|
||||
|
@ -4307,14 +4307,14 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
|
||||
self.plot_all()
|
||||
|
||||
def toolbar_tool_toggle(self, key):
|
||||
"""
|
||||
|
||||
:param key: key to update in self.options dictionary
|
||||
:return:
|
||||
"""
|
||||
self.options[key] = self.sender().isChecked()
|
||||
return self.options[key]
|
||||
# def toolbar_tool_toggle(self, key):
|
||||
# """
|
||||
#
|
||||
# :param key: key to update in self.options dictionary
|
||||
# :return:
|
||||
# """
|
||||
# self.options[key] = self.sender().isChecked()
|
||||
# return self.options[key]
|
||||
|
||||
def on_grb_shape_complete(self, storage=None, specific_shape=None, no_plot=False):
|
||||
"""
|
||||
|
@ -4389,12 +4389,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
"""
|
||||
if self.app.is_legacy is False:
|
||||
event_pos = event.pos
|
||||
event_is_dragging = event.is_dragging
|
||||
right_button = 2
|
||||
# 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_is_dragging = self.app.plotcanvas.is_dragging
|
||||
# right_button = 3
|
||||
|
||||
self.pos = self.canvas.translate_coords(event_pos)
|
||||
|
||||
|
@ -4457,11 +4457,11 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.modifiers = QtWidgets.QApplication.keyboardModifiers()
|
||||
if self.app.is_legacy is False:
|
||||
event_pos = event.pos
|
||||
event_is_dragging = event.is_dragging
|
||||
# event_is_dragging = event.is_dragging
|
||||
right_button = 2
|
||||
else:
|
||||
event_pos = (event.xdata, event.ydata)
|
||||
event_is_dragging = self.app.plotcanvas.is_dragging
|
||||
# event_is_dragging = self.app.plotcanvas.is_dragging
|
||||
right_button = 3
|
||||
|
||||
pos_canvas = self.canvas.translate_coords(event_pos)
|
||||
|
@ -4747,10 +4747,10 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
Plots a geometric object or list of objects without rendering. Plotted objects
|
||||
are returned as a list. This allows for efficient/animated rendering.
|
||||
|
||||
:param geometry: Geometry to be plotted (Any Shapely.geom kind or list of such)
|
||||
:param color: Shape color
|
||||
:param linewidth: Width of lines in # of pixels.
|
||||
:return: List of plotted elements.
|
||||
:param geometry: Geometry to be plotted (Any Shapely.geom kind or list of such)
|
||||
:param color: Shape color
|
||||
:param linewidth: Width of lines in # of pixels.
|
||||
:return: List of plotted elements.
|
||||
"""
|
||||
|
||||
if geometry is None:
|
||||
|
@ -5597,7 +5597,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
self.flip_ref_entry.set_value((0, 0))
|
||||
|
||||
def template(self):
|
||||
if not self.fcdraw.selected:
|
||||
if not self.draw_app.selected:
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled. No shape selected."))
|
||||
return
|
||||
|
||||
|
|
|
@ -2876,7 +2876,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
|
||||
# Open Excellon file
|
||||
if key == QtCore.Qt.Key_E:
|
||||
self.app.on_fileopenexcellon()
|
||||
self.app.on_fileopenexcellon(signal=None)
|
||||
|
||||
# Open Gerber file
|
||||
if key == QtCore.Qt.Key_G:
|
||||
|
@ -2884,7 +2884,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
if 'editor' in widget_name.lower():
|
||||
self.app.goto_text_line()
|
||||
else:
|
||||
self.app.on_fileopengerber()
|
||||
self.app.on_fileopengerber(signal=None)
|
||||
|
||||
# Distance Tool
|
||||
if key == QtCore.Qt.Key_M:
|
||||
|
|
|
@ -1241,6 +1241,7 @@ class ExcellonObjectUI(ObjectUI):
|
|||
self.pdepth_entry.set_precision(self.decimals)
|
||||
self.pdepth_entry.set_range(-9999.9999, 9999.9999)
|
||||
self.pdepth_entry.setSingleStep(0.1)
|
||||
self.pdepth_entry.setObjectName("e_depth_probe")
|
||||
|
||||
self.grid5.addWidget(self.pdepth_label, 13, 0)
|
||||
self.grid5.addWidget(self.pdepth_entry, 13, 1)
|
||||
|
@ -1258,7 +1259,7 @@ class ExcellonObjectUI(ObjectUI):
|
|||
self.feedrate_probe_entry.set_precision(self.decimals)
|
||||
self.feedrate_probe_entry.set_range(0.0, 9999.9999)
|
||||
self.feedrate_probe_entry.setSingleStep(0.1)
|
||||
self.feedrate_probe_entry.setObjectName(_("e_fr_probe"))
|
||||
self.feedrate_probe_entry.setObjectName("e_fr_probe")
|
||||
|
||||
self.grid5.addWidget(self.feedrate_probe_label, 14, 0)
|
||||
self.grid5.addWidget(self.feedrate_probe_entry, 14, 1)
|
||||
|
|
|
@ -16,8 +16,6 @@ from descartes.patch import PolygonPatch
|
|||
|
||||
from shapely.geometry import Polygon, LineString, LinearRing
|
||||
|
||||
import FlatCAMApp
|
||||
|
||||
from copy import deepcopy
|
||||
import logging
|
||||
|
||||
|
@ -496,7 +494,7 @@ class PlotCanvasLegacy(QtCore.QObject):
|
|||
:param event:
|
||||
:return:
|
||||
"""
|
||||
FlatCAMApp.App.log.debug('on_key_down(): ' + str(event.key))
|
||||
log.debug('on_key_down(): ' + str(event.key))
|
||||
self.key = event.key
|
||||
|
||||
def on_key_up(self, event):
|
||||
|
@ -531,7 +529,7 @@ class PlotCanvasLegacy(QtCore.QObject):
|
|||
try:
|
||||
self.figure.clf()
|
||||
except KeyError:
|
||||
FlatCAMApp.App.log.warning("KeyError in MPL figure.clf()")
|
||||
log.warning("KeyError in MPL figure.clf()")
|
||||
|
||||
# Re-build
|
||||
self.figure.add_axes(self.axes)
|
||||
|
@ -582,7 +580,7 @@ class PlotCanvasLegacy(QtCore.QObject):
|
|||
try:
|
||||
r = width / height
|
||||
except ZeroDivisionError:
|
||||
FlatCAMApp.App.log.error("Height is %f" % height)
|
||||
log.error("Height is %f" % height)
|
||||
return
|
||||
canvas_w, canvas_h = self.canvas.get_width_height()
|
||||
canvas_r = float(canvas_w) / canvas_h
|
||||
|
@ -1190,10 +1188,10 @@ class ShapeCollectionLegacy:
|
|||
linewidth=local_shapes[element]['linewidth'])
|
||||
self.axes.add_patch(patch)
|
||||
except AssertionError:
|
||||
FlatCAMApp.App.log.warning("A geometry component was not a polygon:")
|
||||
FlatCAMApp.App.log.warning(str(element))
|
||||
log.warning("A geometry component was not a polygon:")
|
||||
log.warning(str(element))
|
||||
except Exception as e:
|
||||
FlatCAMApp.App.log.debug(
|
||||
log.debug(
|
||||
"PlotCanvasLegacy.ShepeCollectionLegacy.redraw() gerber 'solid' --> %s" % str(e))
|
||||
else:
|
||||
try:
|
||||
|
|
|
@ -8420,7 +8420,7 @@ class Tools2PunchGerberPrefGroupUI(OptionsGroupUI):
|
|||
"- Excellon Object-> the Excellon object drills center will serve as reference.\n"
|
||||
"- Fixed Diameter -> will try to use the pads center as reference adding fixed diameter holes.\n"
|
||||
"- Fixed Annular Ring -> will try to keep a set annular ring.\n"
|
||||
"- Proportional -> will make a Gerber punch hole having the diameter a percentage of the pad diameter.\n")
|
||||
"- Proportional -> will make a Gerber punch hole having the diameter a percentage of the pad diameter.")
|
||||
)
|
||||
grid_lay.addWidget(self.hole_size_label, 9, 0)
|
||||
grid_lay.addWidget(self.hole_size_radio, 9, 1)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,314 @@
|
|||
# ##########################################################
|
||||
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||
# http://flatcam.org #
|
||||
# Author: Juan Pablo Caram (c) #
|
||||
# Date: 2/5/2014 #
|
||||
# MIT Licence #
|
||||
# ##########################################################
|
||||
|
||||
# ##########################################################
|
||||
# File modified by: Marius Stanciu #
|
||||
# ##########################################################
|
||||
|
||||
from flatcamEditors.FlatCAMTextEditor import TextEditor
|
||||
from flatcamObjects.FlatCAMObj import *
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class DocumentObject(FlatCAMObj):
|
||||
"""
|
||||
Represents a Document object.
|
||||
"""
|
||||
optionChanged = QtCore.pyqtSignal(str)
|
||||
ui_type = DocumentObjectUI
|
||||
|
||||
def __init__(self, name):
|
||||
self.decimals = self.app.decimals
|
||||
|
||||
log.debug("Creating a Document object...")
|
||||
FlatCAMObj.__init__(self, name)
|
||||
|
||||
self.kind = "document"
|
||||
self.units = ''
|
||||
|
||||
self.ser_attrs = ['options', 'kind', 'source_file']
|
||||
self.source_file = ''
|
||||
self.doc_code = ''
|
||||
|
||||
self.font_name = None
|
||||
self.font_italic = None
|
||||
self.font_bold = None
|
||||
self.font_underline = None
|
||||
|
||||
self.document_editor_tab = None
|
||||
|
||||
self._read_only = False
|
||||
self.units_found = self.app.defaults['units']
|
||||
|
||||
def set_ui(self, ui):
|
||||
FlatCAMObj.set_ui(self, ui)
|
||||
log.debug("DocumentObject.set_ui()")
|
||||
|
||||
assert isinstance(self.ui, DocumentObjectUI), \
|
||||
"Expected a DocumentObjectUI, got %s" % type(self.ui)
|
||||
|
||||
self.units = self.app.defaults['units'].upper()
|
||||
self.units_found = self.app.defaults['units']
|
||||
|
||||
# Fill form fields only on object create
|
||||
self.to_form()
|
||||
|
||||
# Show/Hide Advanced Options
|
||||
if self.app.defaults["global_app_level"] == 'b':
|
||||
self.ui.level.setText(_(
|
||||
'<span style="color:green;"><b>Basic</b></span>'
|
||||
))
|
||||
else:
|
||||
self.ui.level.setText(_(
|
||||
'<span style="color:red;"><b>Advanced</b></span>'
|
||||
))
|
||||
|
||||
self.document_editor_tab = TextEditor(app=self.app)
|
||||
stylesheet = """
|
||||
QTextEdit {selection-background-color:%s;
|
||||
selection-color:white;
|
||||
}
|
||||
""" % self.app.defaults["document_sel_color"]
|
||||
|
||||
self.document_editor_tab.code_editor.setStyleSheet(stylesheet)
|
||||
|
||||
# first clear previous text in text editor (if any)
|
||||
self.document_editor_tab.code_editor.clear()
|
||||
self.document_editor_tab.code_editor.setReadOnly(self._read_only)
|
||||
|
||||
self.document_editor_tab.buttonRun.hide()
|
||||
|
||||
self.ui.autocomplete_cb.set_value(self.app.defaults['document_autocompleter'])
|
||||
self.on_autocomplete_changed(state=self.app.defaults['document_autocompleter'])
|
||||
self.on_tab_size_change(val=self.app.defaults['document_tab_size'])
|
||||
|
||||
flt = "FlatCAM Docs (*.FlatDoc);;All Files (*.*)"
|
||||
|
||||
# ######################################################################
|
||||
# ######################## SIGNALS #####################################
|
||||
# ######################################################################
|
||||
self.document_editor_tab.buttonOpen.clicked.disconnect()
|
||||
self.document_editor_tab.buttonOpen.clicked.connect(lambda: self.document_editor_tab.handleOpen(filt=flt))
|
||||
self.document_editor_tab.buttonSave.clicked.disconnect()
|
||||
self.document_editor_tab.buttonSave.clicked.connect(lambda: self.document_editor_tab.handleSaveGCode(filt=flt))
|
||||
|
||||
self.document_editor_tab.code_editor.textChanged.connect(self.on_text_changed)
|
||||
|
||||
self.ui.font_type_cb.currentFontChanged.connect(self.font_family)
|
||||
self.ui.font_size_cb.activated.connect(self.font_size)
|
||||
self.ui.font_bold_tb.clicked.connect(self.on_bold_button)
|
||||
self.ui.font_italic_tb.clicked.connect(self.on_italic_button)
|
||||
self.ui.font_under_tb.clicked.connect(self.on_underline_button)
|
||||
|
||||
self.ui.font_color_entry.editingFinished.connect(self.on_font_color_entry)
|
||||
self.ui.font_color_button.clicked.connect(self.on_font_color_button)
|
||||
self.ui.sel_color_entry.editingFinished.connect(self.on_selection_color_entry)
|
||||
self.ui.sel_color_button.clicked.connect(self.on_selection_color_button)
|
||||
|
||||
self.ui.al_left_tb.clicked.connect(lambda: self.document_editor_tab.code_editor.setAlignment(Qt.AlignLeft))
|
||||
self.ui.al_center_tb.clicked.connect(lambda: self.document_editor_tab.code_editor.setAlignment(Qt.AlignCenter))
|
||||
self.ui.al_right_tb.clicked.connect(lambda: self.document_editor_tab.code_editor.setAlignment(Qt.AlignRight))
|
||||
self.ui.al_justify_tb.clicked.connect(
|
||||
lambda: self.document_editor_tab.code_editor.setAlignment(Qt.AlignJustify)
|
||||
)
|
||||
|
||||
self.ui.autocomplete_cb.stateChanged.connect(self.on_autocomplete_changed)
|
||||
self.ui.tab_size_spinner.returnPressed.connect(self.on_tab_size_change)
|
||||
# #######################################################################
|
||||
|
||||
self.ui.font_color_entry.set_value(self.app.defaults['document_font_color'])
|
||||
self.ui.font_color_button.setStyleSheet(
|
||||
"background-color:%s" % str(self.app.defaults['document_font_color']))
|
||||
|
||||
self.ui.sel_color_entry.set_value(self.app.defaults['document_sel_color'])
|
||||
self.ui.sel_color_button.setStyleSheet(
|
||||
"background-color:%s" % self.app.defaults['document_sel_color'])
|
||||
|
||||
self.ui.font_size_cb.setCurrentIndex(int(self.app.defaults['document_font_size']))
|
||||
|
||||
self.document_editor_tab.handleTextChanged()
|
||||
self.ser_attrs = ['options', 'kind', 'source_file']
|
||||
|
||||
if Qt.mightBeRichText(self.source_file):
|
||||
self.document_editor_tab.code_editor.setHtml(self.source_file)
|
||||
else:
|
||||
for line in self.source_file.splitlines():
|
||||
self.document_editor_tab.code_editor.append(line)
|
||||
|
||||
self.build_ui()
|
||||
|
||||
@property
|
||||
def read_only(self):
|
||||
return self._read_only
|
||||
|
||||
@read_only.setter
|
||||
def read_only(self, val):
|
||||
if val:
|
||||
self._read_only = True
|
||||
else:
|
||||
self._read_only = False
|
||||
|
||||
def build_ui(self):
|
||||
FlatCAMObj.build_ui(self)
|
||||
tab_here = False
|
||||
|
||||
# try to not add too many times a tab that it is already installed
|
||||
for idx in range(self.app.ui.plot_tab_area.count()):
|
||||
if self.app.ui.plot_tab_area.widget(idx).objectName() == self.options['name']:
|
||||
tab_here = True
|
||||
break
|
||||
|
||||
# add the tab if it is not already added
|
||||
if tab_here is False:
|
||||
self.app.ui.plot_tab_area.addTab(self.document_editor_tab, '%s' % _("Document Editor"))
|
||||
self.document_editor_tab.setObjectName(self.options['name'])
|
||||
|
||||
# Switch plot_area to CNCJob tab
|
||||
self.app.ui.plot_tab_area.setCurrentWidget(self.document_editor_tab)
|
||||
|
||||
def on_autocomplete_changed(self, state):
|
||||
if state:
|
||||
self.document_editor_tab.code_editor.completer_enable = True
|
||||
else:
|
||||
self.document_editor_tab.code_editor.completer_enable = False
|
||||
|
||||
def on_tab_size_change(self, val=None):
|
||||
try:
|
||||
self.ui.tab_size_spinner.returnPressed.disconnect(self.on_tab_size_change)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
if val:
|
||||
self.ui.tab_size_spinner.set_value(val)
|
||||
|
||||
tab_balue = int(self.ui.tab_size_spinner.get_value())
|
||||
self.document_editor_tab.code_editor.setTabStopWidth(tab_balue)
|
||||
self.app.defaults['document_tab_size'] = tab_balue
|
||||
|
||||
self.ui.tab_size_spinner.returnPressed.connect(self.on_tab_size_change)
|
||||
|
||||
def on_text_changed(self):
|
||||
self.source_file = self.document_editor_tab.code_editor.toHtml()
|
||||
# print(self.source_file)
|
||||
|
||||
def font_family(self, font):
|
||||
# self.document_editor_tab.code_editor.selectAll()
|
||||
font.setPointSize(float(self.ui.font_size_cb.get_value()))
|
||||
self.document_editor_tab.code_editor.setCurrentFont(font)
|
||||
self.font_name = self.ui.font_type_cb.currentFont().family()
|
||||
|
||||
def font_size(self):
|
||||
# self.document_editor_tab.code_editor.selectAll()
|
||||
self.document_editor_tab.code_editor.setFontPointSize(float(self.ui.font_size_cb.get_value()))
|
||||
|
||||
def on_bold_button(self):
|
||||
if self.ui.font_bold_tb.isChecked():
|
||||
self.document_editor_tab.code_editor.setFontWeight(QtGui.QFont.Bold)
|
||||
self.font_bold = True
|
||||
else:
|
||||
self.document_editor_tab.code_editor.setFontWeight(QtGui.QFont.Normal)
|
||||
self.font_bold = False
|
||||
|
||||
def on_italic_button(self):
|
||||
if self.ui.font_italic_tb.isChecked():
|
||||
self.document_editor_tab.code_editor.setFontItalic(True)
|
||||
self.font_italic = True
|
||||
else:
|
||||
self.document_editor_tab.code_editor.setFontItalic(False)
|
||||
self.font_italic = False
|
||||
|
||||
def on_underline_button(self):
|
||||
if self.ui.font_under_tb.isChecked():
|
||||
self.document_editor_tab.code_editor.setFontUnderline(True)
|
||||
self.font_underline = True
|
||||
else:
|
||||
self.document_editor_tab.code_editor.setFontUnderline(False)
|
||||
self.font_underline = False
|
||||
|
||||
# Setting font colors handlers
|
||||
def on_font_color_entry(self):
|
||||
self.app.defaults['document_font_color'] = self.ui.font_color_entry.get_value()
|
||||
self.ui.font_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['document_font_color']))
|
||||
|
||||
def on_font_color_button(self):
|
||||
current_color = QtGui.QColor(self.app.defaults['document_font_color'])
|
||||
|
||||
c_dialog = QtWidgets.QColorDialog()
|
||||
font_color = c_dialog.getColor(initial=current_color)
|
||||
|
||||
if font_color.isValid() is False:
|
||||
return
|
||||
|
||||
self.document_editor_tab.code_editor.setTextColor(font_color)
|
||||
self.ui.font_color_button.setStyleSheet("background-color:%s" % str(font_color.name()))
|
||||
|
||||
new_val = str(font_color.name())
|
||||
self.ui.font_color_entry.set_value(new_val)
|
||||
self.app.defaults['document_font_color'] = new_val
|
||||
|
||||
# Setting selection colors handlers
|
||||
def on_selection_color_entry(self):
|
||||
self.app.defaults['document_sel_color'] = self.ui.sel_color_entry.get_value()
|
||||
self.ui.sel_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['document_sel_color']))
|
||||
|
||||
def on_selection_color_button(self):
|
||||
current_color = QtGui.QColor(self.app.defaults['document_sel_color'])
|
||||
|
||||
c_dialog = QtWidgets.QColorDialog()
|
||||
sel_color = c_dialog.getColor(initial=current_color)
|
||||
|
||||
if sel_color.isValid() is False:
|
||||
return
|
||||
|
||||
p = QtGui.QPalette()
|
||||
p.setColor(QtGui.QPalette.Highlight, sel_color)
|
||||
p.setColor(QtGui.QPalette.HighlightedText, QtGui.QColor('white'))
|
||||
|
||||
self.document_editor_tab.code_editor.setPalette(p)
|
||||
|
||||
self.ui.sel_color_button.setStyleSheet("background-color:%s" % str(sel_color.name()))
|
||||
|
||||
new_val = str(sel_color.name())
|
||||
self.ui.sel_color_entry.set_value(new_val)
|
||||
self.app.defaults['document_sel_color'] = new_val
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Returns a representation of the object as a dictionary.
|
||||
Attributes to include are listed in ``self.ser_attrs``.
|
||||
|
||||
:return: A dictionary-encoded copy of the object.
|
||||
:rtype: dict
|
||||
"""
|
||||
d = {}
|
||||
for attr in self.ser_attrs:
|
||||
d[attr] = getattr(self, attr)
|
||||
return d
|
||||
|
||||
def from_dict(self, d):
|
||||
"""
|
||||
Sets object's attributes from a dictionary.
|
||||
Attributes to include are listed in ``self.ser_attrs``.
|
||||
This method will look only for only and all the
|
||||
attributes in ``self.ser_attrs``. They must all
|
||||
be present. Use only for deserializing saved
|
||||
objects.
|
||||
|
||||
:param d: Dictionary of attributes to set in the object.
|
||||
:type d: dict
|
||||
:return: None
|
||||
"""
|
||||
for attr in self.ser_attrs:
|
||||
setattr(self, attr, d[attr])
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,505 @@
|
|||
# ##########################################################
|
||||
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||
# http://flatcam.org #
|
||||
# Author: Juan Pablo Caram (c) #
|
||||
# Date: 2/5/2014 #
|
||||
# MIT Licence #
|
||||
# ##########################################################
|
||||
|
||||
# ##########################################################
|
||||
# File modified by: Marius Stanciu #
|
||||
# ##########################################################
|
||||
|
||||
import inspect # TODO: For debugging only.
|
||||
|
||||
from flatcamGUI.ObjectUI import *
|
||||
|
||||
from FlatCAMCommon import LoudDict
|
||||
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||
|
||||
import sys
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
# Interrupts plotting process if FlatCAMObj has been deleted
|
||||
class ObjectDeleted(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ValidationError(Exception):
|
||||
def __init__(self, message, errors):
|
||||
super().__init__(message)
|
||||
|
||||
self.errors = errors
|
||||
|
||||
|
||||
class FlatCAMObj(QtCore.QObject):
|
||||
"""
|
||||
Base type of objects handled in FlatCAM. These become interactive
|
||||
in the GUI, can be plotted, and their options can be modified
|
||||
by the user in their respective forms.
|
||||
"""
|
||||
|
||||
# Instance of the application to which these are related.
|
||||
# The app should set this value.
|
||||
app = None
|
||||
|
||||
# signal to plot a single object
|
||||
plot_single_object = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, name):
|
||||
"""
|
||||
Constructor.
|
||||
|
||||
:param name: Name of the object given by the user.
|
||||
:return: FlatCAMObj
|
||||
"""
|
||||
|
||||
QtCore.QObject.__init__(self)
|
||||
|
||||
# View
|
||||
self.ui = None
|
||||
|
||||
self.options = LoudDict(name=name)
|
||||
self.options.set_change_callback(self.on_options_change)
|
||||
|
||||
self.form_fields = {}
|
||||
|
||||
# store here the default data for Geometry Data
|
||||
self.default_data = {}
|
||||
|
||||
# 2D mode
|
||||
# Axes must exist and be attached to canvas.
|
||||
self.axes = None
|
||||
self.kind = None # Override with proper name
|
||||
|
||||
if self.app.is_legacy is False:
|
||||
self.shapes = self.app.plotcanvas.new_shape_group()
|
||||
# self.shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, pool=self.app.pool, layers=2)
|
||||
else:
|
||||
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name=name)
|
||||
|
||||
self.mark_shapes = {}
|
||||
|
||||
self.item = None # Link with project view item
|
||||
|
||||
self.muted_ui = False
|
||||
self.deleted = False
|
||||
|
||||
try:
|
||||
self._drawing_tolerance = float(self.app.defaults["global_tolerance"]) if \
|
||||
self.app.defaults["global_tolerance"] else 0.01
|
||||
except ValueError:
|
||||
self._drawing_tolerance = 0.01
|
||||
|
||||
self.isHovering = False
|
||||
self.notHovering = True
|
||||
|
||||
# Flag to show if a selection shape is drawn
|
||||
self.selection_shape_drawn = False
|
||||
|
||||
# self.units = 'IN'
|
||||
self.units = self.app.defaults['units']
|
||||
|
||||
self.plot_single_object.connect(self.single_object_plot)
|
||||
|
||||
def __del__(self):
|
||||
pass
|
||||
|
||||
def __str__(self):
|
||||
return "<FlatCAMObj({:12s}): {:20s}>".format(self.kind, self.options["name"])
|
||||
|
||||
def from_dict(self, d):
|
||||
"""
|
||||
This supersedes ``from_dict`` in derived classes. Derived classes
|
||||
must inherit from FlatCAMObj first, then from derivatives of Geometry.
|
||||
|
||||
``self.options`` is only updated, not overwritten. This ensures that
|
||||
options set by the app do not vanish when reading the objects
|
||||
from a project file.
|
||||
|
||||
:param d: Dictionary with attributes to set.
|
||||
:return: None
|
||||
"""
|
||||
|
||||
for attr in self.ser_attrs:
|
||||
|
||||
if attr == 'options':
|
||||
self.options.update(d[attr])
|
||||
else:
|
||||
try:
|
||||
setattr(self, attr, d[attr])
|
||||
except KeyError:
|
||||
log.debug("FlatCAMObj.from_dict() --> KeyError: %s. "
|
||||
"Means that we are loading an old project that don't"
|
||||
"have all attributes in the latest FlatCAM." % str(attr))
|
||||
pass
|
||||
|
||||
def on_options_change(self, key):
|
||||
# Update form on programmatically options change
|
||||
self.set_form_item(key)
|
||||
|
||||
# Set object visibility
|
||||
if key == 'plot':
|
||||
self.visible = self.options['plot']
|
||||
|
||||
self.optionChanged.emit(key)
|
||||
|
||||
def set_ui(self, ui):
|
||||
self.ui = ui
|
||||
|
||||
self.form_fields = {"name": self.ui.name_entry}
|
||||
|
||||
assert isinstance(self.ui, ObjectUI)
|
||||
self.ui.name_entry.returnPressed.connect(self.on_name_activate)
|
||||
|
||||
try:
|
||||
# it will raise an exception for those FlatCAM objects that do not build UI with the common elements
|
||||
self.ui.offset_button.clicked.connect(self.on_offset_button_click)
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
try:
|
||||
self.ui.scale_button.clicked.connect(self.on_scale_button_click)
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
try:
|
||||
self.ui.offsetvector_entry.returnPressed.connect(self.on_offset_button_click)
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
# Creates problems on focusOut
|
||||
try:
|
||||
self.ui.scale_entry.returnPressed.connect(self.on_scale_button_click)
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
# self.ui.skew_button.clicked.connect(self.on_skew_button_click)
|
||||
|
||||
def build_ui(self):
|
||||
"""
|
||||
Sets up the UI/form for this object. Show the UI
|
||||
in the App.
|
||||
|
||||
:return: None
|
||||
:rtype: None
|
||||
"""
|
||||
|
||||
self.muted_ui = True
|
||||
log.debug(str(inspect.stack()[1][3]) + "--> FlatCAMObj.build_ui()")
|
||||
|
||||
try:
|
||||
# HACK: disconnect the scale entry signal since on focus out event will trigger an undesired scale()
|
||||
# it seems that the takewidget() does generate a focus out event for the QDoubleSpinbox ...
|
||||
# and reconnect after the takeWidget() is done
|
||||
# self.ui.scale_entry.returnPressed.disconnect(self.on_scale_button_click)
|
||||
self.app.ui.selected_scroll_area.takeWidget()
|
||||
# self.ui.scale_entry.returnPressed.connect(self.on_scale_button_click)
|
||||
except Exception as e:
|
||||
self.app.log.debug("FlatCAMObj.build_ui() --> Nothing to remove: %s" % str(e))
|
||||
|
||||
self.app.ui.selected_scroll_area.setWidget(self.ui)
|
||||
# self.ui.setMinimumWidth(100)
|
||||
# self.ui.setMaximumWidth(self.app.ui.selected_tab.sizeHint().width())
|
||||
|
||||
self.muted_ui = False
|
||||
|
||||
def on_name_activate(self, silent=None):
|
||||
old_name = copy(self.options["name"])
|
||||
new_name = self.ui.name_entry.get_value()
|
||||
|
||||
if new_name != old_name:
|
||||
# update the SHELL auto-completer model data
|
||||
try:
|
||||
self.app.myKeywords.remove(old_name)
|
||||
self.app.myKeywords.append(new_name)
|
||||
self.app.shell._edit.set_model_data(self.app.myKeywords)
|
||||
self.app.ui.code_editor.set_model_data(self.app.myKeywords)
|
||||
except Exception:
|
||||
log.debug("on_name_activate() --> Could not remove the old object name from auto-completer model list")
|
||||
|
||||
self.options["name"] = self.ui.name_entry.get_value()
|
||||
self.default_data["name"] = self.ui.name_entry.get_value()
|
||||
self.app.collection.update_view()
|
||||
if silent:
|
||||
self.app.inform.emit('[success] %s: %s %s: %s' % (
|
||||
_("Name changed from"), str(old_name), _("to"), str(new_name)
|
||||
)
|
||||
)
|
||||
|
||||
def on_offset_button_click(self):
|
||||
self.app.report_usage("obj_on_offset_button")
|
||||
|
||||
self.read_form()
|
||||
vector_val = self.ui.offsetvector_entry.get_value()
|
||||
|
||||
def worker_task():
|
||||
with self.app.proc_container.new(_("Offsetting...")):
|
||||
self.offset(vector_val)
|
||||
self.app.proc_container.update_view_text('')
|
||||
with self.app.proc_container.new('%s...' % _("Plotting")):
|
||||
self.plot()
|
||||
self.app.object_changed.emit(self)
|
||||
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
|
||||
|
||||
def on_scale_button_click(self):
|
||||
self.read_form()
|
||||
try:
|
||||
factor = float(eval(self.ui.scale_entry.get_value()))
|
||||
except Exception as e:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Scaling could not be executed."))
|
||||
log.debug("FlatCAMObj.on_scale_button_click() -- %s" % str(e))
|
||||
return
|
||||
|
||||
if type(factor) != float:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Scaling could not be executed."))
|
||||
|
||||
# if factor is 1.0 do nothing, there is no point in scaling with a factor of 1.0
|
||||
if factor == 1.0:
|
||||
self.app.inform.emit('[success] %s' % _("Scale done."))
|
||||
return
|
||||
|
||||
log.debug("FlatCAMObj.on_scale_button_click()")
|
||||
|
||||
def worker_task():
|
||||
with self.app.proc_container.new(_("Scaling...")):
|
||||
self.scale(factor)
|
||||
self.app.inform.emit('[success] %s' % _("Scale done."))
|
||||
|
||||
self.app.proc_container.update_view_text('')
|
||||
with self.app.proc_container.new('%s...' % _("Plotting")):
|
||||
self.plot()
|
||||
self.app.object_changed.emit(self)
|
||||
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
|
||||
|
||||
def on_skew_button_click(self):
|
||||
self.app.report_usage("obj_on_skew_button")
|
||||
self.read_form()
|
||||
x_angle = self.ui.xangle_entry.get_value()
|
||||
y_angle = self.ui.yangle_entry.get_value()
|
||||
|
||||
def worker_task():
|
||||
with self.app.proc_container.new(_("Skewing...")):
|
||||
self.skew(x_angle, y_angle)
|
||||
self.app.proc_container.update_view_text('')
|
||||
with self.app.proc_container.new('%s...' % _("Plotting")):
|
||||
self.plot()
|
||||
self.app.object_changed.emit(self)
|
||||
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
|
||||
|
||||
def to_form(self):
|
||||
"""
|
||||
Copies options to the UI form.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
log.debug(str(inspect.stack()[1][3]) + " --> FlatCAMObj.to_form()")
|
||||
for option in self.options:
|
||||
try:
|
||||
self.set_form_item(option)
|
||||
except Exception:
|
||||
self.app.log.warning("Unexpected error:", sys.exc_info())
|
||||
|
||||
def read_form(self):
|
||||
"""
|
||||
Reads form into ``self.options``.
|
||||
|
||||
:return: None
|
||||
:rtype: None
|
||||
"""
|
||||
log.debug(str(inspect.stack()[1][3]) + "--> FlatCAMObj.read_form()")
|
||||
for option in self.options:
|
||||
try:
|
||||
self.read_form_item(option)
|
||||
except Exception:
|
||||
self.app.log.warning("Unexpected error:", sys.exc_info())
|
||||
|
||||
def set_form_item(self, option):
|
||||
"""
|
||||
Copies the specified option to the UI form.
|
||||
|
||||
:param option: Name of the option (Key in ``self.options``).
|
||||
:type option: str
|
||||
:return: None
|
||||
"""
|
||||
|
||||
try:
|
||||
self.form_fields[option].set_value(self.options[option])
|
||||
except KeyError:
|
||||
# self.app.log.warn("Tried to set an option or field that does not exist: %s" % option)
|
||||
pass
|
||||
|
||||
def read_form_item(self, option):
|
||||
"""
|
||||
Reads the specified option from the UI form into ``self.options``.
|
||||
|
||||
:param option: Name of the option.
|
||||
:type option: str
|
||||
:return: None
|
||||
"""
|
||||
try:
|
||||
self.options[option] = self.form_fields[option].get_value()
|
||||
except KeyError:
|
||||
pass
|
||||
# self.app.log.warning("Failed to read option from field: %s" % option)
|
||||
|
||||
def plot(self, kind=None):
|
||||
"""
|
||||
Plot this object (Extend this method to implement the actual plotting).
|
||||
Call this in descendants before doing the plotting.
|
||||
|
||||
:param kind: Used by only some of the FlatCAM objects
|
||||
:return: Whether to continue plotting or not depending on the "plot" option. Boolean
|
||||
"""
|
||||
log.debug(str(inspect.stack()[1][3]) + " --> FlatCAMObj.plot()")
|
||||
|
||||
if self.deleted:
|
||||
return False
|
||||
|
||||
self.clear()
|
||||
return True
|
||||
|
||||
def single_object_plot(self):
|
||||
def plot_task():
|
||||
with self.app.proc_container.new('%s...' % _("Plotting")):
|
||||
self.plot()
|
||||
self.app.object_changed.emit(self)
|
||||
|
||||
self.app.worker_task.emit({'fcn': plot_task, 'params': []})
|
||||
|
||||
def serialize(self):
|
||||
"""
|
||||
Returns a representation of the object as a dictionary so
|
||||
it can be later exported as JSON. Override this method.
|
||||
|
||||
:return: Dictionary representing the object
|
||||
:rtype: dict
|
||||
"""
|
||||
return
|
||||
|
||||
def deserialize(self, obj_dict):
|
||||
"""
|
||||
Re-builds an object from its serialized version.
|
||||
|
||||
:param obj_dict: Dictionary representing a FlatCAMObj
|
||||
:type obj_dict: dict
|
||||
:return: None
|
||||
"""
|
||||
return
|
||||
|
||||
def add_shape(self, **kwargs):
|
||||
if self.deleted:
|
||||
raise ObjectDeleted()
|
||||
else:
|
||||
key = self.shapes.add(tolerance=self.drawing_tolerance, **kwargs)
|
||||
return key
|
||||
|
||||
def add_mark_shape(self, apid, **kwargs):
|
||||
if self.deleted:
|
||||
raise ObjectDeleted()
|
||||
else:
|
||||
key = self.mark_shapes[apid].add(tolerance=self.drawing_tolerance, layer=0, **kwargs)
|
||||
return key
|
||||
|
||||
def update_filters(self, last_ext, filter_string):
|
||||
"""
|
||||
Will modify the filter string that is used when saving a file (a list of file extensions) to have the last
|
||||
used file extension as the first one in the special string
|
||||
|
||||
:param last_ext: The file extension that was last used to save a file
|
||||
:param filter_string: A key in self.app.defaults that holds a string with the filter from QFileDialog
|
||||
used when saving a file
|
||||
:return: None
|
||||
"""
|
||||
|
||||
filters = copy(self.app.defaults[filter_string])
|
||||
filter_list = filters.split(';;')
|
||||
filter_list_enum_1 = enumerate(filter_list)
|
||||
|
||||
# search for the last element in the filters which should always be "All Files (*.*)"
|
||||
last_elem = ''
|
||||
for elem in list(filter_list_enum_1):
|
||||
if '(*.*)' in elem[1]:
|
||||
last_elem = filter_list.pop(elem[0])
|
||||
|
||||
filter_list_enum = enumerate(filter_list)
|
||||
for elem in list(filter_list_enum):
|
||||
if '.' + last_ext in elem[1]:
|
||||
used_ext = filter_list.pop(elem[0])
|
||||
|
||||
# sort the extensions back
|
||||
filter_list.sort(key=lambda x: x.rpartition('.')[2])
|
||||
|
||||
# add as a first element the last used extension
|
||||
filter_list.insert(0, used_ext)
|
||||
# add back the element that should always be the last (All Files)
|
||||
filter_list.append(last_elem)
|
||||
|
||||
self.app.defaults[filter_string] = ';;'.join(filter_list)
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
def poly2rings(poly):
|
||||
return [poly.exterior] + [interior for interior in poly.interiors]
|
||||
|
||||
@property
|
||||
def visible(self):
|
||||
return self.shapes.visible
|
||||
|
||||
@visible.setter
|
||||
def visible(self, value, threaded=True):
|
||||
log.debug("FlatCAMObj.visible()")
|
||||
|
||||
def worker_task(app_obj):
|
||||
self.shapes.visible = value
|
||||
|
||||
if self.app.is_legacy is False:
|
||||
# Not all object types has annotations
|
||||
try:
|
||||
self.annotation.visible = value
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if threaded is False:
|
||||
worker_task(app_obj=self.app)
|
||||
else:
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': [self]})
|
||||
|
||||
@property
|
||||
def drawing_tolerance(self):
|
||||
self.units = self.app.defaults['units'].upper()
|
||||
tol = self._drawing_tolerance if self.units == 'MM' or not self.units else self._drawing_tolerance / 25.4
|
||||
return tol
|
||||
|
||||
@drawing_tolerance.setter
|
||||
def drawing_tolerance(self, value):
|
||||
self.units = self.app.defaults['units'].upper()
|
||||
self._drawing_tolerance = value if self.units == 'MM' or not self.units else value / 25.4
|
||||
|
||||
def clear(self, update=False):
|
||||
self.shapes.clear(update)
|
||||
|
||||
# Not all object types has annotations
|
||||
try:
|
||||
self.annotation.clear(update)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def delete(self):
|
||||
# Free resources
|
||||
del self.ui
|
||||
del self.options
|
||||
|
||||
# Set flag
|
||||
self.deleted = True
|
|
@ -0,0 +1,231 @@
|
|||
# ##########################################################
|
||||
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||
# http://flatcam.org #
|
||||
# Author: Juan Pablo Caram (c) #
|
||||
# Date: 2/5/2014 #
|
||||
# MIT Licence #
|
||||
# ##########################################################
|
||||
|
||||
# ##########################################################
|
||||
# File modified by: Marius Stanciu #
|
||||
# ##########################################################
|
||||
|
||||
from flatcamEditors.FlatCAMTextEditor import TextEditor
|
||||
from flatcamObjects.FlatCAMObj import *
|
||||
from flatcamGUI.ObjectUI import *
|
||||
|
||||
import tkinter as tk
|
||||
import sys
|
||||
from copy import deepcopy
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class ScriptObject(FlatCAMObj):
|
||||
"""
|
||||
Represents a TCL script object.
|
||||
"""
|
||||
optionChanged = QtCore.pyqtSignal(str)
|
||||
ui_type = ScriptObjectUI
|
||||
|
||||
def __init__(self, name):
|
||||
self.decimals = self.app.decimals
|
||||
|
||||
log.debug("Creating a ScriptObject object...")
|
||||
FlatCAMObj.__init__(self, name)
|
||||
|
||||
self.kind = "script"
|
||||
|
||||
self.options.update({
|
||||
"plot": True,
|
||||
"type": 'Script',
|
||||
"source_file": '',
|
||||
})
|
||||
|
||||
self.units = ''
|
||||
|
||||
self.ser_attrs = ['options', 'kind', 'source_file']
|
||||
self.source_file = ''
|
||||
self.script_code = ''
|
||||
|
||||
self.units_found = self.app.defaults['units']
|
||||
|
||||
# self.script_editor_tab = TextEditor(app=self.app, plain_text=True)
|
||||
self.script_editor_tab = TextEditor(app=self.app, plain_text=True)
|
||||
|
||||
def set_ui(self, ui):
|
||||
"""
|
||||
Sets the Object UI in Selected Tab for the FlatCAM Script type of object.
|
||||
:param ui:
|
||||
:return:
|
||||
"""
|
||||
FlatCAMObj.set_ui(self, ui)
|
||||
log.debug("ScriptObject.set_ui()")
|
||||
|
||||
assert isinstance(self.ui, ScriptObjectUI), \
|
||||
"Expected a ScriptObjectUI, got %s" % type(self.ui)
|
||||
|
||||
self.units = self.app.defaults['units'].upper()
|
||||
self.units_found = self.app.defaults['units']
|
||||
|
||||
# Fill form fields only on object create
|
||||
self.to_form()
|
||||
|
||||
# Show/Hide Advanced Options
|
||||
if self.app.defaults["global_app_level"] == 'b':
|
||||
self.ui.level.setText(_(
|
||||
'<span style="color:green;"><b>Basic</b></span>'
|
||||
))
|
||||
else:
|
||||
self.ui.level.setText(_(
|
||||
'<span style="color:red;"><b>Advanced</b></span>'
|
||||
))
|
||||
|
||||
# tab_here = False
|
||||
# # try to not add too many times a tab that it is already installed
|
||||
# for idx in range(self.app.ui.plot_tab_area.count()):
|
||||
# if self.app.ui.plot_tab_area.widget(idx).objectName() == self.options['name']:
|
||||
# tab_here = True
|
||||
# break
|
||||
#
|
||||
# # add the tab if it is not already added
|
||||
# if tab_here is False:
|
||||
# self.app.ui.plot_tab_area.addTab(self.script_editor_tab, '%s' % _("Script Editor"))
|
||||
# self.script_editor_tab.setObjectName(self.options['name'])
|
||||
|
||||
self.app.ui.plot_tab_area.addTab(self.script_editor_tab, '%s' % _("Script Editor"))
|
||||
self.script_editor_tab.setObjectName(self.options['name'])
|
||||
|
||||
# first clear previous text in text editor (if any)
|
||||
# self.script_editor_tab.code_editor.clear()
|
||||
# self.script_editor_tab.code_editor.setReadOnly(False)
|
||||
|
||||
self.ui.autocomplete_cb.set_value(self.app.defaults['script_autocompleter'])
|
||||
self.on_autocomplete_changed(state=self.app.defaults['script_autocompleter'])
|
||||
|
||||
self.script_editor_tab.buttonRun.show()
|
||||
|
||||
# Switch plot_area to CNCJob tab
|
||||
self.app.ui.plot_tab_area.setCurrentWidget(self.script_editor_tab)
|
||||
|
||||
flt = "FlatCAM Scripts (*.FlatScript);;All Files (*.*)"
|
||||
self.script_editor_tab.buttonOpen.clicked.disconnect()
|
||||
self.script_editor_tab.buttonOpen.clicked.connect(lambda: self.script_editor_tab.handleOpen(filt=flt))
|
||||
self.script_editor_tab.buttonSave.clicked.disconnect()
|
||||
self.script_editor_tab.buttonSave.clicked.connect(lambda: self.script_editor_tab.handleSaveGCode(filt=flt))
|
||||
|
||||
self.script_editor_tab.buttonRun.clicked.connect(self.handle_run_code)
|
||||
self.script_editor_tab.handleTextChanged()
|
||||
|
||||
self.ui.autocomplete_cb.stateChanged.connect(self.on_autocomplete_changed)
|
||||
|
||||
self.ser_attrs = ['options', 'kind', 'source_file']
|
||||
|
||||
# ---------------------------------------------------- #
|
||||
# ----------- LOAD THE TEXT SOURCE FILE -------------- #
|
||||
# ---------------------------------------------------- #
|
||||
self.app.proc_container.view.set_busy(_("Loading..."))
|
||||
self.script_editor_tab.t_frame.hide()
|
||||
|
||||
try:
|
||||
self.script_editor_tab.code_editor.setPlainText(self.source_file)
|
||||
# for line in self.source_file.splitlines():
|
||||
# QtWidgets.QApplication.processEvents()
|
||||
# self.script_editor_tab.code_editor.append(line)
|
||||
except Exception as e:
|
||||
log.debug("ScriptObject.set_ui() --> %s" % str(e))
|
||||
|
||||
self.script_editor_tab.code_editor.moveCursor(QtGui.QTextCursor.End)
|
||||
self.script_editor_tab.t_frame.show()
|
||||
|
||||
self.app.proc_container.view.set_idle()
|
||||
self.build_ui()
|
||||
|
||||
def build_ui(self):
|
||||
FlatCAMObj.build_ui(self)
|
||||
|
||||
def handle_run_code(self):
|
||||
# trying to run a Tcl command without having the Shell open will create some warnings because the Tcl Shell
|
||||
# tries to print on a hidden widget, therefore show the dock if hidden
|
||||
if self.app.ui.shell_dock.isHidden():
|
||||
self.app.ui.shell_dock.show()
|
||||
|
||||
self.script_code = deepcopy(self.script_editor_tab.code_editor.toPlainText())
|
||||
|
||||
old_line = ''
|
||||
for tcl_command_line in self.script_code.splitlines():
|
||||
# do not process lines starting with '#' = comment and empty lines
|
||||
if not tcl_command_line.startswith('#') and tcl_command_line != '':
|
||||
# id FlatCAM is run in Windows then replace all the slashes with
|
||||
# the UNIX style slash that TCL understands
|
||||
if sys.platform == 'win32':
|
||||
if "open" in tcl_command_line:
|
||||
tcl_command_line = tcl_command_line.replace('\\', '/')
|
||||
|
||||
if old_line != '':
|
||||
new_command = old_line + tcl_command_line + '\n'
|
||||
else:
|
||||
new_command = tcl_command_line
|
||||
|
||||
# execute the actual Tcl command
|
||||
try:
|
||||
self.app.shell.open_processing() # Disables input box.
|
||||
|
||||
result = self.app.tcl.eval(str(new_command))
|
||||
if result != 'None':
|
||||
self.app.shell.append_output(result + '\n')
|
||||
|
||||
old_line = ''
|
||||
except tk.TclError:
|
||||
old_line = old_line + tcl_command_line + '\n'
|
||||
except Exception as e:
|
||||
log.debug("ScriptObject.handleRunCode() --> %s" % str(e))
|
||||
|
||||
if old_line != '':
|
||||
# it means that the script finished with an error
|
||||
result = self.app.tcl.eval("set errorInfo")
|
||||
log.error("Exec command Exception: %s" % (result + '\n'))
|
||||
self.app.shell.append_error('ERROR: ' + result + '\n')
|
||||
|
||||
self.app.shell.close_processing()
|
||||
|
||||
def on_autocomplete_changed(self, state):
|
||||
if state:
|
||||
self.script_editor_tab.code_editor.completer_enable = True
|
||||
else:
|
||||
self.script_editor_tab.code_editor.completer_enable = False
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Returns a representation of the object as a dictionary.
|
||||
Attributes to include are listed in ``self.ser_attrs``.
|
||||
|
||||
:return: A dictionary-encoded copy of the object.
|
||||
:rtype: dict
|
||||
"""
|
||||
d = {}
|
||||
for attr in self.ser_attrs:
|
||||
d[attr] = getattr(self, attr)
|
||||
return d
|
||||
|
||||
def from_dict(self, d):
|
||||
"""
|
||||
Sets object's attributes from a dictionary.
|
||||
Attributes to include are listed in ``self.ser_attrs``.
|
||||
This method will look only for only and all the
|
||||
attributes in ``self.ser_attrs``. They must all
|
||||
be present. Use only for deserializing saved
|
||||
objects.
|
||||
|
||||
:param d: Dictionary of attributes to set in the object.
|
||||
:type d: dict
|
||||
:return: None
|
||||
"""
|
||||
for attr in self.ser_attrs:
|
||||
setattr(self, attr, d[attr])
|
|
@ -7,7 +7,6 @@
|
|||
# ########################################################## ##
|
||||
|
||||
from camlib import Geometry
|
||||
import FlatCAMApp
|
||||
|
||||
import shapely.affinity as affinity
|
||||
from shapely.geometry import Point, LineString
|
||||
|
@ -19,6 +18,7 @@ import traceback
|
|||
from copy import deepcopy
|
||||
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
|
||||
import gettext
|
||||
import builtins
|
||||
|
@ -86,6 +86,7 @@ class Excellon(Geometry):
|
|||
:return: Excellon object.
|
||||
:rtype: Excellon
|
||||
"""
|
||||
|
||||
self.decimals = self.app.decimals
|
||||
|
||||
if geo_steps_per_circle is None:
|
||||
|
@ -241,12 +242,12 @@ class Excellon(Geometry):
|
|||
|
||||
def parse_file(self, filename=None, file_obj=None):
|
||||
"""
|
||||
Reads the specified file as array of lines as
|
||||
passes it to ``parse_lines()``.
|
||||
Reads the specified file as array of lines as passes it to ``parse_lines()``.
|
||||
|
||||
:param filename: The file to be read and parsed.
|
||||
:type filename: str
|
||||
:return: None
|
||||
:param filename: The file to be read and parsed.
|
||||
:param file_obj:
|
||||
:type filename: str
|
||||
:return: None
|
||||
"""
|
||||
if file_obj:
|
||||
estr = file_obj
|
||||
|
@ -298,7 +299,7 @@ class Excellon(Geometry):
|
|||
for eline in elines:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
line_num += 1
|
||||
# log.debug("%3d %s" % (line_num, str(eline)))
|
||||
|
@ -526,7 +527,7 @@ class Excellon(Geometry):
|
|||
slot_dia = 0.05
|
||||
try:
|
||||
slot_dia = float(self.tools[current_tool]['C'])
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
log.debug(
|
||||
'Milling/Drilling slot with tool %s, diam=%f' % (
|
||||
|
@ -596,7 +597,7 @@ class Excellon(Geometry):
|
|||
slot_dia = 0.05
|
||||
try:
|
||||
slot_dia = float(self.tools[current_tool]['C'])
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
log.debug(
|
||||
'Milling/Drilling slot with tool %s, diam=%f' % (
|
||||
|
@ -893,9 +894,8 @@ class Excellon(Geometry):
|
|||
log.info("Zeros: %s, Units %s." % (self.zeros, self.units))
|
||||
except Exception:
|
||||
log.error("Excellon PARSING FAILED. Line %d: %s" % (line_num, eline))
|
||||
msg = '[ERROR_NOTCL] %s' % \
|
||||
_("An internal error has ocurred. See shell.\n")
|
||||
msg += ('{e_code} {tx} {l_nr}: {line}\n').format(
|
||||
msg = '[ERROR_NOTCL] %s' % _("An internal error has occurred. See shell.\n")
|
||||
msg += '{e_code} {tx} {l_nr}: {line}\n'.format(
|
||||
e_code='[ERROR]',
|
||||
tx=_("Excellon Parser error.\nParsing Failed. Line"),
|
||||
l_nr=line_num,
|
||||
|
@ -1010,13 +1010,13 @@ class Excellon(Geometry):
|
|||
"Excellon geometry creation failed due of ERROR: %s" % str(e))
|
||||
return "fail"
|
||||
|
||||
def bounds(self):
|
||||
def bounds(self, flatten=None):
|
||||
"""
|
||||
Returns coordinates of rectangular bounds
|
||||
of Excellon geometry: (xmin, ymin, xmax, ymax).
|
||||
|
||||
:param flatten: No used
|
||||
"""
|
||||
# fixed issue of getting bounds only for one level lists of objects
|
||||
# now it can get bounds for nested lists of objects
|
||||
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.bounds()")
|
||||
|
||||
|
@ -1056,11 +1056,11 @@ class Excellon(Geometry):
|
|||
maxy_list = []
|
||||
|
||||
for tool in self.tools:
|
||||
minx, miny, maxx, maxy = bounds_rec(self.tools[tool]['solid_geometry'])
|
||||
minx_list.append(minx)
|
||||
miny_list.append(miny)
|
||||
maxx_list.append(maxx)
|
||||
maxy_list.append(maxy)
|
||||
eminx, eminy, emaxx, emaxy = bounds_rec(self.tools[tool]['solid_geometry'])
|
||||
minx_list.append(eminx)
|
||||
miny_list.append(eminy)
|
||||
maxx_list.append(emaxx)
|
||||
maxy_list.append(emaxy)
|
||||
|
||||
return min(minx_list), min(miny_list), max(maxx_list), max(maxy_list)
|
||||
|
||||
|
@ -1075,8 +1075,9 @@ class Excellon(Geometry):
|
|||
|
||||
Kind of convolute way to make the conversion and it is based on the assumption that the Excellon file
|
||||
will have detected the units before the tools are parsed and stored in self.tools
|
||||
:param units:
|
||||
:type str: IN or MM
|
||||
|
||||
:param units: 'IN' or 'MM'. String
|
||||
|
||||
:return:
|
||||
"""
|
||||
|
||||
|
@ -1109,12 +1110,13 @@ class Excellon(Geometry):
|
|||
Scales geometry on the XY plane in the object by a given factor.
|
||||
Tool sizes, feedrates an Z-plane dimensions are untouched.
|
||||
|
||||
:param xfactor: Number by which to scale the object.
|
||||
:type xfactor: float
|
||||
:param yfactor: Number by which to scale the object.
|
||||
:type yfactor: float
|
||||
:return: None
|
||||
:rtype: NOne
|
||||
:param xfactor: Number by which to scale the object.
|
||||
:type xfactor: float
|
||||
:param yfactor: Number by which to scale the object.
|
||||
:type yfactor: float
|
||||
:param point: Origin point for scale
|
||||
:return: None
|
||||
:rtype: None
|
||||
"""
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.scale()")
|
||||
|
||||
|
@ -1145,8 +1147,7 @@ class Excellon(Geometry):
|
|||
# variables to display the percentage of work done
|
||||
self.geo_len = 0
|
||||
try:
|
||||
for g in self.drills:
|
||||
self.geo_len += 1
|
||||
self.geo_len = len(self.drills)
|
||||
except TypeError:
|
||||
self.geo_len = 1
|
||||
self.old_disp_number = 0
|
||||
|
@ -1190,12 +1191,12 @@ class Excellon(Geometry):
|
|||
return
|
||||
|
||||
def offset_geom(obj):
|
||||
if type(obj) is list:
|
||||
try:
|
||||
new_obj = []
|
||||
for g in obj:
|
||||
new_obj.append(offset_geom(g))
|
||||
for geo in obj:
|
||||
new_obj.append(offset_geom(geo))
|
||||
return new_obj
|
||||
else:
|
||||
except TypeError:
|
||||
try:
|
||||
return affinity.translate(obj, xoff=dx, yoff=dy)
|
||||
except AttributeError:
|
||||
|
@ -1204,8 +1205,7 @@ class Excellon(Geometry):
|
|||
# variables to display the percentage of work done
|
||||
self.geo_len = 0
|
||||
try:
|
||||
for g in self.drills:
|
||||
self.geo_len += 1
|
||||
self.geo_len = len(self.drills)
|
||||
except TypeError:
|
||||
self.geo_len = 1
|
||||
self.old_disp_number = 0
|
||||
|
@ -1237,11 +1237,11 @@ class Excellon(Geometry):
|
|||
def mirror(self, axis, point):
|
||||
"""
|
||||
|
||||
:param axis: "X" or "Y" indicates around which axis to mirror.
|
||||
:type axis: str
|
||||
:param point: [x, y] point belonging to the mirror axis.
|
||||
:type point: list
|
||||
:return: None
|
||||
:param axis: "X" or "Y" indicates around which axis to mirror.
|
||||
:type axis: str
|
||||
:param point: [x, y] point belonging to the mirror axis.
|
||||
:type point: list
|
||||
:return: None
|
||||
"""
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.mirror()")
|
||||
|
||||
|
@ -1249,12 +1249,12 @@ class Excellon(Geometry):
|
|||
xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis]
|
||||
|
||||
def mirror_geom(obj):
|
||||
if type(obj) is list:
|
||||
try:
|
||||
new_obj = []
|
||||
for g in obj:
|
||||
new_obj.append(mirror_geom(g))
|
||||
for geo in obj:
|
||||
new_obj.append(mirror_geom(geo))
|
||||
return new_obj
|
||||
else:
|
||||
except TypeError:
|
||||
try:
|
||||
return affinity.scale(obj, xscale, yscale, origin=(px, py))
|
||||
except AttributeError:
|
||||
|
@ -1265,8 +1265,7 @@ class Excellon(Geometry):
|
|||
# variables to display the percentage of work done
|
||||
self.geo_len = 0
|
||||
try:
|
||||
for g in self.drills:
|
||||
self.geo_len += 1
|
||||
self.geo_len = len(self.drills)
|
||||
except TypeError:
|
||||
self.geo_len = 1
|
||||
self.old_disp_number = 0
|
||||
|
@ -1300,12 +1299,12 @@ class Excellon(Geometry):
|
|||
Shear/Skew the geometries of an object by angles along x and y dimensions.
|
||||
Tool sizes, feedrates an Z-plane dimensions are untouched.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xs, ys : float, float
|
||||
:param angle_x:
|
||||
:param angle_y:
|
||||
The shear angle(s) for the x and y axes respectively. These can be
|
||||
specified in either degrees (default) or radians by setting
|
||||
use_radians=True.
|
||||
:param point: Origin point for Skew
|
||||
|
||||
See shapely manual for more information:
|
||||
http://toblerity.org/shapely/manual.html#affine-transformations
|
||||
|
@ -1322,12 +1321,12 @@ class Excellon(Geometry):
|
|||
return
|
||||
|
||||
def skew_geom(obj):
|
||||
if type(obj) is list:
|
||||
try:
|
||||
new_obj = []
|
||||
for g in obj:
|
||||
new_obj.append(skew_geom(g))
|
||||
return new_obj
|
||||
else:
|
||||
except TypeError:
|
||||
try:
|
||||
return affinity.skew(obj, angle_x, angle_y, origin=(px, py))
|
||||
except AttributeError:
|
||||
|
@ -1336,8 +1335,7 @@ class Excellon(Geometry):
|
|||
# variables to display the percentage of work done
|
||||
self.geo_len = 0
|
||||
try:
|
||||
for g in self.drills:
|
||||
self.geo_len += 1
|
||||
self.geo_len = len(self.drills)
|
||||
except TypeError:
|
||||
self.geo_len = 1
|
||||
self.old_disp_number = 0
|
||||
|
@ -1393,9 +1391,10 @@ class Excellon(Geometry):
|
|||
def rotate(self, angle, point=None):
|
||||
"""
|
||||
Rotate the geometry of an object by an angle around the 'point' coordinates
|
||||
|
||||
:param angle:
|
||||
:param point: tuple of coordinates (x, y)
|
||||
:return:
|
||||
:param point: tuple of coordinates (x, y)
|
||||
:return: None
|
||||
"""
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.rotate()")
|
||||
|
||||
|
@ -1423,8 +1422,7 @@ class Excellon(Geometry):
|
|||
# variables to display the percentage of work done
|
||||
self.geo_len = 0
|
||||
try:
|
||||
for g in self.drills:
|
||||
self.geo_len += 1
|
||||
self.geo_len = len(self.drills)
|
||||
except TypeError:
|
||||
self.geo_len = 1
|
||||
self.old_disp_number = 0
|
||||
|
@ -1476,9 +1474,10 @@ class Excellon(Geometry):
|
|||
def buffer(self, distance, join, factor):
|
||||
"""
|
||||
|
||||
:param distance: if 'factor' is True then distance is the factor
|
||||
:param factor: True or False (None)
|
||||
:return:
|
||||
:param distance: if 'factor' is True then distance is the factor
|
||||
:param factor: True or False (None)
|
||||
:param join: The type of line joint used by the shapely buffer method: round, square, bevel
|
||||
:return: None
|
||||
"""
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.buffer()")
|
||||
|
||||
|
@ -1486,12 +1485,12 @@ class Excellon(Geometry):
|
|||
return
|
||||
|
||||
def buffer_geom(obj):
|
||||
if type(obj) is list:
|
||||
try:
|
||||
new_obj = []
|
||||
for g in obj:
|
||||
new_obj.append(buffer_geom(g))
|
||||
return new_obj
|
||||
else:
|
||||
except TypeError:
|
||||
try:
|
||||
if factor is None:
|
||||
return obj.buffer(distance, resolution=self.geo_steps_per_circle)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from camlib import Geometry, arc, arc_angle, ApertureMacro
|
||||
import FlatCAMApp
|
||||
|
||||
import numpy as np
|
||||
import re
|
||||
|
@ -9,15 +8,16 @@ import traceback
|
|||
from copy import deepcopy
|
||||
import sys
|
||||
|
||||
from shapely.ops import cascaded_union, unary_union
|
||||
from shapely.geometry import Polygon, MultiPolygon, LineString, Point
|
||||
from shapely.ops import cascaded_union
|
||||
from shapely.affinity import scale, translate
|
||||
import shapely.affinity as affinity
|
||||
from shapely.geometry import box as shply_box
|
||||
from shapely.geometry import box as shply_box, Polygon, LineString, Point, MultiPolygon
|
||||
|
||||
from lxml import etree as ET
|
||||
from flatcamParsers.ParseSVG import *
|
||||
|
||||
from flatcamParsers.ParseSVG import svgparselength, getsvggeo
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
|
||||
import gettext
|
||||
import builtins
|
||||
|
||||
|
@ -255,7 +255,7 @@ class Gerber(Geometry):
|
|||
"""
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# Found some Gerber with a leading zero in the aperture id and the
|
||||
# referenced it without the zero, so this is a hack to handle that.
|
||||
|
@ -403,7 +403,7 @@ class Gerber(Geometry):
|
|||
|
||||
# Absolute or Relative/Incremental coordinates
|
||||
# Not implemented
|
||||
absolute = True
|
||||
# absolute = True
|
||||
|
||||
# How to interpret circular interpolation: SINGLE or MULTI
|
||||
quadrant_mode = None
|
||||
|
@ -428,7 +428,7 @@ class Gerber(Geometry):
|
|||
for gline in glines:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
line_num += 1
|
||||
self.source_file += gline + '\n'
|
||||
|
@ -986,7 +986,7 @@ class Gerber(Geometry):
|
|||
if 'geometry' not in self.apertures[current_aperture]:
|
||||
self.apertures[current_aperture]['geometry'] = []
|
||||
self.apertures[current_aperture]['geometry'].append(deepcopy(geo_dict))
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
last_path_aperture = current_aperture
|
||||
# we do this for the case that a region is done without having defined any aperture
|
||||
|
@ -1229,25 +1229,25 @@ class Gerber(Geometry):
|
|||
try:
|
||||
circular_x = parse_gerber_number(circular_x,
|
||||
self.int_digits, self.frac_digits, self.gerber_zeros)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
circular_x = current_x
|
||||
|
||||
try:
|
||||
circular_y = parse_gerber_number(circular_y,
|
||||
self.int_digits, self.frac_digits, self.gerber_zeros)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
circular_y = current_y
|
||||
|
||||
# According to Gerber specification i and j are not modal, which means that when i or j are missing,
|
||||
# they are to be interpreted as being zero
|
||||
try:
|
||||
i = parse_gerber_number(i, self.int_digits, self.frac_digits, self.gerber_zeros)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
i = 0
|
||||
|
||||
try:
|
||||
j = parse_gerber_number(j, self.int_digits, self.frac_digits, self.gerber_zeros)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
j = 0
|
||||
|
||||
if quadrant_mode is None:
|
||||
|
@ -1668,13 +1668,14 @@ class Gerber(Geometry):
|
|||
bbox = bbox.envelope
|
||||
return bbox
|
||||
|
||||
def bounds(self):
|
||||
def bounds(self, flatten=None):
|
||||
"""
|
||||
Returns coordinates of rectangular bounds
|
||||
of Gerber geometry: (xmin, ymin, xmax, ymax).
|
||||
|
||||
:param flatten: Not used, it is here for compatibility with base class method
|
||||
:return: None
|
||||
"""
|
||||
# fixed issue of getting bounds only for one level lists of objects
|
||||
# now it can get bounds for nested lists of objects
|
||||
|
||||
log.debug("parseGerber.Gerber.bounds()")
|
||||
|
||||
|
@ -1999,8 +2000,7 @@ class Gerber(Geometry):
|
|||
# variables to display the percentage of work done
|
||||
self.geo_len = 0
|
||||
try:
|
||||
for __ in self.solid_geometry:
|
||||
self.geo_len += 1
|
||||
self.geo_len = len(self.solid_geometry)
|
||||
except TypeError:
|
||||
self.geo_len = 1
|
||||
|
||||
|
@ -2078,8 +2078,7 @@ class Gerber(Geometry):
|
|||
# variables to display the percentage of work done
|
||||
self.geo_len = 0
|
||||
try:
|
||||
for __ in self.solid_geometry:
|
||||
self.geo_len += 1
|
||||
self.geo_len = len(self.solid_geometry)
|
||||
except TypeError:
|
||||
self.geo_len = 1
|
||||
|
||||
|
@ -2217,8 +2216,7 @@ class Gerber(Geometry):
|
|||
# variables to display the percentage of work done
|
||||
self.geo_len = 0
|
||||
try:
|
||||
for __ in self.solid_geometry:
|
||||
self.geo_len += 1
|
||||
self.geo_len = len(self.solid_geometry)
|
||||
except TypeError:
|
||||
self.geo_len = 1
|
||||
|
||||
|
@ -2266,8 +2264,9 @@ class Gerber(Geometry):
|
|||
def buffer(self, distance, join, factor=None):
|
||||
"""
|
||||
|
||||
:param distance: if 'factor' is True then distance is the factor
|
||||
:param factor: True or False (None)
|
||||
:param distance: If 'factor' is True then distance is the factor
|
||||
:param join: The type of joining used by the Shapely buffer method. Can be: round, square and bevel
|
||||
:param factor: True or False (None)
|
||||
:return:
|
||||
"""
|
||||
log.debug("parseGerber.Gerber.buffer()")
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
# ############################################################
|
||||
|
||||
from camlib import arc, three_point_circle
|
||||
import FlatCAMApp
|
||||
|
||||
import numpy as np
|
||||
import re
|
||||
|
@ -19,6 +18,7 @@ import sys
|
|||
from shapely.ops import unary_union
|
||||
from shapely.geometry import LineString, Point
|
||||
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import gettext
|
||||
import builtins
|
||||
|
@ -180,7 +180,7 @@ class HPGL2:
|
|||
for gline in glines:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
line_num += 1
|
||||
self.source_file += gline + '\n'
|
||||
|
@ -304,7 +304,7 @@ class HPGL2:
|
|||
(_("Coordinates missing, line ignored"), str(gline)))
|
||||
|
||||
if current_x is not None and current_y is not None:
|
||||
radius = match.group(1)
|
||||
radius = float(match.group(1))
|
||||
geo = Point((current_x, current_y)).buffer(radius, int(self.steps_per_circle))
|
||||
geo_line = geo.exterior
|
||||
self.tools[current_tool]['solid_geometry'].append(geo_line)
|
||||
|
|
|
@ -382,7 +382,7 @@ class AlignObjects(FlatCAMTool):
|
|||
def check_points(self):
|
||||
if len(self.clicked_points) == 1:
|
||||
self.app.inform.emit('%s: %s. %s' % (
|
||||
_("First Point"), _("Click on the DESTINATION point."), _(" Or right click to cancel.")))
|
||||
_("First Point"), _("Click on the DESTINATION point."), _("Or right click to cancel.")))
|
||||
self.target_obj = self.aligner_obj
|
||||
self.reset_color()
|
||||
self.set_color()
|
||||
|
@ -397,14 +397,14 @@ class AlignObjects(FlatCAMTool):
|
|||
return
|
||||
else:
|
||||
self.app.inform.emit('%s: %s. %s' % (
|
||||
_("Second Point"), _("Click on the START point."), _(" Or right click to cancel.")))
|
||||
_("Second Point"), _("Click on the START point."), _("Or right click to cancel.")))
|
||||
self.target_obj = self.aligned_obj
|
||||
self.reset_color()
|
||||
self.set_color()
|
||||
|
||||
if len(self.clicked_points) == 3:
|
||||
self.app.inform.emit('%s: %s. %s' % (
|
||||
_("Second Point"), _("Click on the DESTINATION point."), _(" Or right click to cancel.")))
|
||||
_("Second Point"), _("Click on the DESTINATION point."), _("Or right click to cancel.")))
|
||||
self.target_obj = self.aligner_obj
|
||||
self.reset_color()
|
||||
self.set_color()
|
||||
|
|
|
@ -7,10 +7,9 @@
|
|||
|
||||
from PyQt5 import QtWidgets, QtCore
|
||||
|
||||
import FlatCAMApp
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, RadioSet, FCEntry, FCComboBox
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry, FlatCAMExcellon
|
||||
|
||||
import shapely.geometry.base as base
|
||||
from shapely.ops import cascaded_union, unary_union
|
||||
|
@ -994,7 +993,7 @@ class ToolCopperThieving(FlatCAMTool):
|
|||
for pol in app_obj.grb_object.solid_geometry:
|
||||
if app_obj.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
clearance_geometry.append(
|
||||
pol.buffer(c_val, int(int(app_obj.geo_steps_per_circle) / 4))
|
||||
|
@ -1073,7 +1072,7 @@ class ToolCopperThieving(FlatCAMTool):
|
|||
for poly in working_obj:
|
||||
if app_obj.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
|
||||
except TypeError:
|
||||
geo_buff_list.append(working_obj.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
|
||||
|
@ -1082,7 +1081,7 @@ class ToolCopperThieving(FlatCAMTool):
|
|||
else: # ref_selected == 'box'
|
||||
geo_n = working_obj.solid_geometry
|
||||
|
||||
if isinstance(working_obj, FlatCAMGeometry):
|
||||
if working_obj.kind == 'geometry':
|
||||
try:
|
||||
__ = iter(geo_n)
|
||||
except Exception as e:
|
||||
|
@ -1093,11 +1092,11 @@ class ToolCopperThieving(FlatCAMTool):
|
|||
for poly in geo_n:
|
||||
if app_obj.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
|
||||
|
||||
bounding_box = cascaded_union(geo_buff_list)
|
||||
elif isinstance(working_obj, FlatCAMGerber):
|
||||
elif working_obj.kind == 'gerber':
|
||||
geo_n = cascaded_union(geo_n).convex_hull
|
||||
bounding_box = cascaded_union(thieving_obj.solid_geometry).convex_hull.intersection(geo_n)
|
||||
bounding_box = bounding_box.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
|
||||
|
@ -1192,7 +1191,7 @@ class ToolCopperThieving(FlatCAMTool):
|
|||
for pol in app_obj.grb_object.solid_geometry:
|
||||
if app_obj.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
outline_geometry.append(
|
||||
pol.buffer(c_val+half_thick_line, int(int(app_obj.geo_steps_per_circle) / 4))
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, RadioSet, FCComboBox, OptionalInputSection, FCButton
|
||||
from FlatCAMObj import FlatCAMGerber
|
||||
|
||||
from shapely.geometry import box, MultiPolygon, Polygon, LineString, LinearRing
|
||||
from shapely.ops import cascaded_union, unary_union
|
||||
|
@ -270,7 +269,7 @@ class CutOut(FlatCAMTool):
|
|||
form_layout_2.addRow(gaps_label, self.gaps)
|
||||
|
||||
# Buttons
|
||||
self.ff_cutout_object_btn = QtWidgets.QPushButton(_("Generate Freeform Geometry"))
|
||||
self.ff_cutout_object_btn = FCButton(_("Generate Freeform Geometry"))
|
||||
self.ff_cutout_object_btn.setToolTip(
|
||||
_("Cutout the selected object.\n"
|
||||
"The cutout shape can be of any shape.\n"
|
||||
|
@ -284,7 +283,7 @@ class CutOut(FlatCAMTool):
|
|||
""")
|
||||
grid0.addWidget(self.ff_cutout_object_btn, 20, 0, 1, 2)
|
||||
|
||||
self.rect_cutout_object_btn = QtWidgets.QPushButton(_("Generate Rectangular Geometry"))
|
||||
self.rect_cutout_object_btn = FCButton(_("Generate Rectangular Geometry"))
|
||||
self.rect_cutout_object_btn.setToolTip(
|
||||
_("Cutout the selected object.\n"
|
||||
"The resulting cutout shape is\n"
|
||||
|
@ -335,7 +334,7 @@ class CutOut(FlatCAMTool):
|
|||
|
||||
# form_layout_3.addRow(e_lab_0)
|
||||
|
||||
self.man_geo_creation_btn = QtWidgets.QPushButton(_("Generate Manual Geometry"))
|
||||
self.man_geo_creation_btn = FCButton(_("Generate Manual Geometry"))
|
||||
self.man_geo_creation_btn.setToolTip(
|
||||
_("If the object to be cutout is a Gerber\n"
|
||||
"first create a Geometry that surrounds it,\n"
|
||||
|
@ -350,7 +349,7 @@ class CutOut(FlatCAMTool):
|
|||
""")
|
||||
grid0.addWidget(self.man_geo_creation_btn, 24, 0, 1, 2)
|
||||
|
||||
self.man_gaps_creation_btn = QtWidgets.QPushButton(_("Manual Add Bridge Gaps"))
|
||||
self.man_gaps_creation_btn = FCButton(_("Manual Add Bridge Gaps"))
|
||||
self.man_gaps_creation_btn.setToolTip(
|
||||
_("Use the left mouse button (LMB) click\n"
|
||||
"to create a bridge gap to separate the PCB from\n"
|
||||
|
@ -369,7 +368,7 @@ class CutOut(FlatCAMTool):
|
|||
self.layout.addStretch()
|
||||
|
||||
# ## Reset Tool
|
||||
self.reset_button = QtWidgets.QPushButton(_("Reset Tool"))
|
||||
self.reset_button = FCButton(_("Reset Tool"))
|
||||
self.reset_button.setToolTip(
|
||||
_("Will reset the tool parameters.")
|
||||
)
|
||||
|
@ -525,7 +524,7 @@ class CutOut(FlatCAMTool):
|
|||
def geo_init(geo_obj, app_obj):
|
||||
solid_geo = []
|
||||
|
||||
if isinstance(cutout_obj, FlatCAMGerber):
|
||||
if cutout_obj.kind == 'gerber':
|
||||
if isinstance(cutout_obj.solid_geometry, list):
|
||||
cutout_obj.solid_geometry = MultiPolygon(cutout_obj.solid_geometry)
|
||||
|
||||
|
@ -542,12 +541,12 @@ class CutOut(FlatCAMTool):
|
|||
|
||||
def cutout_handler(geom):
|
||||
# Get min and max data for each object as we just cut rectangles across X or Y
|
||||
xmin, ymin, xmax, ymax = recursive_bounds(geom)
|
||||
xxmin, yymin, xxmax, yymax = recursive_bounds(geom)
|
||||
|
||||
px = 0.5 * (xmin + xmax) + margin
|
||||
py = 0.5 * (ymin + ymax) + margin
|
||||
lenx = (xmax - xmin) + (margin * 2)
|
||||
leny = (ymax - ymin) + (margin * 2)
|
||||
px = 0.5 * (xxmin + xxmax) + margin
|
||||
py = 0.5 * (yymin + yymax) + margin
|
||||
lenx = (xxmax - xxmin) + (margin * 2)
|
||||
leny = (yymax - yymin) + (margin * 2)
|
||||
|
||||
proc_geometry = []
|
||||
if gaps == 'None':
|
||||
|
@ -555,41 +554,41 @@ class CutOut(FlatCAMTool):
|
|||
else:
|
||||
if gaps == '8' or gaps == '2LR':
|
||||
geom = self.subtract_poly_from_geo(geom,
|
||||
xmin - gapsize, # botleft_x
|
||||
xxmin - gapsize, # botleft_x
|
||||
py - gapsize + leny / 4, # botleft_y
|
||||
xmax + gapsize, # topright_x
|
||||
xxmax + gapsize, # topright_x
|
||||
py + gapsize + leny / 4) # topright_y
|
||||
geom = self.subtract_poly_from_geo(geom,
|
||||
xmin - gapsize,
|
||||
xxmin - gapsize,
|
||||
py - gapsize - leny / 4,
|
||||
xmax + gapsize,
|
||||
xxmax + gapsize,
|
||||
py + gapsize - leny / 4)
|
||||
|
||||
if gaps == '8' or gaps == '2TB':
|
||||
geom = self.subtract_poly_from_geo(geom,
|
||||
px - gapsize + lenx / 4,
|
||||
ymin - gapsize,
|
||||
yymin - gapsize,
|
||||
px + gapsize + lenx / 4,
|
||||
ymax + gapsize)
|
||||
yymax + gapsize)
|
||||
geom = self.subtract_poly_from_geo(geom,
|
||||
px - gapsize - lenx / 4,
|
||||
ymin - gapsize,
|
||||
yymin - gapsize,
|
||||
px + gapsize - lenx / 4,
|
||||
ymax + gapsize)
|
||||
yymax + gapsize)
|
||||
|
||||
if gaps == '4' or gaps == 'LR':
|
||||
geom = self.subtract_poly_from_geo(geom,
|
||||
xmin - gapsize,
|
||||
xxmin - gapsize,
|
||||
py - gapsize,
|
||||
xmax + gapsize,
|
||||
xxmax + gapsize,
|
||||
py + gapsize)
|
||||
|
||||
if gaps == '4' or gaps == 'TB':
|
||||
geom = self.subtract_poly_from_geo(geom,
|
||||
px - gapsize,
|
||||
ymin - gapsize,
|
||||
yymin - gapsize,
|
||||
px + gapsize,
|
||||
ymax + gapsize)
|
||||
yymax + gapsize)
|
||||
|
||||
try:
|
||||
for g in geom:
|
||||
|
@ -603,7 +602,7 @@ class CutOut(FlatCAMTool):
|
|||
object_geo = unary_union(object_geo)
|
||||
|
||||
# for geo in object_geo:
|
||||
if isinstance(cutout_obj, FlatCAMGerber):
|
||||
if cutout_obj.kind == 'gerber':
|
||||
if isinstance(object_geo, MultiPolygon):
|
||||
x0, y0, x1, y1 = object_geo.bounds
|
||||
object_geo = box(x0, y0, x1, y1)
|
||||
|
@ -623,7 +622,7 @@ class CutOut(FlatCAMTool):
|
|||
object_geo = [object_geo]
|
||||
|
||||
for geom_struct in object_geo:
|
||||
if isinstance(cutout_obj, FlatCAMGerber):
|
||||
if cutout_obj.kind == 'gerber':
|
||||
if margin >= 0:
|
||||
geom_struct = (geom_struct.buffer(margin + abs(dia / 2))).exterior
|
||||
else:
|
||||
|
@ -775,7 +774,7 @@ class CutOut(FlatCAMTool):
|
|||
|
||||
# if Gerber create a buffer at a distance
|
||||
# if Geometry then cut through the geometry
|
||||
if isinstance(cutout_obj, FlatCAMGerber):
|
||||
if cutout_obj.kind == 'gerber':
|
||||
if margin >= 0:
|
||||
geo = geo.buffer(margin + abs(dia / 2))
|
||||
else:
|
||||
|
@ -909,7 +908,7 @@ class CutOut(FlatCAMTool):
|
|||
"Select one and try again."))
|
||||
return
|
||||
|
||||
if not isinstance(cutout_obj, FlatCAMGerber):
|
||||
if cutout_obj.kind != 'gerber':
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_("The selected object has to be of Gerber type.\n"
|
||||
"Select a Gerber file and try again."))
|
||||
|
@ -988,11 +987,11 @@ class CutOut(FlatCAMTool):
|
|||
|
||||
if self.app.is_legacy is False:
|
||||
event_pos = event.pos
|
||||
event_is_dragging = event.is_dragging
|
||||
# event_is_dragging = event.is_dragging
|
||||
right_button = 2
|
||||
else:
|
||||
event_pos = (event.xdata, event.ydata)
|
||||
event_is_dragging = self.app.plotcanvas.is_dragging
|
||||
# event_is_dragging = self.app.plotcanvas.is_dragging
|
||||
right_button = 3
|
||||
|
||||
try:
|
||||
|
@ -1038,11 +1037,11 @@ class CutOut(FlatCAMTool):
|
|||
if self.app.is_legacy is False:
|
||||
event_pos = event.pos
|
||||
event_is_dragging = event.is_dragging
|
||||
right_button = 2
|
||||
# right_button = 2
|
||||
else:
|
||||
event_pos = (event.xdata, event.ydata)
|
||||
event_is_dragging = self.app.plotcanvas.is_dragging
|
||||
right_button = 3
|
||||
# right_button = 3
|
||||
|
||||
try:
|
||||
x = float(event_pos[0])
|
||||
|
@ -1159,13 +1158,17 @@ class CutOut(FlatCAMTool):
|
|||
if '+' in key_string:
|
||||
mod, __, key_text = key_string.rpartition('+')
|
||||
if mod.lower() == 'ctrl':
|
||||
modifiers = QtCore.Qt.ControlModifier
|
||||
# modifiers = QtCore.Qt.ControlModifier
|
||||
pass
|
||||
elif mod.lower() == 'alt':
|
||||
modifiers = QtCore.Qt.AltModifier
|
||||
# modifiers = QtCore.Qt.AltModifier
|
||||
pass
|
||||
elif mod.lower() == 'shift':
|
||||
modifiers = QtCore.Qt.ShiftModifier
|
||||
# modifiers = QtCore.Qt.ShiftModifier
|
||||
pass
|
||||
else:
|
||||
modifiers = QtCore.Qt.NoModifier
|
||||
# modifiers = QtCore.Qt.NoModifier
|
||||
pass
|
||||
key = QtGui.QKeySequence(key_text)
|
||||
# events from Vispy are of type KeyEvent
|
||||
else:
|
||||
|
@ -1203,7 +1206,8 @@ class CutOut(FlatCAMTool):
|
|||
geo = self.cutting_geo(pos=(l_x, l_y))
|
||||
self.draw_utility_geometry(geo=geo)
|
||||
|
||||
def subtract_poly_from_geo(self, solid_geo, x0, y0, x1, y1):
|
||||
@staticmethod
|
||||
def subtract_poly_from_geo(solid_geo, x0, y0, x1, y1):
|
||||
"""
|
||||
Subtract polygon made from points from the given object.
|
||||
This only operates on the paths in the original geometry,
|
||||
|
@ -1270,8 +1274,9 @@ def flatten(geometry):
|
|||
|
||||
def recursive_bounds(geometry):
|
||||
"""
|
||||
Returns coordinates of rectangular bounds
|
||||
of geometry: (xmin, ymin, xmax, ymax).
|
||||
|
||||
:param geometry: a iterable object that holds geometry
|
||||
:return: Returns coordinates of rectangular bounds of geometry: (xmin, ymin, xmax, ymax).
|
||||
"""
|
||||
|
||||
# now it can get bounds for nested lists of objects
|
||||
|
|
|
@ -3,7 +3,6 @@ from PyQt5 import QtWidgets, QtCore
|
|||
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, EvalEntry, FCEntry, FCButton, FCComboBox
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMExcellon, FlatCAMGeometry
|
||||
|
||||
from numpy import Inf
|
||||
|
||||
|
@ -192,7 +191,7 @@ class DblSidedTool(FlatCAMTool):
|
|||
# Add a reference
|
||||
self.add_point_button = QtWidgets.QPushButton(_("Add"))
|
||||
self.add_point_button.setToolTip(
|
||||
_("Add the coordinates in format <b>(x, y)</b> through which the mirroring axis \n "
|
||||
_("Add the coordinates in format <b>(x, y)</b> through which the mirroring axis\n "
|
||||
"selected in 'MIRROR AXIS' pass.\n"
|
||||
"The (x, y) coordinates are captured by pressing SHIFT key\n"
|
||||
"and left mouse button click on canvas or you can enter the coordinates manually.")
|
||||
|
@ -658,7 +657,7 @@ class DblSidedTool(FlatCAMTool):
|
|||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ..."))
|
||||
return
|
||||
|
||||
if not isinstance(fcobj, FlatCAMGerber):
|
||||
if fcobj.kind != 'gerber':
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Only Gerber, Excellon and Geometry objects can be mirrored."))
|
||||
return
|
||||
|
||||
|
@ -701,7 +700,7 @@ class DblSidedTool(FlatCAMTool):
|
|||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Excellon object loaded ..."))
|
||||
return
|
||||
|
||||
if not isinstance(fcobj, FlatCAMExcellon):
|
||||
if fcobj.kind != 'excellon':
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Only Gerber, Excellon and Geometry objects can be mirrored."))
|
||||
return
|
||||
|
||||
|
@ -745,7 +744,7 @@ class DblSidedTool(FlatCAMTool):
|
|||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Geometry object loaded ..."))
|
||||
return
|
||||
|
||||
if not isinstance(fcobj, FlatCAMGeometry):
|
||||
if fcobj.kind != 'geometry':
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Only Gerber, Excellon and Geometry objects can be mirrored."))
|
||||
return
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
from PyQt5 import QtWidgets, QtCore
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
from flatcamGUI.VisPyVisuals import *
|
||||
from FlatCAMObj import FlatCAMGerber
|
||||
|
||||
from copy import copy
|
||||
import logging
|
||||
|
@ -128,7 +127,7 @@ class ToolMove(FlatCAMTool):
|
|||
pos_canvas = self.app.plotcanvas.translate_coords(event_pos)
|
||||
|
||||
# if GRID is active we need to get the snapped positions
|
||||
if self.app.grid_status() == True:
|
||||
if self.app.grid_status():
|
||||
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
||||
else:
|
||||
pos = pos_canvas
|
||||
|
@ -148,7 +147,7 @@ class ToolMove(FlatCAMTool):
|
|||
self.delete_shape()
|
||||
|
||||
# if GRID is active we need to get the snapped positions
|
||||
if self.app.grid_status() == True:
|
||||
if self.app.grid_status():
|
||||
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
||||
else:
|
||||
pos = pos_canvas
|
||||
|
@ -171,7 +170,7 @@ class ToolMove(FlatCAMTool):
|
|||
# remove any mark aperture shape that may be displayed
|
||||
for sel_obj in obj_list:
|
||||
# if the Gerber mark shapes are enabled they need to be disabled before move
|
||||
if isinstance(sel_obj, FlatCAMGerber):
|
||||
if sel_obj.kind == 'gerber':
|
||||
sel_obj.ui.aperture_table_visibility_cb.setChecked(False)
|
||||
|
||||
try:
|
||||
|
@ -198,8 +197,8 @@ class ToolMove(FlatCAMTool):
|
|||
elif sel_obj.kind == 'excellon':
|
||||
sel_obj.source_file = self.app.export_excellon(
|
||||
obj_name=out_name, filename=None, local_use=sel_obj, use_thread=False)
|
||||
except Exception as e:
|
||||
log.debug('[ERROR_NOTCL] %s --> %s' % ('ToolMove.on_left_click()', str(e)))
|
||||
except Exception as err:
|
||||
log.debug('[ERROR_NOTCL] %s --> %s' % ('ToolMove.on_left_click()', str(err)))
|
||||
return "fail"
|
||||
|
||||
# time to plot the moved objects
|
||||
|
@ -249,7 +248,7 @@ class ToolMove(FlatCAMTool):
|
|||
pos_canvas = self.app.plotcanvas.translate_coords((x, y))
|
||||
|
||||
# if GRID is active we need to get the snapped positions
|
||||
if self.app.grid_status() == True:
|
||||
if self.app.grid_status():
|
||||
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
|
||||
else:
|
||||
pos = pos_canvas
|
||||
|
|
|
@ -12,7 +12,7 @@ from flatcamGUI.GUIElements import FCCheckBox, FCDoubleSpinner, RadioSet, FCTabl
|
|||
FCComboBox, OptionalInputSection
|
||||
from flatcamParsers.ParseGerber import Gerber
|
||||
|
||||
import FlatCAMApp
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
|
||||
from copy import deepcopy
|
||||
|
||||
|
@ -1987,7 +1987,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
for poly in env_obj:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
geo_buff_list.append(poly.buffer(distance=ncc_margin, join_style=base.JOIN_STYLE.mitre))
|
||||
bounding_box = cascaded_union(geo_buff_list)
|
||||
elif ncc_select == _("Reference Object"):
|
||||
|
@ -1996,7 +1996,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
for poly in env_obj:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
geo_buff_list.append(poly.buffer(distance=ncc_margin, join_style=base.JOIN_STYLE.mitre))
|
||||
|
||||
bounding_box = cascaded_union(geo_buff_list)
|
||||
|
@ -2090,7 +2090,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
if isinstance(geo_elem, Polygon):
|
||||
for ring in self.poly2rings(geo_elem):
|
||||
|
@ -2263,7 +2263,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
# ##########################################################################################
|
||||
def gen_clear_area(geo_obj, app_obj):
|
||||
assert geo_obj.kind == 'geometry', \
|
||||
"Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
|
||||
"Initializer expected a GeometryObject, got %s" % type(geo_obj)
|
||||
|
||||
# provide the app with a way to process the GUI events when in a blocking loop
|
||||
if not run_threaded:
|
||||
|
@ -2312,7 +2312,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
log.debug("Starting geometry processing for tool: %s" % str(tool))
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# provide the app with a way to process the GUI events when in a blocking loop
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
@ -2377,7 +2377,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# clean the polygon
|
||||
p = p.buffer(0)
|
||||
|
@ -2551,7 +2551,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
# ###########################################################################################
|
||||
def gen_clear_area_rest(geo_obj, app_obj):
|
||||
assert geo_obj.kind == 'geometry', \
|
||||
"Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
|
||||
"Initializer expected a GeometryObject, got %s" % type(geo_obj)
|
||||
|
||||
log.debug("NCC Tool. Rest machining copper clearing task started.")
|
||||
app_obj.inform.emit('_(NCC Tool. Rest machining copper clearing task started.')
|
||||
|
@ -2595,7 +2595,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
log.debug("Starting geometry processing for tool: %s" % str(tool))
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# provide the app with a way to process the GUI events when in a blocking loop
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
@ -2644,7 +2644,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
try:
|
||||
area = area.difference(poly)
|
||||
except Exception:
|
||||
|
@ -2674,7 +2674,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
for p in area.geoms:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# clean the polygon
|
||||
p = p.buffer(0)
|
||||
|
@ -2753,7 +2753,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# check if there is a geometry at all in the cleared geometry
|
||||
if cleared_geo:
|
||||
|
@ -2771,7 +2771,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
for p in cleared_area:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
poly = p.buffer(buffer_value)
|
||||
cleared_by_last_tool.append(poly)
|
||||
|
@ -2836,7 +2836,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
app_obj.new_object("geometry", name, gen_clear_area_rest)
|
||||
else:
|
||||
app_obj.new_object("geometry", name, gen_clear_area)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
if run_threaded:
|
||||
proc.done()
|
||||
return
|
||||
|
@ -2999,7 +2999,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
for poly in geo_n:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
geo_buff_list.append(poly.buffer(distance=ncc_margin, join_style=base.JOIN_STYLE.mitre))
|
||||
|
||||
bounding_box = cascaded_union(geo_buff_list)
|
||||
|
@ -3017,7 +3017,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
for poly in geo_n:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
geo_buff_list.append(poly.buffer(distance=ncc_margin, join_style=base.JOIN_STYLE.mitre))
|
||||
|
||||
bounding_box = cascaded_union(geo_buff_list)
|
||||
|
@ -3045,7 +3045,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
# ##########################################################################################
|
||||
def gen_clear_area(geo_obj, app_obj):
|
||||
assert geo_obj.kind == 'geometry', \
|
||||
"Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
|
||||
"Initializer expected a GeometryObject, got %s" % type(geo_obj)
|
||||
|
||||
# provide the app with a way to process the GUI events when in a blocking loop
|
||||
if not run_threaded:
|
||||
|
@ -3141,7 +3141,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
if isinstance(geo_elem, Polygon):
|
||||
for ring in self.poly2rings(geo_elem):
|
||||
|
@ -3242,7 +3242,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
log.debug("Starting geometry processing for tool: %s" % str(tool))
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# provide the app with a way to process the GUI events when in a blocking loop
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
@ -3283,7 +3283,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# clean the polygon
|
||||
p = p.buffer(0)
|
||||
|
@ -3446,7 +3446,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
# ###########################################################################################
|
||||
def gen_clear_area_rest(geo_obj, app_obj):
|
||||
assert geo_obj.kind == 'geometry', \
|
||||
"Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
|
||||
"Initializer expected a GeometryObject, got %s" % type(geo_obj)
|
||||
|
||||
log.debug("NCC Tool. Rest machining copper clearing task started.")
|
||||
app_obj.inform.emit('_(NCC Tool. Rest machining copper clearing task started.')
|
||||
|
@ -3520,7 +3520,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
if isinstance(geo_elem, Polygon):
|
||||
for ring in self.poly2rings(geo_elem):
|
||||
|
@ -3614,7 +3614,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
if type(empty) is Polygon:
|
||||
empty = MultiPolygon([empty])
|
||||
|
@ -3628,7 +3628,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
while sorted_tools:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
tool = sorted_tools.pop(0)
|
||||
log.debug("Starting geometry processing for tool: %s" % str(tool))
|
||||
|
@ -3648,7 +3648,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
try:
|
||||
area = area.difference(poly_r)
|
||||
except Exception:
|
||||
|
@ -3678,7 +3678,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
for p in area.geoms:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# clean the polygon
|
||||
p = p.buffer(0)
|
||||
|
@ -3754,7 +3754,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# check if there is a geometry at all in the cleared geometry
|
||||
if cleared_geo:
|
||||
|
@ -3772,7 +3772,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
for p in cleared_area:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
r_poly = p.buffer(buffer_value)
|
||||
cleared_by_last_tool.append(r_poly)
|
||||
|
@ -3833,7 +3833,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
app_obj.new_object("geometry", name, gen_clear_area_rest, plot=plot)
|
||||
else:
|
||||
app_obj.new_object("geometry", name, gen_clear_area, plot=plot)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
if run_threaded:
|
||||
proc.done()
|
||||
return
|
||||
|
@ -3887,7 +3887,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
boundary = boundary.difference(el)
|
||||
pol_nr += 1
|
||||
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
|
||||
|
|
|
@ -9,8 +9,7 @@ from PyQt5 import QtWidgets, QtCore, QtGui
|
|||
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
from flatcamGUI.GUIElements import OptionalHideInputSection, FCTextArea, FCEntry, FCSpinner, FCCheckBox, FCComboBox
|
||||
from FlatCAMObj import FlatCAMGerber
|
||||
import FlatCAMApp
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
|
||||
from shapely.geometry import MultiPolygon
|
||||
from shapely.ops import nearest_points
|
||||
|
@ -343,7 +342,7 @@ class ToolOptimal(FlatCAMTool):
|
|||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ..."))
|
||||
return
|
||||
|
||||
if not isinstance(fcobj, FlatCAMGerber):
|
||||
if fcobj.kind != 'gerber':
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Only Gerber objects can be evaluated."))
|
||||
return
|
||||
|
||||
|
@ -365,7 +364,7 @@ class ToolOptimal(FlatCAMTool):
|
|||
for geo_el in fcobj.apertures[ap]['geometry']:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
if 'solid' in geo_el and geo_el['solid'] is not None and geo_el['solid'].is_valid:
|
||||
total_geo.append(geo_el['solid'])
|
||||
|
@ -395,7 +394,7 @@ class ToolOptimal(FlatCAMTool):
|
|||
for s_geo in total_geo[idx:]:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# minimize the number of distances by not taking into considerations those that are too small
|
||||
dist = geo.distance(s_geo)
|
||||
|
@ -459,7 +458,7 @@ class ToolOptimal(FlatCAMTool):
|
|||
log.debug("ToolOptimal.on_locate_position() --> first try %s" % str(e))
|
||||
self.app.inform.emit("[ERROR_NOTCL] The selected text is no valid location in the format "
|
||||
"((x0, y0), (x1, y1)).")
|
||||
return 'fail'
|
||||
return
|
||||
|
||||
try:
|
||||
loc_1 = loc[0]
|
||||
|
@ -471,7 +470,7 @@ class ToolOptimal(FlatCAMTool):
|
|||
self.app.on_jump_to(custom_location=loc)
|
||||
except Exception as e:
|
||||
log.debug("ToolOptimal.on_locate_position() --> sec try %s" % str(e))
|
||||
return 'fail'
|
||||
return
|
||||
|
||||
def on_update_text(self, data):
|
||||
txt = ''
|
||||
|
@ -567,12 +566,12 @@ class ToolOptimal(FlatCAMTool):
|
|||
if self.selected_locations_text != '':
|
||||
loc = eval(self.selected_locations_text)
|
||||
else:
|
||||
return 'fail'
|
||||
return
|
||||
except Exception as e:
|
||||
log.debug("ToolOptimal.on_locate_sec_position() --> first try %s" % str(e))
|
||||
self.app.inform.emit("[ERROR_NOTCL] The selected text is no valid location in the format "
|
||||
"((x0, y0), (x1, y1)).")
|
||||
return 'fail'
|
||||
return
|
||||
|
||||
try:
|
||||
loc_1 = loc[0]
|
||||
|
@ -584,7 +583,7 @@ class ToolOptimal(FlatCAMTool):
|
|||
self.app.on_jump_to(custom_location=loc)
|
||||
except Exception as e:
|
||||
log.debug("ToolOptimal.on_locate_sec_position() --> sec try %s" % str(e))
|
||||
return 'fail'
|
||||
return
|
||||
|
||||
def reset_fields(self):
|
||||
self.gerber_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
from PyQt5 import QtWidgets, QtCore
|
||||
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
import FlatCAMApp
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
|
||||
from shapely.geometry import Point, Polygon, LineString, MultiPolygon
|
||||
from shapely.ops import unary_union
|
||||
|
@ -190,7 +190,7 @@ class ToolPDF(FlatCAMTool):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
with self.app.proc_container.new(_("Parsing PDF file ...")):
|
||||
with open(filename, "rb") as f:
|
||||
|
@ -200,7 +200,7 @@ class ToolPDF(FlatCAMTool):
|
|||
for s in re.findall(self.stream_re, pdf):
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
stream_nr += 1
|
||||
log.debug(" PDF STREAM: %d\n" % stream_nr)
|
||||
|
@ -291,7 +291,7 @@ class ToolPDF(FlatCAMTool):
|
|||
def layer_rendering_as_gerber(self, filename, ap_dict, layer_nr):
|
||||
outname = filename.split('/')[-1].split('\\')[-1] + "_%s" % str(layer_nr)
|
||||
|
||||
def obj_init(grb_obj, app_obj):
|
||||
def obj_init(grb_obj):
|
||||
|
||||
grb_obj.apertures = ap_dict
|
||||
|
||||
|
@ -404,7 +404,7 @@ class ToolPDF(FlatCAMTool):
|
|||
for object_name in self.pdf_parsed:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
filename = deepcopy(self.pdf_parsed[object_name]['filename'])
|
||||
pdf_content = deepcopy(self.pdf_parsed[object_name]['pdf'])
|
||||
|
@ -412,7 +412,7 @@ class ToolPDF(FlatCAMTool):
|
|||
for k in pdf_content:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
ap_dict = pdf_content[k]
|
||||
if ap_dict:
|
||||
|
@ -493,7 +493,7 @@ class ToolPDF(FlatCAMTool):
|
|||
for pline in lines:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
line_nr += 1
|
||||
log.debug("line %d: %s" % (line_nr, pline))
|
||||
|
@ -868,7 +868,6 @@ class ToolPDF(FlatCAMTool):
|
|||
new_el['solid'] = pdf_geo
|
||||
new_el['follow'] = pdf_geo.exterior
|
||||
apertures_dict[copy(found_aperture)]['geometry'].append(deepcopy(new_el))
|
||||
found_aperture = None
|
||||
else:
|
||||
if str(aperture) in apertures_dict.keys():
|
||||
aperture += 1
|
||||
|
@ -1231,7 +1230,6 @@ class ToolPDF(FlatCAMTool):
|
|||
new_el['solid'] = pdf_geo
|
||||
new_el['follow'] = pdf_geo.exterior
|
||||
apertures_dict[copy(found_aperture)]['geometry'].append(deepcopy(new_el))
|
||||
found_aperture = None
|
||||
else:
|
||||
if str(aperture) in apertures_dict.keys():
|
||||
aperture += 1
|
||||
|
@ -1355,7 +1353,7 @@ class ToolPDF(FlatCAMTool):
|
|||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
return object_dict
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ from copy import deepcopy
|
|||
from flatcamParsers.ParseGerber import Gerber
|
||||
from camlib import Geometry, FlatCAMRTreeStorage
|
||||
from flatcamGUI.GUIElements import FCTable, FCDoubleSpinner, FCCheckBox, FCInputDialog, RadioSet, FCButton, FCComboBox
|
||||
import FlatCAMApp
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
|
||||
from shapely.geometry import base, Polygon, MultiPolygon, LinearRing, Point
|
||||
from shapely.ops import cascaded_union, unary_union, linemerge
|
||||
|
@ -1836,7 +1836,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
contour=cont,
|
||||
connect=conn,
|
||||
prog_plot=prog_plot)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
return "fail"
|
||||
except Exception as ee:
|
||||
log.debug("ToolPaint.paint_polygon_worker() Standard --> %s" % str(ee))
|
||||
|
@ -1850,7 +1850,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
contour=cont,
|
||||
connect=conn,
|
||||
prog_plot=prog_plot)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
return "fail"
|
||||
except Exception as ee:
|
||||
log.debug("ToolPaint.paint_polygon_worker() Seed --> %s" % str(ee))
|
||||
|
@ -1864,7 +1864,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
contour=cont,
|
||||
connect=conn,
|
||||
prog_plot=prog_plot)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
return "fail"
|
||||
except Exception as ee:
|
||||
log.debug("ToolPaint.paint_polygon_worker() Lines --> %s" % str(ee))
|
||||
|
@ -2015,7 +2015,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
# contour=cont,
|
||||
# connect=conn,
|
||||
# prog_plot=prog_plot)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
return "fail"
|
||||
except Exception as ee:
|
||||
log.debug("ToolPaint.paint_polygon_worker() Laser Lines --> %s" % str(ee))
|
||||
|
@ -2052,7 +2052,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
contour=cont,
|
||||
connect=conn,
|
||||
prog_plot=prog_plot)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
return "fail"
|
||||
except Exception as ee:
|
||||
log.debug("ToolPaint.paint_polygon_worker() Combo --> %s" % str(ee))
|
||||
|
@ -2199,7 +2199,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
geo_res = self.paint_polygon_worker(pp, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
prog_plot=prog_plot)
|
||||
|
@ -2217,7 +2217,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
geo_res = self.paint_polygon_worker(poly_buf, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
|
@ -2230,7 +2230,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
for x in cp:
|
||||
total_geometry += list(x.get_objects())
|
||||
final_solid_geometry += total_geometry
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
return "fail"
|
||||
except Exception as e:
|
||||
log.debug("Could not Paint the polygons. %s" % str(e))
|
||||
|
@ -2305,7 +2305,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
def job_thread(app_obj):
|
||||
try:
|
||||
ret = app_obj.new_object("geometry", name, job_init, plot=plot)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
proc.done()
|
||||
return
|
||||
except Exception as er:
|
||||
|
@ -2376,7 +2376,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
"""
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
if geometry is None:
|
||||
return
|
||||
|
@ -2517,7 +2517,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
geo_res = self.paint_polygon_worker(pp, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
|
@ -2542,7 +2542,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
geo_res = self.paint_polygon_worker(poly_buf, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
|
@ -2705,7 +2705,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
geo_res = self.paint_polygon_worker(pp, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
prog_plot=prog_plot)
|
||||
|
@ -2723,7 +2723,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
geo_res = self.paint_polygon_worker(poly_buf, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
|
@ -2735,7 +2735,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
for x in cp:
|
||||
cleared_geo += list(x.get_objects())
|
||||
final_solid_geometry += cleared_geo
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
return "fail"
|
||||
except Exception as e:
|
||||
log.debug("Could not Paint the polygons. %s" % str(e))
|
||||
|
@ -2815,7 +2815,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
ret = app_obj.new_object("geometry", name, gen_paintarea_rest_machining, plot=plot)
|
||||
else:
|
||||
ret = app_obj.new_object("geometry", name, gen_paintarea, plot=plot)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
proc.done()
|
||||
return
|
||||
except Exception as err:
|
||||
|
@ -2873,7 +2873,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
"""
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
if geometry is None:
|
||||
return
|
||||
|
@ -3015,7 +3015,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
geo_res = self.paint_polygon_worker(pp, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
|
@ -3040,7 +3040,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
geo_res = self.paint_polygon_worker(poly_buf, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
|
@ -3193,7 +3193,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
geo_res = self.paint_polygon_worker(pp, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
|
@ -3218,7 +3218,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
geo_res = self.paint_polygon_worker(poly_buf, tooldiameter=tool_dia, over=over, conn=conn,
|
||||
cont=cont, paint_method=paint_method, obj=obj,
|
||||
|
@ -3312,7 +3312,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
|||
ret = app_obj.new_object("geometry", name, gen_paintarea_rest_machining, plot=plot)
|
||||
else:
|
||||
ret = app_obj.new_object("geometry", name, gen_paintarea, plot=plot)
|
||||
except FlatCAMApp.GracefulException:
|
||||
except grace:
|
||||
proc.done()
|
||||
return
|
||||
except Exception as err:
|
||||
|
|
|
@ -9,10 +9,8 @@ from PyQt5 import QtWidgets, QtGui, QtCore
|
|||
from FlatCAMTool import FlatCAMTool
|
||||
|
||||
from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet, FCCheckBox, OptionalInputSection, FCComboBox
|
||||
from FlatCAMObj import FlatCAMGeometry, FlatCAMGerber, FlatCAMExcellon
|
||||
import FlatCAMApp
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
from copy import deepcopy
|
||||
# from ObjectCollection import *
|
||||
import numpy as np
|
||||
|
||||
import shapely.affinity as affinity
|
||||
|
@ -480,13 +478,13 @@ class Panelize(FlatCAMTool):
|
|||
rows -= 1
|
||||
panel_lengthy = ((ymax - ymin) * rows) + (spacing_rows * (rows - 1))
|
||||
|
||||
if isinstance(panel_obj, FlatCAMExcellon) or isinstance(panel_obj, FlatCAMGeometry):
|
||||
if panel_obj.kind == 'excellon' or panel_obj.kind == 'geometry':
|
||||
# make a copy of the panelized Excellon or Geometry tools
|
||||
copied_tools = {}
|
||||
for tt, tt_val in list(panel_obj.tools.items()):
|
||||
copied_tools[tt] = deepcopy(tt_val)
|
||||
|
||||
if isinstance(panel_obj, FlatCAMGerber):
|
||||
if panel_obj.kind == 'gerber':
|
||||
# make a copy of the panelized Gerber apertures
|
||||
copied_apertures = {}
|
||||
for tt, tt_val in list(panel_obj.apertures.items()):
|
||||
|
@ -525,7 +523,7 @@ class Panelize(FlatCAMTool):
|
|||
for tool_dict in panel_obj.drills:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
point_offseted = affinity.translate(tool_dict['point'], currentx, currenty)
|
||||
obj_fin.drills.append(
|
||||
|
@ -550,7 +548,7 @@ class Panelize(FlatCAMTool):
|
|||
for tool_dict in panel_obj.slots:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
start_offseted = affinity.translate(tool_dict['start'], currentx, currenty)
|
||||
stop_offseted = affinity.translate(tool_dict['stop'], currentx, currenty)
|
||||
|
@ -600,20 +598,20 @@ class Panelize(FlatCAMTool):
|
|||
obj_fin.solid_geometry = []
|
||||
|
||||
# create the initial structure on which to create the panel
|
||||
if isinstance(panel_obj, FlatCAMGeometry):
|
||||
if panel_obj.kind == 'geometry':
|
||||
obj_fin.multigeo = panel_obj.multigeo
|
||||
obj_fin.tools = copied_tools
|
||||
if panel_obj.multigeo is True:
|
||||
for tool in panel_obj.tools:
|
||||
obj_fin.tools[tool]['solid_geometry'][:] = []
|
||||
elif isinstance(panel_obj, FlatCAMGerber):
|
||||
elif panel_obj.kind == 'gerber':
|
||||
obj_fin.apertures = copied_apertures
|
||||
for ap in obj_fin.apertures:
|
||||
obj_fin.apertures[ap]['geometry'] = []
|
||||
|
||||
# find the number of polygons in the source solid_geometry
|
||||
geo_len = 0
|
||||
if isinstance(panel_obj, FlatCAMGeometry):
|
||||
if panel_obj.kind == 'geometry':
|
||||
if panel_obj.multigeo is True:
|
||||
for tool in panel_obj.tools:
|
||||
try:
|
||||
|
@ -625,7 +623,7 @@ class Panelize(FlatCAMTool):
|
|||
geo_len = len(panel_obj.solid_geometry)
|
||||
except TypeError:
|
||||
geo_len = 1
|
||||
elif isinstance(panel_obj, FlatCAMGerber):
|
||||
elif panel_obj.kind == 'gerber':
|
||||
for ap in panel_obj.apertures:
|
||||
if 'geometry' in panel_obj.apertures[ap]:
|
||||
try:
|
||||
|
@ -641,12 +639,12 @@ class Panelize(FlatCAMTool):
|
|||
element += 1
|
||||
old_disp_number = 0
|
||||
|
||||
if isinstance(panel_obj, FlatCAMGeometry):
|
||||
if panel_obj.kind == 'geometry':
|
||||
if panel_obj.multigeo is True:
|
||||
for tool in panel_obj.tools:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
# geo = translate_recursion(panel_obj.tools[tool]['solid_geometry'])
|
||||
# if isinstance(geo, list):
|
||||
|
@ -678,7 +676,7 @@ class Panelize(FlatCAMTool):
|
|||
# obj_fin.solid_geometry.append(geo)
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
try:
|
||||
# calculate the number of polygons
|
||||
|
@ -690,7 +688,7 @@ class Panelize(FlatCAMTool):
|
|||
for geo_el in panel_obj.solid_geometry:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
trans_geo = translate_recursion(geo_el)
|
||||
obj_fin.solid_geometry.append(trans_geo)
|
||||
|
@ -715,13 +713,13 @@ class Panelize(FlatCAMTool):
|
|||
# obj_fin.solid_geometry.append(geo)
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
try:
|
||||
for geo_el in panel_obj.solid_geometry:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
trans_geo = translate_recursion(geo_el)
|
||||
obj_fin.solid_geometry.append(trans_geo)
|
||||
|
@ -732,7 +730,7 @@ class Panelize(FlatCAMTool):
|
|||
for apid in panel_obj.apertures:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
if 'geometry' in panel_obj.apertures[apid]:
|
||||
try:
|
||||
# calculate the number of polygons
|
||||
|
@ -743,7 +741,7 @@ class Panelize(FlatCAMTool):
|
|||
for el in panel_obj.apertures[apid]['geometry']:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
raise grace
|
||||
|
||||
new_el = {}
|
||||
if 'solid' in el:
|
||||
|
@ -786,7 +784,7 @@ class Panelize(FlatCAMTool):
|
|||
self.app.proc_container.update_view_text('')
|
||||
|
||||
self.app.inform.emit('%s: %d' % (_("Generating panel... Spawning copies"), (int(rows * columns))))
|
||||
if isinstance(panel_obj, FlatCAMExcellon):
|
||||
if panel_obj.kind == 'excellon':
|
||||
self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True)
|
||||
else:
|
||||
self.app.new_object(panel_type, self.outname, job_init_geometry, plot=True, autoselected=True)
|
||||
|
|
|
@ -142,7 +142,7 @@ class ToolPunchGerber(FlatCAMTool):
|
|||
"- Excellon Object-> the Excellon object drills center will serve as reference.\n"
|
||||
"- Fixed Diameter -> will try to use the pads center as reference adding fixed diameter holes.\n"
|
||||
"- Fixed Annular Ring -> will try to keep a set annular ring.\n"
|
||||
"- Proportional -> will make a Gerber punch hole having the diameter a percentage of the pad diameter.\n")
|
||||
"- Proportional -> will make a Gerber punch hole having the diameter a percentage of the pad diameter.")
|
||||
)
|
||||
self.method_punch = RadioSet(
|
||||
[
|
||||
|
@ -604,8 +604,8 @@ class ToolPunchGerber(FlatCAMTool):
|
|||
if grb_obj.apertures[apid]['type'] == 'C' and self.circular_cb.get_value():
|
||||
if punch_size >= float(grb_obj.apertures[apid]['size']):
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_(" Could not generate punched hole Gerber because the punch hole size"
|
||||
"is bigger than some of the apertures in the Gerber object."))
|
||||
_("Could not generate punched hole Gerber because the punch hole size"
|
||||
" is bigger than some of the apertures in the Gerber object."))
|
||||
return 'fail'
|
||||
else:
|
||||
for elem in grb_obj.apertures[apid]['geometry']:
|
||||
|
@ -617,7 +617,7 @@ class ToolPunchGerber(FlatCAMTool):
|
|||
punch_size >= float(grb_obj.apertures[apid]['height']):
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_("Could not generate punched hole Gerber because the punch hole size"
|
||||
"is bigger than some of the apertures in the Gerber object."))
|
||||
" is bigger than some of the apertures in the Gerber object."))
|
||||
return 'fail'
|
||||
elif round(float(grb_obj.apertures[apid]['width']), self.decimals) == \
|
||||
round(float(grb_obj.apertures[apid]['height']), self.decimals) and \
|
||||
|
|
|
@ -13,8 +13,10 @@ from PyQt5.QtWidgets import QVBoxLayout, QWidget
|
|||
from flatcamGUI.GUIElements import _BrowserTextEdit, _ExpandableTextEdit
|
||||
import html
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import tkinter as tk
|
||||
import tclCommands
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
|
@ -110,7 +112,7 @@ class TermWidget(QWidget):
|
|||
elif style == 'err':
|
||||
text = '<span style="font-weight: bold; color: red;">%s</span>'\
|
||||
'<span style="font-weight: bold;">%s</span>'\
|
||||
%(mtype, body)
|
||||
% (mtype, body)
|
||||
elif style == 'warning':
|
||||
# text = '<span style="font-weight: bold; color: #f4b642;">%s</span>' % text
|
||||
text = '<span style="font-weight: bold; color: #f4b642;">%s</span>' \
|
||||
|
@ -253,15 +255,90 @@ class TermWidget(QWidget):
|
|||
|
||||
|
||||
class FCShell(TermWidget):
|
||||
def __init__(self, sysShell, version, *args):
|
||||
def __init__(self, app, version, *args):
|
||||
"""
|
||||
Initialize the TCL Shell. A dock widget that holds the GUI interface to the FlatCAM command line.
|
||||
|
||||
:param sysShell: When instantiated the sysShell will be actually the FlatCAMApp.App() class
|
||||
:param app: When instantiated the sysShell will be actually the FlatCAMApp.App() class
|
||||
:param version: FlatCAM version string
|
||||
:param args: Parameters passed to the TermWidget parent class
|
||||
"""
|
||||
TermWidget.__init__(self, version, *args, app=sysShell)
|
||||
self._sysShell = sysShell
|
||||
TermWidget.__init__(self, version, *args, app=app)
|
||||
self.app = app
|
||||
|
||||
self.tcl_commands_storage = {}
|
||||
|
||||
if hasattr(self, 'tcl') and self.tcl is not None:
|
||||
# self.tcl = None
|
||||
# new object cannot be used here as it will not remember values created for next passes,
|
||||
# because tcl was executed in old instance of TCL
|
||||
pass
|
||||
else:
|
||||
self.tcl = tk.Tcl()
|
||||
self.setup_shell()
|
||||
|
||||
self._edit.set_model_data(self.app.myKeywords)
|
||||
self.setWindowIcon(self.app.ui.app_icon)
|
||||
self.setWindowTitle("FlatCAM Shell")
|
||||
self.resize(*self.app.defaults["global_shell_shape"])
|
||||
self._append_to_browser('in', "FlatCAM %s - " % version)
|
||||
self.append_output('%s\n\n' % _("Type >help< to get started"))
|
||||
|
||||
def setup_shell(self):
|
||||
"""
|
||||
Creates shell functions. Runs once at startup.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
'''
|
||||
How to implement TCL shell commands:
|
||||
|
||||
All parameters passed to command should be possible to set as None and test it afterwards.
|
||||
This is because we need to see error caused in tcl,
|
||||
if None value as default parameter is not allowed TCL will return empty error.
|
||||
Use:
|
||||
def mycommand(name=None,...):
|
||||
|
||||
Test it like this:
|
||||
if name is None:
|
||||
|
||||
self.raise_tcl_error('Argument name is missing.')
|
||||
|
||||
When error occurred, always use raise_tcl_error, never return "some text" on error,
|
||||
otherwise we will miss it and processing will silently continue.
|
||||
Method raise_tcl_error pass error into TCL interpreter, then raise python exception,
|
||||
which is caught in exec_command and displayed in TCL shell console with red background.
|
||||
Error in console is displayed with TCL trace.
|
||||
|
||||
This behavior works only within main thread,
|
||||
errors with promissed tasks can be catched and detected only with log.
|
||||
TODO: this problem have to be addressed somehow, maybe rewrite promissing to be blocking somehow for
|
||||
TCL shell.
|
||||
|
||||
Kamil's comment: I will rewrite existing TCL commands from time to time to follow this rules.
|
||||
|
||||
'''
|
||||
|
||||
# Import/overwrite tcl commands as objects of TclCommand descendants
|
||||
# This modifies the variable 'self.tcl_commands_storage'.
|
||||
tclCommands.register_all_commands(self.app, self.tcl_commands_storage)
|
||||
|
||||
# Add commands to the tcl interpreter
|
||||
for cmd in self.tcl_commands_storage:
|
||||
self.tcl.createcommand(cmd, self.tcl_commands_storage[cmd]['fcn'])
|
||||
|
||||
# Make the tcl puts function return instead of print to stdout
|
||||
self.tcl.eval('''
|
||||
rename puts original_puts
|
||||
proc puts {args} {
|
||||
if {[llength $args] == 1} {
|
||||
return "[lindex $args 0]"
|
||||
} else {
|
||||
eval original_puts $args
|
||||
}
|
||||
}
|
||||
''')
|
||||
|
||||
def is_command_complete(self, text):
|
||||
def skipQuotes(txt):
|
||||
|
@ -293,7 +370,7 @@ class FCShell(TermWidget):
|
|||
:return: output if there was any
|
||||
"""
|
||||
|
||||
self._sysShell.report_usage('exec_command')
|
||||
self.app.report_usage('exec_command')
|
||||
|
||||
return self.exec_command_test(text, False, no_echo=no_echo)
|
||||
|
||||
|
@ -315,15 +392,15 @@ class FCShell(TermWidget):
|
|||
if no_echo is False:
|
||||
self.open_processing() # Disables input box.
|
||||
|
||||
result = self._sysShell.tcl.eval(str(tcl_command_string))
|
||||
result = self.tcl.eval(str(tcl_command_string))
|
||||
if result != 'None' and no_echo is False:
|
||||
self.append_output(result + '\n')
|
||||
|
||||
except tk.TclError as e:
|
||||
|
||||
# This will display more precise answer if something in TCL shell fails
|
||||
result = self._sysShell.tcl.eval("set errorInfo")
|
||||
self._sysShell.log.error("Exec command Exception: %s" % (result + '\n'))
|
||||
result = self.tcl.eval("set errorInfo")
|
||||
self.app.log.error("Exec command Exception: %s" % (result + '\n'))
|
||||
if no_echo is False:
|
||||
self.append_error('ERROR: ' + result + '\n')
|
||||
# Show error in console and just return or in test raise exception
|
||||
|
@ -335,39 +412,101 @@ class FCShell(TermWidget):
|
|||
pass
|
||||
return result
|
||||
|
||||
# """
|
||||
# Code below is unsused. Saved for later.
|
||||
# """
|
||||
def raise_tcl_unknown_error(self, unknownException):
|
||||
"""
|
||||
Raise exception if is different type than TclErrorException
|
||||
this is here mainly to show unknown errors inside TCL shell console.
|
||||
|
||||
# parts = re.findall(r'([\w\\:\.]+|".*?")+', text)
|
||||
# parts = [p.replace('\n', '').replace('"', '') for p in parts]
|
||||
# self.log.debug(parts)
|
||||
# try:
|
||||
# if parts[0] not in commands:
|
||||
# self.shell.append_error("Unknown command\n")
|
||||
# return
|
||||
#
|
||||
# #import inspect
|
||||
# #inspect.getargspec(someMethod)
|
||||
# if (type(commands[parts[0]]["params"]) is not list and len(parts)-1 != commands[parts[0]]["params"]) or \
|
||||
# (type(commands[parts[0]]["params"]) is list and len(parts)-1 not in commands[parts[0]]["params"]):
|
||||
# self.shell.append_error(
|
||||
# "Command %s takes %d arguments. %d given.\n" %
|
||||
# (parts[0], commands[parts[0]]["params"], len(parts)-1)
|
||||
# )
|
||||
# return
|
||||
#
|
||||
# cmdfcn = commands[parts[0]]["fcn"]
|
||||
# cmdconv = commands[parts[0]]["converters"]
|
||||
# if len(parts) - 1 > 0:
|
||||
# retval = cmdfcn(*[cmdconv[i](parts[i + 1]) for i in range(len(parts)-1)])
|
||||
# else:
|
||||
# retval = cmdfcn()
|
||||
# retfcn = commands[parts[0]]["retfcn"]
|
||||
# if retval and retfcn(retval):
|
||||
# self.shell.append_output(retfcn(retval) + "\n")
|
||||
#
|
||||
# except Exception as e:
|
||||
# #self.shell.append_error(''.join(traceback.format_exc()))
|
||||
# #self.shell.append_error("?\n")
|
||||
# self.shell.append_error(str(e) + "\n")
|
||||
:param unknownException:
|
||||
:return:
|
||||
"""
|
||||
|
||||
if not isinstance(unknownException, self.TclErrorException):
|
||||
self.raise_tcl_error("Unknown error: %s" % str(unknownException))
|
||||
else:
|
||||
raise unknownException
|
||||
|
||||
def display_tcl_error(self, error, error_info=None):
|
||||
"""
|
||||
Escape bracket [ with '\' otherwise there is error
|
||||
"ERROR: missing close-bracket" instead of real error
|
||||
|
||||
:param error: it may be text or exception
|
||||
:param error_info: Some informations about the error
|
||||
:return: None
|
||||
"""
|
||||
|
||||
if isinstance(error, Exception):
|
||||
exc_type, exc_value, exc_traceback = error_info
|
||||
if not isinstance(error, self.TclErrorException):
|
||||
show_trace = 1
|
||||
else:
|
||||
show_trace = int(self.app.defaults['global_verbose_error_level'])
|
||||
|
||||
if show_trace > 0:
|
||||
trc = traceback.format_list(traceback.extract_tb(exc_traceback))
|
||||
trc_formated = []
|
||||
for a in reversed(trc):
|
||||
trc_formated.append(a.replace(" ", " > ").replace("\n", ""))
|
||||
text = "%s\nPython traceback: %s\n%s" % (exc_value, exc_type, "\n".join(trc_formated))
|
||||
else:
|
||||
text = "%s" % error
|
||||
else:
|
||||
text = error
|
||||
|
||||
text = text.replace('[', '\\[').replace('"', '\\"')
|
||||
self.tcl.eval('return -code error "%s"' % text)
|
||||
|
||||
def raise_tcl_error(self, text):
|
||||
"""
|
||||
This method pass exception from python into TCL as error, so we get stacktrace and reason
|
||||
|
||||
:param text: text of error
|
||||
:return: raise exception
|
||||
"""
|
||||
|
||||
self.display_tcl_error(text)
|
||||
raise self.TclErrorException(text)
|
||||
|
||||
class TclErrorException(Exception):
|
||||
"""
|
||||
this exception is defined here, to be able catch it if we successfully handle all errors from shell command
|
||||
"""
|
||||
pass
|
||||
|
||||
# """
|
||||
# Code below is unsused. Saved for later.
|
||||
# """
|
||||
|
||||
# parts = re.findall(r'([\w\\:\.]+|".*?")+', text)
|
||||
# parts = [p.replace('\n', '').replace('"', '') for p in parts]
|
||||
# self.log.debug(parts)
|
||||
# try:
|
||||
# if parts[0] not in commands:
|
||||
# self.shell.append_error("Unknown command\n")
|
||||
# return
|
||||
#
|
||||
# #import inspect
|
||||
# #inspect.getargspec(someMethod)
|
||||
# if (type(commands[parts[0]]["params"]) is not list and len(parts)-1 != commands[parts[0]]["params"]) or \
|
||||
# (type(commands[parts[0]]["params"]) is list and len(parts)-1 not in commands[parts[0]]["params"]):
|
||||
# self.shell.append_error(
|
||||
# "Command %s takes %d arguments. %d given.\n" %
|
||||
# (parts[0], commands[parts[0]]["params"], len(parts)-1)
|
||||
# )
|
||||
# return
|
||||
#
|
||||
# cmdfcn = commands[parts[0]]["fcn"]
|
||||
# cmdconv = commands[parts[0]]["converters"]
|
||||
# if len(parts) - 1 > 0:
|
||||
# retval = cmdfcn(*[cmdconv[i](parts[i + 1]) for i in range(len(parts)-1)])
|
||||
# else:
|
||||
# retval = cmdfcn()
|
||||
# retfcn = commands[parts[0]]["retfcn"]
|
||||
# if retval and retfcn(retval):
|
||||
# self.shell.append_output(retfcn(retval) + "\n")
|
||||
#
|
||||
# except Exception as e:
|
||||
# #self.shell.append_error(''.join(traceback.format_exc()))
|
||||
# #self.shell.append_error("?\n")
|
||||
# self.shell.append_error(str(e) + "\n")
|
||||
|
|
|
@ -11,7 +11,6 @@ from flatcamGUI.GUIElements import FCComboBox, FCEntry, FCTable, \
|
|||
FCInputDialog, FCDoubleSpinner, FCSpinner, FCFileSaveDialog
|
||||
from FlatCAMApp import log
|
||||
from camlib import distance
|
||||
from FlatCAMObj import FlatCAMCNCjob
|
||||
from flatcamEditors.FlatCAMTextEditor import TextEditor
|
||||
|
||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
||||
|
@ -506,7 +505,8 @@ class SolderPaste(FlatCAMTool):
|
|||
self.flat_geometry = []
|
||||
|
||||
# action to be added in the combobox context menu
|
||||
self.combo_context_del_action = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/trash16.png'), _("Delete Object"))
|
||||
self.combo_context_del_action = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/trash16.png'),
|
||||
_("Delete Object"))
|
||||
|
||||
# ## Signals
|
||||
self.combo_context_del_action.triggered.connect(self.on_delete_object)
|
||||
|
@ -966,6 +966,7 @@ class SolderPaste(FlatCAMTool):
|
|||
self.build_ui()
|
||||
return
|
||||
else:
|
||||
old_tool_dia = ''
|
||||
# identify the old tool_dia and restore the text in tool table
|
||||
for k, v in self.tooltable_tools.items():
|
||||
if k == tooluid:
|
||||
|
@ -1332,9 +1333,9 @@ class SolderPaste(FlatCAMTool):
|
|||
|
||||
# Object initialization function for app.new_object()
|
||||
# RUNNING ON SEPARATE THREAD!
|
||||
def job_init(job_obj, app_obj):
|
||||
assert isinstance(job_obj, FlatCAMCNCjob), \
|
||||
"Initializer expected a FlatCAMCNCjob, got %s" % type(job_obj)
|
||||
def job_init(job_obj):
|
||||
assert job_obj.kind == 'cncjob', \
|
||||
"Initializer expected a CNCJobObject, got %s" % type(job_obj)
|
||||
|
||||
# this turn on the FlatCAMCNCJob plot for multiple tools
|
||||
job_obj.multitool = True
|
||||
|
@ -1364,7 +1365,7 @@ class SolderPaste(FlatCAMTool):
|
|||
res = job_obj.generate_gcode_from_solderpaste_geo(**tooluid_value)
|
||||
|
||||
if res == 'fail':
|
||||
log.debug("FlatCAMGeometry.mtool_gen_cncjob() --> generate_from_geometry2() failed")
|
||||
log.debug("GeometryObject.mtool_gen_cncjob() --> generate_from_geometry2() failed")
|
||||
return 'fail'
|
||||
else:
|
||||
tool_cnc_dict['gcode'] = res
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCButton, OptionalInputSection, EvalEntry2
|
||||
from FlatCAMObj import FlatCAMCNCjob
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
|
@ -681,7 +680,7 @@ class ToolTransform(FlatCAMTool):
|
|||
try:
|
||||
# first get a bounding box to fit all
|
||||
for obj in obj_list:
|
||||
if isinstance(obj, FlatCAMCNCjob):
|
||||
if obj.kind == 'cncjob':
|
||||
pass
|
||||
else:
|
||||
xmin, ymin, xmax, ymax = obj.bounds()
|
||||
|
@ -699,7 +698,7 @@ class ToolTransform(FlatCAMTool):
|
|||
px = 0.5 * (xminimal + xmaximal)
|
||||
py = 0.5 * (yminimal + ymaximal)
|
||||
for sel_obj in obj_list:
|
||||
if isinstance(sel_obj, FlatCAMCNCjob):
|
||||
if sel_obj.kind == 'cncjob':
|
||||
self.app.inform.emit(_("CNCJob objects can't be rotated."))
|
||||
else:
|
||||
sel_obj.rotate(-num, point=(px, py))
|
||||
|
@ -735,7 +734,7 @@ class ToolTransform(FlatCAMTool):
|
|||
else:
|
||||
# first get a bounding box to fit all
|
||||
for obj in obj_list:
|
||||
if isinstance(obj, FlatCAMCNCjob):
|
||||
if obj.kind == 'cncjob':
|
||||
pass
|
||||
else:
|
||||
xmin, ymin, xmax, ymax = obj.bounds()
|
||||
|
@ -755,7 +754,7 @@ class ToolTransform(FlatCAMTool):
|
|||
|
||||
# execute mirroring
|
||||
for sel_obj in obj_list:
|
||||
if isinstance(sel_obj, FlatCAMCNCjob):
|
||||
if sel_obj.kind == 'cncjob':
|
||||
self.app.inform.emit(_("CNCJob objects can't be mirrored/flipped."))
|
||||
else:
|
||||
if axis == 'X':
|
||||
|
@ -803,7 +802,7 @@ class ToolTransform(FlatCAMTool):
|
|||
try:
|
||||
# first get a bounding box to fit all
|
||||
for obj in obj_list:
|
||||
if isinstance(obj, FlatCAMCNCjob):
|
||||
if obj.kind == 'cncjob':
|
||||
pass
|
||||
else:
|
||||
xmin, ymin, xmax, ymax = obj.bounds()
|
||||
|
@ -815,7 +814,7 @@ class ToolTransform(FlatCAMTool):
|
|||
yminimal = min(yminlist)
|
||||
|
||||
for sel_obj in obj_list:
|
||||
if isinstance(sel_obj, FlatCAMCNCjob):
|
||||
if sel_obj.kind == 'cncjob':
|
||||
self.app.inform.emit(_("CNCJob objects can't be skewed."))
|
||||
else:
|
||||
if axis == 'X':
|
||||
|
@ -842,15 +841,14 @@ class ToolTransform(FlatCAMTool):
|
|||
ymaxlist = []
|
||||
|
||||
if not obj_list:
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
||||
_("No object selected. Please Select an object to scale!"))
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("No object selected. Please Select an object to scale!"))
|
||||
return
|
||||
else:
|
||||
with self.app.proc_container.new(_("Applying Scale")):
|
||||
try:
|
||||
# first get a bounding box to fit all
|
||||
for obj in obj_list:
|
||||
if isinstance(obj, FlatCAMCNCjob):
|
||||
if obj.kind == 'cncjob':
|
||||
pass
|
||||
else:
|
||||
xmin, ymin, xmax, ymax = obj.bounds()
|
||||
|
@ -873,7 +871,7 @@ class ToolTransform(FlatCAMTool):
|
|||
py = 0
|
||||
|
||||
for sel_obj in obj_list:
|
||||
if isinstance(sel_obj, FlatCAMCNCjob):
|
||||
if sel_obj.kind == 'cncjob':
|
||||
self.app.inform.emit(_("CNCJob objects can't be scaled."))
|
||||
else:
|
||||
sel_obj.scale(xfactor, yfactor, point=(px, py))
|
||||
|
@ -883,8 +881,7 @@ class ToolTransform(FlatCAMTool):
|
|||
self.app.object_changed.emit(sel_obj)
|
||||
sel_obj.plot()
|
||||
|
||||
self.app.inform.emit('[success] %s %s %s...' %
|
||||
(_('Scale on the'), str(axis), _('axis done')))
|
||||
self.app.inform.emit('[success] %s %s %s...' % (_('Scale on the'), str(axis), _('axis done')))
|
||||
except Exception as e:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s %s, %s.' %
|
||||
(_("Due of"), str(e), _("action was not executed.")))
|
||||
|
@ -894,14 +891,13 @@ class ToolTransform(FlatCAMTool):
|
|||
obj_list = self.app.collection.get_selected()
|
||||
|
||||
if not obj_list:
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
||||
_("No object selected. Please Select an object to offset!"))
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("No object selected. Please Select an object to offset!"))
|
||||
return
|
||||
else:
|
||||
with self.app.proc_container.new(_("Applying Offset")):
|
||||
try:
|
||||
for sel_obj in obj_list:
|
||||
if isinstance(sel_obj, FlatCAMCNCjob):
|
||||
if sel_obj.kind == 'cncjob':
|
||||
self.app.inform.emit(_("CNCJob objects can't be offset."))
|
||||
else:
|
||||
if axis == 'X':
|
||||
|
@ -915,8 +911,7 @@ class ToolTransform(FlatCAMTool):
|
|||
self.app.object_changed.emit(sel_obj)
|
||||
sel_obj.plot()
|
||||
|
||||
self.app.inform.emit('[success] %s %s %s...' %
|
||||
(_('Offset on the'), str(axis), _('axis done')))
|
||||
self.app.inform.emit('[success] %s %s %s...' % (_('Offset on the'), str(axis), _('axis done')))
|
||||
except Exception as e:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s %s, %s.' %
|
||||
(_("Due of"), str(e), _("action was not executed.")))
|
||||
|
@ -932,7 +927,7 @@ class ToolTransform(FlatCAMTool):
|
|||
with self.app.proc_container.new(_("Applying Buffer")):
|
||||
try:
|
||||
for sel_obj in obj_list:
|
||||
if isinstance(sel_obj, FlatCAMCNCjob):
|
||||
if sel_obj.kind == 'cncjob':
|
||||
self.app.inform.emit(_("CNCJob objects can't be buffered."))
|
||||
elif sel_obj.kind.lower() == 'gerber':
|
||||
sel_obj.buffer(value, join, factor)
|
||||
|
|
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
|
@ -507,7 +507,7 @@ msgid "Failed. Select a Geometry Object and try again."
|
|||
msgstr ""
|
||||
|
||||
#: FlatCAMApp.py:5652 FlatCAMApp.py:5688
|
||||
msgid "Expected a FlatCAMGeometry, got"
|
||||
msgid "Expected a GeometryObject, got"
|
||||
msgstr ""
|
||||
|
||||
#: FlatCAMApp.py:5665
|
||||
|
@ -1125,7 +1125,7 @@ msgid "Open TCL script cancelled."
|
|||
msgstr ""
|
||||
|
||||
#: FlatCAMApp.py:9993
|
||||
msgid "Executing FlatCAMScript file."
|
||||
msgid "Executing ScriptObject file."
|
||||
msgstr ""
|
||||
|
||||
#: FlatCAMApp.py:10000 FlatCAMApp.py:10003
|
||||
|
@ -14705,7 +14705,7 @@ msgid "Buffer done"
|
|||
msgstr ""
|
||||
|
||||
#: tclCommands/TclCommandBbox.py:74 tclCommands/TclCommandNregions.py:73
|
||||
msgid "Expected FlatCAMGerber or FlatCAMGeometry, got"
|
||||
msgid "Expected GerberObject or GeometryObject, got"
|
||||
msgstr ""
|
||||
|
||||
#: tclCommands/TclCommandBounds.py:64 tclCommands/TclCommandBounds.py:68
|
||||
|
|
|
@ -557,7 +557,7 @@ msgid "Failed. Select a Geometry Object and try again."
|
|||
msgstr "Falha. Selecione um Objeto de Geometria e tente novamente."
|
||||
|
||||
#: FlatCAMApp.py:5652 FlatCAMApp.py:5688
|
||||
msgid "Expected a FlatCAMGeometry, got"
|
||||
msgid "Expected a GeometryObject, got"
|
||||
msgstr "Geometria FlatCAM esperada, recebido"
|
||||
|
||||
#: FlatCAMApp.py:5665
|
||||
|
@ -1211,7 +1211,7 @@ msgid "Open TCL script cancelled."
|
|||
msgstr "Abrir script TCL cancelado."
|
||||
|
||||
#: FlatCAMApp.py:9993
|
||||
msgid "Executing FlatCAMScript file."
|
||||
msgid "Executing ScriptObject file."
|
||||
msgstr "Executando arquivo de Script FlatCAM."
|
||||
|
||||
#: FlatCAMApp.py:10000 FlatCAMApp.py:10003
|
||||
|
@ -16677,8 +16677,8 @@ msgid "Buffer done"
|
|||
msgstr "Buffer concluído"
|
||||
|
||||
#: tclCommands/TclCommandBbox.py:74 tclCommands/TclCommandNregions.py:73
|
||||
msgid "Expected FlatCAMGerber or FlatCAMGeometry, got"
|
||||
msgstr "Esperando FlatCAMGerber ou FlatCAMGeometry, recebido"
|
||||
msgid "Expected GerberObject or GeometryObject, got"
|
||||
msgstr "Esperando GerberObject ou GeometryObject, recebido"
|
||||
|
||||
#: tclCommands/TclCommandBounds.py:64 tclCommands/TclCommandBounds.py:68
|
||||
msgid "Expected a list of objects names separated by comma. Got"
|
||||
|
@ -17323,8 +17323,8 @@ msgstr "Nenhum nome de geometria nos argumentos. Altere e tente novamente."
|
|||
#~ msgid "<span style=\"color:red;\"><b>%s</b></span>"
|
||||
#~ msgstr "<span style=\"color:red;\"><b>%s</b></span>"
|
||||
|
||||
#~ msgid "FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() -->"
|
||||
#~ msgstr "FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() -->"
|
||||
#~ msgid "FlatCAMObj.GeometryObject.mtool_gen_cncjob() -->"
|
||||
#~ msgstr "FlatCAMObj.GeometryObject.mtool_gen_cncjob() -->"
|
||||
|
||||
#~ msgid "FlatCAMCNNJob.on_edit_code_click() -->"
|
||||
#~ msgstr "FlatCAMCNNJob.on_edit_code_click() -->"
|
||||
|
@ -17580,7 +17580,7 @@ msgstr "Nenhum nome de geometria nos argumentos. Altere e tente novamente."
|
|||
#~ "flatcam/src/Beta/\">aqui.</a><BR>Área de <B>DOWNLOAD</B> <a href = "
|
||||
#~ "\"https://bitbucket.org/jpcgt/flatcam/downloads/\">aqui.</a><BR>"
|
||||
|
||||
#~ msgid "Expected a FlatCAMGeometry, got %s"
|
||||
#~ msgid "Expected a GeometryObject, got %s"
|
||||
#~ msgstr "Geometria FlatCAM esperada, recebido %s"
|
||||
|
||||
#~ msgid "Saved to: %s"
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -546,8 +546,8 @@ msgid "Failed. Select a Geometry Object and try again."
|
|||
msgstr "Неудалось. Выберите объект Geometry и попробуйте снова."
|
||||
|
||||
#: FlatCAMApp.py:5652 FlatCAMApp.py:5688
|
||||
msgid "Expected a FlatCAMGeometry, got"
|
||||
msgstr "Ожидается FlatCAMGeometry, получено"
|
||||
msgid "Expected a GeometryObject, got"
|
||||
msgstr "Ожидается GeometryObject, получено"
|
||||
|
||||
#: FlatCAMApp.py:5665
|
||||
msgid "A Geometry object was converted to MultiGeo type."
|
||||
|
@ -1189,8 +1189,8 @@ msgid "Open TCL script cancelled."
|
|||
msgstr "Открытие сценария отменено."
|
||||
|
||||
#: FlatCAMApp.py:9993
|
||||
msgid "Executing FlatCAMScript file."
|
||||
msgstr "Выполнение файла FlatCAMScript."
|
||||
msgid "Executing ScriptObject file."
|
||||
msgstr "Выполнение файла ScriptObject."
|
||||
|
||||
#: FlatCAMApp.py:10000 FlatCAMApp.py:10003
|
||||
msgid "Run TCL script"
|
||||
|
@ -16746,8 +16746,8 @@ msgid "Buffer done"
|
|||
msgstr "Буфер готов"
|
||||
|
||||
#: tclCommands/TclCommandBbox.py:74 tclCommands/TclCommandNregions.py:73
|
||||
msgid "Expected FlatCAMGerber or FlatCAMGeometry, got"
|
||||
msgstr "Ожидался FlatCAMGerber или FlatCAMGeometry, получено"
|
||||
msgid "Expected GerberObject or GeometryObject, got"
|
||||
msgstr "Ожидался GerberObject или GeometryObject, получено"
|
||||
|
||||
#: tclCommands/TclCommandBounds.py:64 tclCommands/TclCommandBounds.py:68
|
||||
msgid "Expected a list of objects names separated by comma. Got"
|
||||
|
@ -17431,8 +17431,8 @@ msgstr "Нет имени геометрии в аргументах. Укажи
|
|||
#~ msgid "<span style=\"color:red;\"><b>%s</b></span>"
|
||||
#~ msgstr "<span style=\"color:red;\"><b>%s</b></span>"
|
||||
|
||||
#~ msgid "FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() -->"
|
||||
#~ msgstr "FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() -->"
|
||||
#~ msgid "FlatCAMObj.GeometryObject.mtool_gen_cncjob() -->"
|
||||
#~ msgstr "FlatCAMObj.GeometryObject.mtool_gen_cncjob() -->"
|
||||
|
||||
#~ msgid "FlatCAMCNNJob.on_edit_code_click() -->"
|
||||
#~ msgstr "FlatCAMCNNJob.on_edit_code_click() -->"
|
||||
|
@ -17603,8 +17603,8 @@ msgstr "Нет имени геометрии в аргументах. Укажи
|
|||
#~ "a><BR><b>ЗАГРУЗИТЬ</B> можно <a href = \"https://bitbucket.org/jpcgt/"
|
||||
#~ "flatcam/downloads/\">отсюда.</a><BR>"
|
||||
|
||||
#~ msgid "Expected a FlatCAMGeometry, got %s"
|
||||
#~ msgstr "Ожидается FlatCAMGeometry, получено %s"
|
||||
#~ msgid "Expected a GeometryObject, got %s"
|
||||
#~ msgstr "Ожидается GeometryObject, получено %s"
|
||||
|
||||
#~ msgid "Saved to: %s"
|
||||
#~ msgstr "Сохранёно в: %s"
|
||||
|
|
|
@ -498,7 +498,7 @@ msgid "Failed. Select a Geometry Object and try again."
|
|||
msgstr ""
|
||||
|
||||
#: FlatCAMApp.py:5765 FlatCAMApp.py:5801
|
||||
msgid "Expected a FlatCAMGeometry, got"
|
||||
msgid "Expected a GeometryObject, got"
|
||||
msgstr ""
|
||||
|
||||
#: FlatCAMApp.py:5778
|
||||
|
@ -1056,7 +1056,7 @@ msgid "Open TCL script"
|
|||
msgstr ""
|
||||
|
||||
#: FlatCAMApp.py:10373
|
||||
msgid "Executing FlatCAMScript file."
|
||||
msgid "Executing ScriptObject file."
|
||||
msgstr ""
|
||||
|
||||
#: FlatCAMApp.py:10381 FlatCAMApp.py:10384
|
||||
|
@ -15065,7 +15065,7 @@ msgid "Buffer done"
|
|||
msgstr ""
|
||||
|
||||
#: tclCommands/TclCommandBbox.py:76 tclCommands/TclCommandNregions.py:75
|
||||
msgid "Expected FlatCAMGerber or FlatCAMGeometry, got"
|
||||
msgid "Expected GerberObject or GeometryObject, got"
|
||||
msgstr ""
|
||||
|
||||
#: tclCommands/TclCommandBounds.py:67 tclCommands/TclCommandBounds.py:71
|
||||
|
|
|
@ -18,7 +18,7 @@ vispy
|
|||
ortools>=7.0
|
||||
svg.path
|
||||
simplejson
|
||||
shapely>=1.3
|
||||
shapely>=1.7.0
|
||||
freetype-py
|
||||
fontTools
|
||||
rasterio
|
||||
|
|
|
@ -71,7 +71,7 @@ class TclCommand(object):
|
|||
:return: none
|
||||
"""
|
||||
|
||||
self.app.raise_tcl_error(text)
|
||||
self.app.shell.raise_tcl_error(text)
|
||||
|
||||
def get_current_command(self):
|
||||
"""
|
||||
|
@ -275,7 +275,7 @@ class TclCommand(object):
|
|||
# because of signaling we cannot call error to TCL from here but when task
|
||||
# is finished also non-signaled are handled here to better exception
|
||||
# handling and displayed after command is finished
|
||||
raise self.app.TclErrorException(text)
|
||||
raise self.app.shell.TclErrorException(text)
|
||||
|
||||
def execute_wrapper(self, *args):
|
||||
"""
|
||||
|
@ -296,7 +296,7 @@ class TclCommand(object):
|
|||
except Exception as unknown:
|
||||
error_info = sys.exc_info()
|
||||
self.log.error("TCL command '%s' failed. Error text: %s" % (str(self), str(unknown)))
|
||||
self.app.display_tcl_error(unknown, error_info)
|
||||
self.app.shell.display_tcl_error(unknown, error_info)
|
||||
self.raise_tcl_unknown_error(unknown)
|
||||
|
||||
@abc.abstractmethod
|
||||
|
@ -400,9 +400,9 @@ class TclCommandSignaled(TclCommand):
|
|||
raise ex[0]
|
||||
|
||||
if status['timed_out']:
|
||||
self.app.raise_tcl_unknown_error("Operation timed outed! Consider increasing option "
|
||||
"'-timeout <miliseconds>' for command or "
|
||||
"'set_sys global_background_timeout <miliseconds>'.")
|
||||
self.app.shell.raise_tcl_unknown_error("Operation timed outed! Consider increasing option "
|
||||
"'-timeout <miliseconds>' for command or "
|
||||
"'set_sys global_background_timeout <miliseconds>'.")
|
||||
|
||||
try:
|
||||
self.log.debug("TCL command '%s' executed." % str(type(self).__name__))
|
||||
|
@ -439,5 +439,5 @@ class TclCommandSignaled(TclCommand):
|
|||
else:
|
||||
error_info = sys.exc_info()
|
||||
self.log.error("TCL command '%s' failed." % str(self))
|
||||
self.app.display_tcl_error(unknown, error_info)
|
||||
self.app.shell.display_tcl_error(unknown, error_info)
|
||||
self.raise_tcl_unknown_error(unknown)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import collections
|
||||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from FlatCAMObj import FlatCAMGeometry, FlatCAMGerber, FlatCAMExcellon
|
||||
|
||||
from shapely.geometry import Point
|
||||
import shapely.affinity as affinity
|
||||
|
@ -89,9 +88,7 @@ class TclCommandAlignDrill(TclCommandSignaled):
|
|||
if obj is None:
|
||||
return "Object not found: %s" % name
|
||||
|
||||
if not isinstance(obj, FlatCAMGeometry) and \
|
||||
not isinstance(obj, FlatCAMGerber) and \
|
||||
not isinstance(obj, FlatCAMExcellon):
|
||||
if obj.kind != "geometry" and obj.kind != 'gerber' and obj.kind != 'excellon':
|
||||
return "ERROR: Only Gerber, Geometry and Excellon objects can be used."
|
||||
|
||||
# Axis
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import collections
|
||||
from tclCommands.TclCommand import TclCommand
|
||||
from FlatCAMObj import FlatCAMGeometry, FlatCAMGerber
|
||||
|
||||
from shapely.ops import cascaded_union
|
||||
|
||||
|
@ -73,7 +72,7 @@ class TclCommandBbox(TclCommand):
|
|||
|
||||
if not isinstance(obj, FlatCAMGerber) and not isinstance(obj, FlatCAMGeometry):
|
||||
self.raise_tcl_error('%s %s: %s.' % (
|
||||
_("Expected FlatCAMGerber or FlatCAMGeometry, got"), name, type(obj)))
|
||||
_("Expected GerberObject or GeometryObject, got"), name, type(obj)))
|
||||
|
||||
if 'margin' not in args:
|
||||
args['margin'] = float(self.app.defaults["gerber_bboxmargin"])
|
||||
|
@ -92,7 +91,7 @@ class TclCommandBbox(TclCommand):
|
|||
|
||||
try:
|
||||
def geo_init(geo_obj, app_obj):
|
||||
assert isinstance(geo_obj, FlatCAMGeometry)
|
||||
# assert geo_obj.kind == 'geometry'
|
||||
|
||||
# Bounding box with rounded corners
|
||||
geo = cascaded_union(obj.solid_geometry)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from FlatCAMObj import FlatCAMGeometry
|
||||
|
||||
import collections
|
||||
from copy import deepcopy
|
||||
|
@ -119,9 +118,9 @@ class TclCommandCncjob(TclCommandSignaled):
|
|||
else:
|
||||
return "fail"
|
||||
|
||||
if not isinstance(obj, FlatCAMGeometry):
|
||||
if obj.kind != 'geometry':
|
||||
if muted is False:
|
||||
self.raise_tcl_error('Expected FlatCAMGeometry, got %s %s.' % (str(name), type(obj)))
|
||||
self.raise_tcl_error('Expected GeometryObject, got %s %s.' % (str(name), type(obj)))
|
||||
else:
|
||||
return
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from FlatCAMObj import FlatCAMExcellon
|
||||
|
||||
import collections
|
||||
import math
|
||||
|
@ -125,9 +124,9 @@ class TclCommandDrillcncjob(TclCommandSignaled):
|
|||
else:
|
||||
return "fail"
|
||||
|
||||
if not isinstance(obj, FlatCAMExcellon):
|
||||
if obj.kind != 'excellon':
|
||||
if muted is False:
|
||||
self.raise_tcl_error('Expected FlatCAMExcellon, got %s %s.' % (name, type(obj)))
|
||||
self.raise_tcl_error('Expected ExcellonObject, got %s %s.' % (name, type(obj)))
|
||||
else:
|
||||
return "fail"
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from FlatCAMObj import FlatCAMGerber
|
||||
|
||||
import collections
|
||||
|
||||
|
@ -56,8 +55,8 @@ class TclCommandFollow(TclCommandSignaled):
|
|||
if obj is None:
|
||||
self.raise_tcl_error("Object not found: %s" % name)
|
||||
|
||||
if not isinstance(obj, FlatCAMGerber):
|
||||
self.raise_tcl_error('Expected FlatCAMGerber, got %s %s.' % (name, type(obj)))
|
||||
if obj.kind != 'gerber':
|
||||
self.raise_tcl_error('Expected GerberObject, got %s %s.' % (name, type(obj)))
|
||||
|
||||
del args['name']
|
||||
try:
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry
|
||||
|
||||
import logging
|
||||
import collections
|
||||
|
@ -209,7 +208,7 @@ class TclCommandGeoCutout(TclCommandSignaled):
|
|||
except ValueError:
|
||||
gaps_u = gaps
|
||||
|
||||
if isinstance(cutout_obj, FlatCAMGeometry):
|
||||
if cutout_obj.kind == 'geometry':
|
||||
# rename the obj name so it can be identified as cutout
|
||||
# cutout_obj.options["name"] += "_cutout"
|
||||
|
||||
|
@ -306,7 +305,7 @@ class TclCommandGeoCutout(TclCommandSignaled):
|
|||
# cutout_obj.plot()
|
||||
# self.app.inform.emit("[success] Any-form Cutout operation finished.")
|
||||
# self.app.plots_updated.emit()
|
||||
elif isinstance(cutout_obj, FlatCAMGerber):
|
||||
elif cutout_obj.kind == 'gerber':
|
||||
|
||||
def geo_init(geo_obj, app_obj):
|
||||
try:
|
||||
|
|
|
@ -65,10 +65,11 @@ class TclCommandHelp(TclCommand):
|
|||
|
||||
if 'name' in args:
|
||||
name = args['name']
|
||||
if name not in self.app.tcl_commands_storage:
|
||||
if name not in self.app.shell.tcl_commands_storage:
|
||||
return "Unknown command: %s" % name
|
||||
|
||||
self.app.shell.append_output(self.app.tcl_commands_storage[name]["help"])
|
||||
help_for_command = self.app.shell.tcl_commands_storage[name]["help"] + '\n\n'
|
||||
self.app.shell.append_output(help_for_command)
|
||||
else:
|
||||
if not args:
|
||||
cmd_enum = '%s\n' % _("Available commands:")
|
||||
|
@ -77,19 +78,21 @@ class TclCommandHelp(TclCommand):
|
|||
try:
|
||||
# find the maximum length of a command name
|
||||
max_len = 0
|
||||
for cmd_name in self.app.tcl_commands_storage:
|
||||
for cmd_name in self.app.shell.tcl_commands_storage:
|
||||
curr_len = len(cmd_name)
|
||||
if curr_len > max_len:
|
||||
max_len = curr_len
|
||||
|
||||
h_space = " "
|
||||
cnt = 0
|
||||
for cmd_name in sorted(self.app.tcl_commands_storage):
|
||||
cmd_description = "<span>%s</span>" % self.app.tcl_commands_storage[cmd_name]['description']
|
||||
for cmd_name in sorted(self.app.shell.tcl_commands_storage):
|
||||
cmd_description = "<span>%s</span>" % \
|
||||
self.app.shell.tcl_commands_storage[cmd_name]['description']
|
||||
|
||||
curr_len = len(cmd_name)
|
||||
|
||||
cmd_name_colored = "<span style=\" font-weight: bold; color: red;\" >%s</span>" % str(cmd_name)
|
||||
cmd_name_colored = "> <span style=\" font-weight: bold; color: red;\" >%s</span>" % \
|
||||
str(cmd_name)
|
||||
|
||||
nr_chars = max_len - curr_len
|
||||
|
||||
|
@ -104,11 +107,11 @@ class TclCommandHelp(TclCommand):
|
|||
else:
|
||||
cnt += 1
|
||||
except Exception as err:
|
||||
self.app.log.debug("App.setup_shell.shelp() when run as 'help' --> %s" % str(err))
|
||||
displayed_text = ['> %s\n' % cmd for cmd in sorted(self.app.tcl_commands_storage)]
|
||||
self.app.log.debug("tclCommands.TclCommandHelp() when run as 'help' --> %s" % str(err))
|
||||
displayed_text = ['> %s' % cmd for cmd in sorted(self.app.shell.tcl_commands_storage)]
|
||||
|
||||
cmd_enum += '<br>'.join(displayed_text)
|
||||
cmd_enum += '<br><br>%s<br>%s<br>' % (
|
||||
cmd_enum += '<br><br>%s<br>%s<br><br>' % (
|
||||
_("Type help <command_name> for usage."), _("Example: help open_gerber"))
|
||||
|
||||
self.app.shell.append_raw(cmd_enum)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from FlatCAMObj import FlatCAMGerber
|
||||
|
||||
import collections
|
||||
|
||||
|
@ -96,8 +95,8 @@ class TclCommandIsolate(TclCommandSignaled):
|
|||
if obj is None:
|
||||
self.raise_tcl_error("Object not found: %s" % name)
|
||||
|
||||
if not isinstance(obj, FlatCAMGerber):
|
||||
self.raise_tcl_error('Expected FlatCAMGerber, got %s %s.' % (name, type(obj)))
|
||||
if obj.kind != 'gerber':
|
||||
self.raise_tcl_error('Expected GerberObject, got %s %s.' % (name, type(obj)))
|
||||
|
||||
del args['name']
|
||||
obj.isolate(plot=False, **args)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from tclCommands.TclCommand import TclCommand
|
||||
from FlatCAMObj import FlatCAMExcellon
|
||||
from flatcamObjects.FlatCAMExcellon import ExcellonObject
|
||||
|
||||
import collections
|
||||
|
||||
|
@ -62,7 +62,7 @@ class TclCommandJoinExcellon(TclCommand):
|
|||
objs.append(obj)
|
||||
|
||||
def initialize(obj_, app):
|
||||
FlatCAMExcellon.merge(self, objs, obj_)
|
||||
ExcellonObject.merge(self, objs, obj_)
|
||||
|
||||
if objs and len(objs) >= 2:
|
||||
self.app.new_object("excellon", outname, initialize, plot=False)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from tclCommands.TclCommand import TclCommand
|
||||
from FlatCAMObj import FlatCAMGeometry
|
||||
from flatcamObjects.FlatCAMGeometry import GeometryObject
|
||||
|
||||
import collections
|
||||
|
||||
|
@ -62,7 +62,7 @@ class TclCommandJoinGeometry(TclCommand):
|
|||
objs.append(obj)
|
||||
|
||||
def initialize(obj_, app):
|
||||
FlatCAMGeometry.merge(self, objs, obj_)
|
||||
GeometryObject.merge(self, objs, obj_)
|
||||
|
||||
if objs and len(objs) >= 2:
|
||||
self.app.new_object("geometry", outname, initialize, plot=False)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
# ##########################################################
|
||||
|
||||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from FlatCAMObj import FlatCAMExcellon
|
||||
|
||||
import math
|
||||
import collections
|
||||
|
@ -138,7 +137,7 @@ class TclCommandMillDrills(TclCommandSignaled):
|
|||
except Exception as e:
|
||||
self.raise_tcl_error("Bad tools: %s" % str(e))
|
||||
|
||||
if not isinstance(obj, FlatCAMExcellon):
|
||||
if obj.kind != 'excellon':
|
||||
self.raise_tcl_error('Only Excellon objects can be mill-drilled, got %s %s.' % (name, type(obj)))
|
||||
|
||||
if self.app.collection.has_promises():
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
# ##########################################################
|
||||
|
||||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from FlatCAMObj import FlatCAMExcellon
|
||||
|
||||
import collections
|
||||
import math
|
||||
|
@ -139,7 +138,7 @@ class TclCommandMillSlots(TclCommandSignaled):
|
|||
except Exception as e:
|
||||
self.raise_tcl_error("Bad tools: %s" % str(e))
|
||||
|
||||
if not isinstance(obj, FlatCAMExcellon):
|
||||
if obj.kind != 'excellon':
|
||||
self.raise_tcl_error('Only Excellon objects can have mill-slots, got %s %s.' % (name, type(obj)))
|
||||
|
||||
if self.app.collection.has_promises():
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from FlatCAMObj import FlatCAMExcellon, FlatCAMGeometry, FlatCAMGerber
|
||||
|
||||
import collections
|
||||
|
||||
|
@ -68,9 +67,7 @@ class TclCommandMirror(TclCommandSignaled):
|
|||
if obj is None:
|
||||
return "Object not found: %s" % name
|
||||
|
||||
if not isinstance(obj, FlatCAMGerber) and \
|
||||
not isinstance(obj, FlatCAMExcellon) and \
|
||||
not isinstance(obj, FlatCAMGeometry):
|
||||
if obj.kind != 'gerber' and obj.kind != 'geometry' and obj.kind != 'excellon':
|
||||
return "ERROR: Only Gerber, Excellon and Geometry objects can be mirrored."
|
||||
|
||||
# Axis
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from tclCommands.TclCommand import TclCommand
|
||||
from FlatCAMObj import FlatCAMGeometry, FlatCAMGerber
|
||||
|
||||
from shapely.ops import cascaded_union
|
||||
|
||||
|
@ -71,8 +70,8 @@ class TclCommandNregions(TclCommand):
|
|||
if obj is None:
|
||||
self.raise_tcl_error("%s: %s" % (_("Object not found"), name))
|
||||
|
||||
if not isinstance(obj, FlatCAMGerber) and not isinstance(obj, FlatCAMGeometry):
|
||||
self.raise_tcl_error('%s %s: %s.' % (_("Expected FlatCAMGerber or FlatCAMGeometry, got"), name, type(obj)))
|
||||
if obj.kind != 'gerber' and obj.kind != 'geometry':
|
||||
self.raise_tcl_error('%s %s: %s.' % (_("Expected GerberObject or GeometryObject, got"), name, type(obj)))
|
||||
|
||||
if 'margin' not in args:
|
||||
args['margin'] = float(self.app.defaults["gerber_noncoppermargin"])
|
||||
|
@ -91,7 +90,7 @@ class TclCommandNregions(TclCommand):
|
|||
|
||||
try:
|
||||
def geo_init(geo_obj, app_obj):
|
||||
assert isinstance(geo_obj, FlatCAMGeometry)
|
||||
assert geo_obj.kind == 'geometry'
|
||||
|
||||
geo = cascaded_union(obj.solid_geometry)
|
||||
bounding_box = geo.envelope.buffer(float(margin))
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from tclCommands.TclCommand import TclCommandSignaled
|
||||
from camlib import ParseError
|
||||
from FlatCAMObj import FlatCAMGerber
|
||||
|
||||
import collections
|
||||
|
||||
|
@ -53,8 +52,8 @@ class TclCommandOpenGerber(TclCommandSignaled):
|
|||
# How the object should be initialized
|
||||
def obj_init(gerber_obj, app_obj):
|
||||
|
||||
if not isinstance(gerber_obj, FlatCAMGerber):
|
||||
self.raise_tcl_error('Expected FlatCAMGerber, got %s %s.' % (outname, type(gerber_obj)))
|
||||
if gerber_obj.kind != 'gerber':
|
||||
self.raise_tcl_error('Expected GerberObject, got %s %s.' % (outname, type(gerber_obj)))
|
||||
|
||||
# Opening the file happens here
|
||||
try:
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from tclCommands.TclCommand import TclCommand
|
||||
from FlatCAMObj import FlatCAMGeometry, FlatCAMExcellon
|
||||
|
||||
import shapely.affinity as affinity
|
||||
|
||||
|
@ -153,12 +152,12 @@ class TclCommandPanelize(TclCommand):
|
|||
# objs.append(obj_init)
|
||||
#
|
||||
# def initialize_geometry(obj_init, app):
|
||||
# FlatCAMGeometry.merge(objs, obj_init)
|
||||
# GeometryObject.merge(objs, obj_init)
|
||||
#
|
||||
# def initialize_excellon(obj_init, app):
|
||||
# # merge expects tools to exist in the target object
|
||||
# obj_init.tools = obj.tools.copy()
|
||||
# FlatCAMExcellon.merge(objs, obj_init)
|
||||
# ExcellonObject.merge(objs, obj_init)
|
||||
#
|
||||
# objs = []
|
||||
# if obj is not None:
|
||||
|
@ -167,7 +166,7 @@ class TclCommandPanelize(TclCommand):
|
|||
# currentx = 0
|
||||
# for col in range(columns):
|
||||
# local_outname = outname + ".tmp." + str(col) + "." + str(row)
|
||||
# if isinstance(obj, FlatCAMExcellon):
|
||||
# if isinstance(obj, ExcellonObject):
|
||||
# self.app.new_object("excellon", local_outname, initialize_local_excellon, plot=False,
|
||||
# autoselected=False)
|
||||
# else:
|
||||
|
@ -177,7 +176,7 @@ class TclCommandPanelize(TclCommand):
|
|||
# currentx += lenghtx
|
||||
# currenty += lenghty
|
||||
#
|
||||
# if isinstance(obj, FlatCAMExcellon):
|
||||
# if isinstance(obj, ExcellonObject):
|
||||
# self.app.new_object("excellon", outname, initialize_excellon)
|
||||
# else:
|
||||
# self.app.new_object("geometry", outname, initialize_geometry)
|
||||
|
@ -258,7 +257,7 @@ class TclCommandPanelize(TclCommand):
|
|||
|
||||
obj_fin.solid_geometry = []
|
||||
|
||||
if isinstance(obj, FlatCAMGeometry):
|
||||
if obj.kind == 'geometry':
|
||||
obj_fin.multigeo = obj.multigeo
|
||||
obj_fin.tools = deepcopy(obj.tools)
|
||||
if obj.multigeo is True:
|
||||
|
@ -269,7 +268,7 @@ class TclCommandPanelize(TclCommand):
|
|||
currentx = 0.0
|
||||
|
||||
for col in range(columns):
|
||||
if isinstance(obj, FlatCAMGeometry):
|
||||
if obj.kind == 'geometry':
|
||||
if obj.multigeo is True:
|
||||
for tool in obj.tools:
|
||||
obj_fin.tools[tool]['solid_geometry'].append(translate_recursion(
|
||||
|
@ -287,7 +286,7 @@ class TclCommandPanelize(TclCommand):
|
|||
currentx += lenghtx
|
||||
currenty += lenghty
|
||||
|
||||
if isinstance(obj, FlatCAMExcellon):
|
||||
if obj.kind == 'excellon':
|
||||
self.app.new_object("excellon", outname, job_init_excellon, plot=False, autoselected=True)
|
||||
else:
|
||||
self.app.new_object("geometry", outname, job_init_geometry, plot=False, autoselected=True)
|
||||
|
|
Loading…
Reference in New Issue