Merged marius_stanciu/flatcam_beta/Beta_8.994 into Beta_unstable

This commit is contained in:
Marius Stanciu 2020-10-26 13:21:10 +02:00
commit 5a4422d3ba
90 changed files with 40263 additions and 60915 deletions

View File

@ -7,6 +7,70 @@ CHANGELOG for FlatCAM beta
=================================================
26.10.2020
- added a new menu entry and functionality in the View category: enable all non-selected (shortcut key ALT+3)
- fixed shortcut keys for a number of functionality and in some cases added some new
- fixed the enable/disable all plots functionality
- fixed issue with the app window restored in a shifted position after doing Fullscreen
- fixed issue with coords, delta_coords and status toolbars being disabled when entering fullscreen mode and remaining disabled after restore to normal mode
- changed some of the strings (added a few in the How To section)
25.10.2020
- updated the Italian translation (by Massimiliano Golfetto)
- finished the update of the Spanish translation (Google translate)
24.10.2020
- added a new GUI element, an InputDialog made out of FCSliderWithSpinner named FCInputDialogSlider
- replaced the InputDialog in the Opacity pop menu for the objects in the Project Tab with a FCInputDialogSlider
- minor changes
- UI changes in the AppTextEditor and in CNCJob properties tab and in GCoe Editor
- some changes in strings; updated all the translation strings to the latest changes
- finished the Romanian translation
- created two new preprocessors (from 'default' and from 'grbl_11') that will have no toolchange commands regardless of the settings in the software
- updated the Turkish translation (by Mehmet Kaya)
- the methods of the APP class that were the handlers for the File menu are now moved to their own class
- fixed some of the Tcl Commands that depended on the methods refactored above
- reverted the preprocessors with no toolchange commands to the original but removed the M6 toolchange command
- fixed newly introduced issue when doing File -> Print(PDF)
- fixed newly introduced issues with SysTray and Splash
- added ability for the app to detect the current DPI used on the screen; applied this information in the Film Tool when exporting PNG files
- found that Pillow v >= 7.2 breaks Reportlab 3.5.53 (latest version) and creates an error in Film Tool when exporting PNG files. Pillow 7.2 still works.
23.10.2020
- updated Copper Thieving Tool to work with the updated program
- updated Rules Check Tool - Hole Size rule to work with the new data structure for the Excellon objects
- updated Rules Check Tool - added an activity message
- updated some strings, updated the translation strings
- commented the ToolsDB class since it is not used currently
- some minor changes in the AppTextEditor.py file
- removed Hungarian language since it's looking like is no longer being translated
- added a default properties tab which will hold a set of information's about the application
- minor changes in the Properties Tool
- Excellon UI: fixed a small issue with toggling all rows in Tools Table not toggling off and also the milling section in Utilities was not updated
- some refactoring in the keys of the defaults dictionary
- fixed an ambiguity in the Tools Database GUI elements
22.10.2020
- added a message to show if voronoi_diagram method can be used (require Shapely >= 1.8)
- modified behind the scene the UI for Tool Subtract
- modified some strings and updated the translation strings
- in NCC Tool added a check for the validity of the used tools; its only informative
- in NCC Tool done some refactoring
- in NCC Tool fixed a bug when using Rest Machining; optimizations
- in NCC Tool fixed a UI issue
- updated the Turkish translation (by Mehmet Kaya)
- small change in the CNCJob UI by replacing the AL checkbox with a checkable QButton
- disabled the Autolevelling feature in CNCJob due of being not finished and missing also a not-yet-released package: Shapely v 1.8
- added some new strings for translation and updated the translation strings
- in ToolsDB2UI class made the vertical layouts have a preferred minimum dimension as opposed to the previous fixed one
- in Geometry Object made sure that the Tools Table second column is set to Resize to contents
- fixed a bug in Tool PunchGerber when using an Excellon to punch holes in the Gerber apertures
21.10.2020
- in Geometry Object fixed the issue with not using the End X-Y value and also made some other updates here
@ -28,6 +92,7 @@ CHANGELOG for FlatCAM beta
- optimized a bit the UI for Gerber/Excellon/Geometry objects
- optimized FlatCAMObj.add_properties_items() method
- updated the Turkish translation (by Mehmet Kaya)
- added ability to run a callback function with callback_parameters after a new FlatCAM object is created
20.10.2020

View File

@ -90,6 +90,6 @@ if __name__ == '__main__':
style = settings.value('style', type=str)
app.setStyle(style)
fc = App()
fc = App(qapp=app)
sys.exit(app.exec_())
# app.exec_()

File diff suppressed because it is too large Load Diff

View File

@ -1978,9 +1978,9 @@ class AppExcEditor(QtCore.QObject):
self.e_ui.tools_table_exc.clearSelection()
# Remove anything else in the GUI Selected Tab
self.app.ui.selected_scroll_area.takeWidget()
self.app.ui.properties_scroll_area.takeWidget()
# Put ourselves in the GUI Properties Tab
self.app.ui.selected_scroll_area.setWidget(self.e_ui.exc_edit_widget)
self.app.ui.properties_scroll_area.setWidget(self.e_ui.exc_edit_widget)
# Switch notebook to Properties page
self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab)
@ -2868,10 +2868,10 @@ class AppExcEditor(QtCore.QObject):
try:
edited_obj = self.app.app_obj.new_object("excellon", outname, obj_init)
edited_obj.source_file = self.app.export_excellon(obj_name=edited_obj.options['name'],
local_use=edited_obj,
filename=None,
use_thread=False)
edited_obj.source_file = self.app.f_handlers.export_excellon(obj_name=edited_obj.options['name'],
local_use=edited_obj,
filename=None,
use_thread=False)
except Exception as e:
self.deactivate()
log.error("Error on Edited object creation: %s" % str(e))

View File

@ -310,7 +310,7 @@ class TextInputTool(AppTool):
self.font_italic_tb.setIcon(QtGui.QIcon(self.app.resource_location + '/italic32.png'))
hlay.addWidget(self.font_italic_tb)
self.form_layout.addRow(FCLabel('%s:' % "Size"), hlay)
self.form_layout.addRow(FCLabel('%s:' % _("Size")), hlay)
# Text input
self.text_input_entry = FCTextAreaRich()
@ -547,33 +547,33 @@ class PaintOptionsTool(AppTool):
def set_tool_ui(self):
# Init appGUI
if self.app.defaults["tools_painttooldia"]:
self.painttooldia_entry.set_value(self.app.defaults["tools_painttooldia"])
if self.app.defaults["tools_paint_tooldia"]:
self.painttooldia_entry.set_value(self.app.defaults["tools_paint_tooldia"])
else:
self.painttooldia_entry.set_value(0.0)
if self.app.defaults["tools_paintoverlap"]:
self.paintoverlap_entry.set_value(self.app.defaults["tools_paintoverlap"])
if self.app.defaults["tools_paint_overlap"]:
self.paintoverlap_entry.set_value(self.app.defaults["tools_paint_overlap"])
else:
self.paintoverlap_entry.set_value(0.0)
if self.app.defaults["tools_paintoffset"]:
self.paintmargin_entry.set_value(self.app.defaults["tools_paintoffset"])
if self.app.defaults["tools_paint_offset"]:
self.paintmargin_entry.set_value(self.app.defaults["tools_paint_offset"])
else:
self.paintmargin_entry.set_value(0.0)
if self.app.defaults["tools_paintmethod"]:
self.paintmethod_combo.set_value(self.app.defaults["tools_paintmethod"])
if self.app.defaults["tools_paint_method"]:
self.paintmethod_combo.set_value(self.app.defaults["tools_paint_method"])
else:
self.paintmethod_combo.set_value(_("Seed"))
if self.app.defaults["tools_pathconnect"]:
self.pathconnect_cb.set_value(self.app.defaults["tools_pathconnect"])
if self.app.defaults["tools_paint_connect"]:
self.pathconnect_cb.set_value(self.app.defaults["tools_paint_connect"])
else:
self.pathconnect_cb.set_value(False)
if self.app.defaults["tools_paintcontour"]:
self.paintcontour_cb.set_value(self.app.defaults["tools_paintcontour"])
if self.app.defaults["tools_paint_contour"]:
self.paintcontour_cb.set_value(self.app.defaults["tools_paint_contour"])
else:
self.paintcontour_cb.set_value(False)
@ -3419,57 +3419,15 @@ class AppGeoEditor(QtCore.QObject):
self.rtree_index = rtindex.Index()
def entry2option(opt, entry):
"""
:param opt: A option from the self.options dictionary
:param entry: A GUI element which text value is used
:return:
"""
try:
text_value = entry.text()
if ',' in text_value:
text_value = text_value.replace(',', '.')
self.options[opt] = float(text_value)
except Exception as e:
entry.set_value(self.app.defaults[opt])
log.debug("AppGeoEditor.__init__().entry2option() --> %s" % str(e))
return
def grid_changed(goption, gentry):
"""
:param goption: String. Can be either 'global_gridx' or 'global_gridy'
:param gentry: A GUI element which text value is read and used
:return:
"""
if goption not in ['global_gridx', 'global_gridy']:
return
entry2option(opt=goption, entry=gentry)
# if the grid link is checked copy the value in the GridX field to GridY
try:
text_value = gentry.text()
if ',' in text_value:
text_value = text_value.replace(',', '.')
val = float(text_value)
except ValueError:
return
if self.app.ui.grid_gap_link_cb.isChecked():
self.app.ui.grid_gap_y_entry.set_value(val, decimals=self.decimals)
self.app.ui.grid_gap_x_entry.setValidator(QtGui.QDoubleValidator())
self.app.ui.grid_gap_x_entry.textChanged.connect(
lambda: grid_changed("global_gridx", self.app.ui.grid_gap_x_entry))
self.app.ui.grid_gap_x_entry.textChanged.connect(self.on_gridx_val_changed)
self.app.ui.grid_gap_y_entry.setValidator(QtGui.QDoubleValidator())
self.app.ui.grid_gap_y_entry.textChanged.connect(
lambda: entry2option("global_gridy", self.app.ui.grid_gap_y_entry))
self.app.ui.grid_gap_y_entry.textChanged.connect(self.on_gridy_val_changed)
self.app.ui.snap_max_dist_entry.setValidator(QtGui.QDoubleValidator())
self.app.ui.snap_max_dist_entry.textChanged.connect(
lambda: entry2option("snap_max", self.app.ui.snap_max_dist_entry))
lambda: self.entry2option("snap_max", self.app.ui.snap_max_dist_entry))
# if using Paint store here the tool diameter used
self.paint_tooldia = None
@ -3522,15 +3480,65 @@ class AppGeoEditor(QtCore.QObject):
self.delete_selected()
self.replot()
def entry2option(self, opt, entry):
"""
:param opt: A option from the self.options dictionary
:param entry: A GUI element which text value is used
:return:
"""
try:
text_value = entry.text()
if ',' in text_value:
text_value = text_value.replace(',', '.')
self.options[opt] = float(text_value)
except Exception as e:
entry.set_value(self.app.defaults[opt])
log.debug("AppGeoEditor.__init__().entry2option() --> %s" % str(e))
return
def grid_changed(self, goption, gentry):
"""
:param goption: String. Can be either 'global_gridx' or 'global_gridy'
:param gentry: A GUI element which text value is read and used
:return:
"""
if goption not in ['global_gridx', 'global_gridy']:
return
self.entry2option(opt=goption, entry=gentry)
# if the grid link is checked copy the value in the GridX field to GridY
try:
text_value = gentry.text()
if ',' in text_value:
text_value = text_value.replace(',', '.')
val = float(text_value)
except ValueError:
return
if self.app.ui.grid_gap_link_cb.isChecked():
self.app.ui.grid_gap_y_entry.set_value(val, decimals=self.decimals)
def on_gridx_val_changed(self):
self.grid_changed("global_gridx", self.app.ui.grid_gap_x_entry)
# try:
# self.app.defaults["global_gridx"] = float(self.app.ui.grid_gap_x_entry.get_value())
# except ValueError:
# return
def on_gridy_val_changed(self):
self.entry2option("global_gridy", self.app.ui.grid_gap_y_entry)
def set_ui(self):
# updated units
self.units = self.app.defaults['units'].upper()
self.decimals = self.app.decimals
# Remove anything else in the GUI Selected Tab
self.app.ui.selected_scroll_area.takeWidget()
self.app.ui.properties_scroll_area.takeWidget()
# Put ourselves in the appGUI Properties Tab
self.app.ui.selected_scroll_area.setWidget(self.geo_edit_widget)
self.app.ui.properties_scroll_area.setWidget(self.geo_edit_widget)
# Switch notebook to Properties page
self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab)
@ -4025,9 +4033,11 @@ class AppGeoEditor(QtCore.QObject):
# make sure that the cursor shape is enabled/disabled, too
if self.options['grid_snap'] is True:
self.app.defaults['global_grid_snap'] = True
self.app.inform[str, bool].emit(_("Grid Snap enabled."), False)
self.app.app_cursor.enabled = True
else:
self.app.defaults['global_grid_snap'] = False
self.app.app_cursor.enabled = False
self.app.inform[str, bool].emit(_("Grid Snap disabled."), False)

View File

@ -3323,9 +3323,9 @@ class AppGerberEditor(QtCore.QObject):
self.apertures_table.clearSelection()
# Remove anything else in the GUI Properties Tab
self.app.ui.selected_scroll_area.takeWidget()
self.app.ui.properties_scroll_area.takeWidget()
# Put ourselves in the GUI Properties Tab
self.app.ui.selected_scroll_area.setWidget(self.grb_edit_widget)
self.app.ui.properties_scroll_area.setWidget(self.grb_edit_widget)
# Switch notebook to Properties page
self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab)
@ -4366,8 +4366,8 @@ class AppGerberEditor(QtCore.QObject):
app_obj.inform.emit(msg)
raise
grb_obj.source_file = self.app.export_gerber(obj_name=out_name, filename=None,
local_use=grb_obj, use_thread=False)
grb_obj.source_file = self.app.f_handlers.export_gerber(obj_name=out_name, filename=None,
local_use=grb_obj, use_thread=False)
with self.app.proc_container.new(_("Creating Gerber.")):
try:

View File

@ -37,6 +37,7 @@ class AppTextEditor(QtWidgets.QWidget):
QtWidgets.QSizePolicy.MinimumExpanding
)
# UI Layout
self.main_editor_layout = QtWidgets.QVBoxLayout(self)
self.main_editor_layout.setContentsMargins(0, 0, 0, 0)
@ -48,6 +49,7 @@ class AppTextEditor(QtWidgets.QWidget):
self.work_editor_layout.setContentsMargins(2, 2, 2, 2)
self.t_frame.setLayout(self.work_editor_layout)
# CODE Editor
if self.plain_text:
self.editor_class = FCTextAreaLineNumber()
self.code_editor = self.editor_class.edit
@ -72,90 +74,86 @@ class AppTextEditor(QtWidgets.QWidget):
if text:
self.code_editor.setPlainText(text)
self.buttonPreview = FCButton(_('Print Preview'))
self.buttonPreview.setIcon(QtGui.QIcon(self.app.resource_location + '/preview32.png'))
self.buttonPreview.setToolTip(_("Open a OS standard Preview Print window."))
self.buttonPreview.setMinimumWidth(100)
# #############################################################################################################
# UI SETUP
# #############################################################################################################
control_lay = QtWidgets.QHBoxLayout()
self.work_editor_layout.addLayout(control_lay, 1, 0, 1, 5)
self.buttonPrint = FCButton(_('Print Code'))
self.buttonPrint.setIcon(QtGui.QIcon(self.app.resource_location + '/printer32.png'))
self.buttonPrint.setToolTip(_("Open a OS standard Print window."))
self.buttonPrint.setMinimumWidth(100)
self.buttonFind = FCButton(_('Find in Code'))
# FIND
self.buttonFind = FCButton(_('Find'))
self.buttonFind.setIcon(QtGui.QIcon(self.app.resource_location + '/find32.png'))
self.buttonFind.setToolTip(_("Will search and highlight in yellow the string in the Find box."))
self.buttonFind.setMinimumWidth(100)
control_lay.addWidget(self.buttonFind)
# Entry FIND
self.entryFind = FCEntry()
self.entryFind.setToolTip(_("Find box. Enter here the strings to be searched in the text."))
control_lay.addWidget(self.entryFind)
# REPLACE
self.buttonReplace = FCButton(_('Replace With'))
self.buttonReplace.setIcon(QtGui.QIcon(self.app.resource_location + '/replace32.png'))
self.buttonReplace.setToolTip(_("Will replace the string from the Find box with the one in the Replace box."))
self.buttonReplace.setMinimumWidth(100)
control_lay.addWidget(self.buttonReplace)
# Entry REPLACE
self.entryReplace = FCEntry()
self.entryReplace.setToolTip(_("String to replace the one in the Find box throughout the text."))
control_lay.addWidget(self.entryReplace)
# Select All
self.sel_all_cb = QtWidgets.QCheckBox(_('All'))
self.sel_all_cb.setToolTip(_("When checked it will replace all instances in the 'Find' box\n"
"with the text in the 'Replace' box.."))
control_lay.addWidget(self.sel_all_cb)
self.button_copy_all = FCButton(_('Copy All'))
self.button_copy_all.setIcon(QtGui.QIcon(self.app.resource_location + '/copy_file32.png'))
self.button_copy_all.setToolTip(_("Will copy all the text in the Code Editor to the clipboard."))
self.button_copy_all.setMinimumWidth(100)
# COPY All
# self.button_copy_all = FCButton(_('Copy All'))
# self.button_copy_all.setIcon(QtGui.QIcon(self.app.resource_location + '/copy_file32.png'))
# self.button_copy_all.setToolTip(_("Will copy all the text in the Code Editor to the clipboard."))
# control_lay.addWidget(self.button_copy_all)
# Update
self.button_update_code = QtWidgets.QToolButton()
self.button_update_code.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
self.button_update_code.setToolTip(_("Save changes internally."))
self.button_update_code.hide()
control_lay.addWidget(self.button_update_code)
self.buttonOpen = FCButton(_('Open Code'))
# Print PREVIEW
self.buttonPreview = QtWidgets.QToolButton()
self.buttonPreview.setIcon(QtGui.QIcon(self.app.resource_location + '/preview32.png'))
self.buttonPreview.setToolTip(_("Open a OS standard Preview Print window."))
control_lay.addWidget(self.buttonPreview)
# PRINT
self.buttonPrint = QtWidgets.QToolButton()
self.buttonPrint.setIcon(QtGui.QIcon(self.app.resource_location + '/printer32.png'))
self.buttonPrint.setToolTip(_("Open a OS standard Print window."))
control_lay.addWidget(self.buttonPrint)
# OPEN
self.buttonOpen = QtWidgets.QToolButton()
self.buttonOpen.setIcon(QtGui.QIcon(self.app.resource_location + '/folder32_bis.png'))
self.buttonOpen.setToolTip(_("Will open a text file in the editor."))
self.buttonOpen.setMinimumWidth(100)
control_lay.addWidget(self.buttonOpen)
self.buttonSave = FCButton(_('Save Code'))
# SAVE
self.buttonSave = QtWidgets.QToolButton()
self.buttonSave.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
self.buttonSave.setToolTip(_("Will save the text in the editor into a file."))
self.buttonSave.setMinimumWidth(100)
control_lay.addWidget(self.buttonSave)
self.buttonRun = FCButton(_('Run Code'))
# RUN
self.buttonRun = FCButton(_('Run'))
self.buttonRun.setToolTip(_("Will run the TCL commands found in the text file, one by one."))
self.buttonRun.setMinimumWidth(100)
self.buttonRun.hide()
control_lay.addWidget(self.buttonRun)
editor_hlay_1 = QtWidgets.QHBoxLayout()
# cnc_tab_lay_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
editor_hlay_1.addWidget(self.buttonFind)
editor_hlay_1.addWidget(self.entryFind)
editor_hlay_1.addWidget(self.buttonReplace)
editor_hlay_1.addWidget(self.entryReplace)
editor_hlay_1.addWidget(self.sel_all_cb)
editor_hlay_1.addWidget(self.button_copy_all)
editor_hlay_1.addWidget(self.button_update_code)
self.work_editor_layout.addLayout(editor_hlay_1, 1, 0, 1, 5)
editor_hlay_2 = QtWidgets.QHBoxLayout()
editor_hlay_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
editor_hlay_2.addWidget(self.buttonPreview)
editor_hlay_2.addWidget(self.buttonPrint)
self.work_editor_layout.addLayout(editor_hlay_2, 2, 0, 1, 1, QtCore.Qt.AlignLeft)
cnc_tab_lay_4 = QtWidgets.QHBoxLayout()
cnc_tab_lay_4.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
cnc_tab_lay_4.addWidget(self.buttonOpen)
cnc_tab_lay_4.addWidget(self.buttonSave)
cnc_tab_lay_4.addWidget(self.buttonRun)
self.work_editor_layout.addLayout(cnc_tab_lay_4, 2, 4, 1, 1)
# #################################################################################
# ################### SIGNALS #####################################################
# #################################################################################
# #############################################################################################################
# ################### SIGNALS #################################################################################
# #############################################################################################################
self.code_editor.textChanged.connect(self.handleTextChanged)
self.buttonOpen.clicked.connect(self.handleOpen)
self.buttonSave.clicked.connect(self.handleSaveGCode)
@ -163,7 +161,7 @@ class AppTextEditor(QtWidgets.QWidget):
self.buttonPreview.clicked.connect(self.handlePreview)
self.buttonFind.clicked.connect(self.handleFindGCode)
self.buttonReplace.clicked.connect(self.handleReplaceGCode)
self.button_copy_all.clicked.connect(self.handleCopyAll)
# self.button_copy_all.clicked.connect(self.handleCopyAll)
self.code_editor.set_model_data(self.app.myKeywords)
@ -173,18 +171,14 @@ class AppTextEditor(QtWidgets.QWidget):
self.callback = callback
def handlePrint(self):
self.app.defaults.report_usage("handlePrint()")
dialog = QtPrintSupport.QPrintDialog()
if dialog.exec_() == QtWidgets.QDialog.Accepted:
if dialog.exec() == QtWidgets.QDialog.Accepted:
self.code_editor.document().print_(dialog.printer())
def handlePreview(self):
self.app.defaults.report_usage("handlePreview()")
dialog = QtPrintSupport.QPrintPreviewDialog()
dialog.paintRequested.connect(self.code_editor.print_)
dialog.exec_()
dialog.paintRequested.connect(self.code_editor.print)
dialog.exec()
def handleTextChanged(self):
# enable = not self.ui.code_editor.document().isEmpty()
@ -368,10 +362,10 @@ class AppTextEditor(QtWidgets.QWidget):
# Mark end of undo block
cursor.endEditBlock()
def handleCopyAll(self):
text = self.code_editor.toPlainText()
self.app.clipboard.setText(text)
self.app.inform.emit(_("Content copied to clipboard ..."))
# def handleCopyAll(self):
# text = self.code_editor.toPlainText()
# self.app.clipboard.setText(text)
# self.app.inform.emit(_("Content copied to clipboard ..."))
# def closeEvent(self, QCloseEvent):
# super().closeEvent(QCloseEvent)

View File

@ -91,9 +91,9 @@ class AppGCodeEditor(QtCore.QObject):
self.ui.prepend_text.set_value(self.app.defaults["cncjob_prepend"])
# Remove anything else in the GUI Properties Tab
self.app.ui.selected_scroll_area.takeWidget()
self.app.ui.properties_scroll_area.takeWidget()
# Put ourselves in the GUI Properties Tab
self.app.ui.selected_scroll_area.setWidget(self.ui.edit_widget)
self.app.ui.properties_scroll_area.setWidget(self.ui.edit_widget)
# Switch notebook to Properties page
self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab)

View File

@ -1687,6 +1687,64 @@ class FCInputDialog(QtWidgets.QInputDialog):
pass
class FCInputDialogSlider(QtWidgets.QDialog):
def __init__(self, parent=None, title=None, text=None, min=None, max=None, step=1, init_val=None):
super().__init__(parent)
self.val = 0.0
self.init_value = init_val if init_val else 0.0
self.setWindowTitle(title) if title else self.setWindowTitle('title')
self.text = text if text else 'text'
self.min = min if min else 0
self.max = max if max else 255
self.step = step if step else 1
self.lbl = FCLabel(self.text)
self.wdg = FCSliderWithSpinner(min=self.min, max=self.max, step=self.step)
self.wdg.set_value(self.init_value)
QBtn = QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel
self.buttonBox = QtWidgets.QDialogButtonBox(QBtn)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.lbl)
self.layout.addWidget(self.wdg)
self.layout.addWidget(self.buttonBox)
self.setLayout(self.layout)
def set_title(self, txt):
self.setWindowTitle(txt)
def set_text(self, txt):
self.lbl.set_value(txt)
def set_min(self, val):
self.wdg.spinner.setMinimum(val)
def set_max(self, val):
self.wdg.spinner.setMaximum(val)
def set_range(self, min, max):
self.wdg.spinner.set_range(min, max)
def set_step(self, val):
self.wdg.spinner.set_step(val)
def get_results(self):
if self.exec_() == QtWidgets.QDialog.Accepted:
return self.wdg.get_value(), True
else:
return None, False
class FCButton(QtWidgets.QPushButton):
def __init__(self, text=None, checkable=None, click_callback=None, parent=None):
super(FCButton, self).__init__(text, parent)
@ -3790,10 +3848,10 @@ class FlatCAMSystemTray(QtWidgets.QSystemTrayIcon):
self.menu_open.addSeparator()
menu_openproject.triggered.connect(self.app.on_file_openproject)
menu_opengerber.triggered.connect(self.app.on_fileopengerber)
menu_openexcellon.triggered.connect(self.app.on_fileopenexcellon)
menu_opengcode.triggered.connect(self.app.on_fileopengcode)
menu_openproject.triggered.connect(self.app.f_handlers.on_file_openproject)
menu_opengerber.triggered.connect(self.app.f_handlers.on_fileopengerber)
menu_openexcellon.triggered.connect(self.app.f_handlers.on_fileopenexcellon)
menu_opengcode.triggered.connect(self.app.f_handlers.on_fileopengcode)
exitAction = menu.addAction(_("Exit"))
exitAction.setIcon(QtGui.QIcon(self.app.resource_location + '/power16.png'))

View File

@ -81,14 +81,14 @@ class MainGUI(QtWidgets.QMainWindow):
# New Project
self.menufilenewproject = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/file16.png'),
_('&New Project ...\tCtrl+N'), self)
_('New Project ...\tCtrl+N'), self)
self.menufilenewproject.setToolTip(
_("Will create a new, blank project")
)
self.menufile.addAction(self.menufilenewproject)
# New Category (Excellon, Geometry)
self.menufilenew = self.menufile.addMenu(QtGui.QIcon(self.app.resource_location + '/file16.png'), _('&New'))
self.menufilenew = self.menufile.addMenu(QtGui.QIcon(self.app.resource_location + '/file16.png'), _('New'))
self.menufilenew.setToolTipsVisible(True)
self.menufilenewgeo = self.menufilenew.addAction(
@ -120,23 +120,23 @@ class MainGUI(QtWidgets.QMainWindow):
# Open Project ...
self.menufileopenproject = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/folder16.png'), _('Open &Project ...'), self)
QtGui.QIcon(self.app.resource_location + '/folder16.png'), _('Open Project ...'), self)
self.menufile_open.addAction(self.menufileopenproject)
self.menufile_open.addSeparator()
# Open Gerber ...
self.menufileopengerber = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/flatcam_icon24.png'),
_('Open &Gerber ...\tCtrl+G'), self)
_('Open Gerber ...\tCtrl+G'), self)
self.menufile_open.addAction(self.menufileopengerber)
# Open Excellon ...
self.menufileopenexcellon = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/open_excellon32.png'),
_('Open &Excellon ...\tCtrl+E'), self)
_('Open Excellon ...\tCtrl+E'), self)
self.menufile_open.addAction(self.menufileopenexcellon)
# Open G-Code ...
self.menufileopengcode = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/code.png'), _('Open G-&Code ...'), self)
QtGui.QIcon(self.app.resource_location + '/code.png'), _('Open G-Code ...'), self)
self.menufile_open.addAction(self.menufileopengcode)
self.menufile_open.addSeparator()
@ -157,17 +157,17 @@ class MainGUI(QtWidgets.QMainWindow):
# Save Project
self.menufilesaveproject = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/floppy16.png'), _('&Save Project ...\tCtrl+S'), self)
QtGui.QIcon(self.app.resource_location + '/floppy16.png'), _('Save Project ...\tCtrl+S'), self)
self.menufile_save.addAction(self.menufilesaveproject)
# Save Project As ...
self.menufilesaveprojectas = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/floppy16.png'), _('Save Project &As ...\tCtrl+Shift+S'), self)
QtGui.QIcon(self.app.resource_location + '/floppy16.png'), _('Save Project As ...\tCtrl+Shift+S'), self)
self.menufile_save.addAction(self.menufilesaveprojectas)
# Save Project Copy ...
# self.menufilesaveprojectcopy = QtWidgets.QAction(
# QtGui.QIcon(self.app.resource_location + '/floppy16.png'), _('Save Project C&opy ...'), self)
# QtGui.QIcon(self.app.resource_location + '/floppy16.png'), _('Save Project Copy ...'), self)
# self.menufile_save.addAction(self.menufilesaveprojectcopy)
self.menufile_save.addSeparator()
@ -206,18 +206,18 @@ class MainGUI(QtWidgets.QMainWindow):
self.menufileimport = self.menufile.addMenu(
QtGui.QIcon(self.app.resource_location + '/import.png'), _('Import'))
self.menufileimportsvg = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/svg16.png'), _('&SVG as Geometry Object ...'), self)
QtGui.QIcon(self.app.resource_location + '/svg16.png'), _('SVG as Geometry Object ...'), self)
self.menufileimport.addAction(self.menufileimportsvg)
self.menufileimportsvg_as_gerber = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/svg16.png'), _('&SVG as Gerber Object ...'), self)
QtGui.QIcon(self.app.resource_location + '/svg16.png'), _('SVG as Gerber Object ...'), self)
self.menufileimport.addAction(self.menufileimportsvg_as_gerber)
self.menufileimport.addSeparator()
self.menufileimportdxf = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/dxf16.png'), _('&DXF as Geometry Object ...'), self)
QtGui.QIcon(self.app.resource_location + '/dxf16.png'), _('DXF as Geometry Object ...'), self)
self.menufileimport.addAction(self.menufileimportdxf)
self.menufileimportdxf_as_gerber = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/dxf16.png'), _('&DXF as Gerber Object ...'), self)
QtGui.QIcon(self.app.resource_location + '/dxf16.png'), _('DXF as Gerber Object ...'), self)
self.menufileimport.addAction(self.menufileimportdxf_as_gerber)
self.menufileimport.addSeparator()
self.menufileimport_hpgl2_as_geo = QtWidgets.QAction(
@ -231,7 +231,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.menufileexport.setToolTipsVisible(True)
self.menufileexportsvg = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/export.png'), _('Export &SVG ...'), self)
QtGui.QIcon(self.app.resource_location + '/export.png'), _('Export SVG ...'), self)
self.menufileexport.addAction(self.menufileexportsvg)
self.menufileexportdxf = QtWidgets.QAction(
@ -241,7 +241,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.menufileexport.addSeparator()
self.menufileexportpng = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/export_png32.png'), _('Export &PNG ...'), self)
QtGui.QIcon(self.app.resource_location + '/export_png32.png'), _('Export PNG ...'), self)
self.menufileexportpng.setToolTip(
_("Will export an image in PNG format,\n"
"the saved image will contain the visual \n"
@ -252,7 +252,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.menufileexport.addSeparator()
self.menufileexportexcellon = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/drill32.png'), _('Export &Excellon ...'), self)
QtGui.QIcon(self.app.resource_location + '/drill32.png'), _('Export Excellon ...'), self)
self.menufileexportexcellon.setToolTip(
_("Will export an Excellon Object as Excellon file,\n"
"the coordinates format, the file units and zeros\n"
@ -261,7 +261,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.menufileexport.addAction(self.menufileexportexcellon)
self.menufileexportgerber = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/flatcam_icon32.png'), _('Export &Gerber ...'), self)
QtGui.QIcon(self.app.resource_location + '/flatcam_icon32.png'), _('Export Gerber ...'), self)
self.menufileexportgerber.setToolTip(
_("Will export an Gerber Object as Gerber file,\n"
"the coordinates format, the file units and zeros\n"
@ -306,7 +306,7 @@ class MainGUI(QtWidgets.QMainWindow):
# Quit
self.menufile_exit = QtWidgets.QAction(
QtGui.QIcon(self.app.resource_location + '/power16.png'), _('E&xit'), self)
QtGui.QIcon(self.app.resource_location + '/power16.png'), _('Exit'), self)
# exitAction.setShortcut('Ctrl+Q')
# exitAction.setStatusTip('Exit application')
self.menufile.addAction(self.menufile_exit)
@ -361,7 +361,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.menuedit_join = self.menuedit.addMenu(
QtGui.QIcon(self.app.resource_location + '/join16.png'), _('Join Objects'))
self.menuedit_join2geo = self.menuedit_join.addAction(
QtGui.QIcon(self.app.resource_location + '/join16.png'), _('&Join Geo/Gerber/Exc -> Geo'))
QtGui.QIcon(self.app.resource_location + '/join16.png'), _('Join Geo/Gerber/Exc -> Geo'))
self.menuedit_join2geo.setToolTip(
_("Merge a selection of objects, which can be of type:\n"
"- Gerber\n"
@ -385,17 +385,17 @@ class MainGUI(QtWidgets.QMainWindow):
# Separator
self.menuedit.addSeparator()
self.menueditcopyobject = self.menuedit.addAction(
QtGui.QIcon(self.app.resource_location + '/copy.png'), _('&Copy\tCtrl+C'))
QtGui.QIcon(self.app.resource_location + '/copy.png'), _('Copy\tCtrl+C'))
# Separator
self.menuedit.addSeparator()
self.menueditdelete = self.menuedit.addAction(
QtGui.QIcon(self.app.resource_location + '/trash16.png'), _('&Delete\tDEL'))
QtGui.QIcon(self.app.resource_location + '/trash16.png'), _('Delete\tDEL'))
# Separator
self.menuedit.addSeparator()
self.menueditorigin = self.menuedit.addAction(
QtGui.QIcon(self.app.resource_location + '/origin16.png'), _('Se&t Origin\tO'))
QtGui.QIcon(self.app.resource_location + '/origin16.png'), _('Set Origin\tO'))
self.menuedit_move2origin = self.menuedit.addAction(
QtGui.QIcon(self.app.resource_location + '/origin2_16.png'), _('Move to Origin\tShift+O'))
@ -409,12 +409,12 @@ class MainGUI(QtWidgets.QMainWindow):
self.menuedittoggleunits = self.menuedit.addAction(
QtGui.QIcon(self.app.resource_location + '/toggle_units16.png'), _('Toggle Units\tQ'))
self.menueditselectall = self.menuedit.addAction(
QtGui.QIcon(self.app.resource_location + '/select_all.png'), _('&Select All\tCtrl+A'))
QtGui.QIcon(self.app.resource_location + '/select_all.png'), _('Select All\tCtrl+A'))
# Separator
self.menuedit.addSeparator()
self.menueditpreferences = self.menuedit.addAction(
QtGui.QIcon(self.app.resource_location + '/pref.png'), _('&Preferences\tShift+P'))
QtGui.QIcon(self.app.resource_location + '/pref.png'), _('Preferences\tShift+P'))
# ########################################################################
# ########################## OPTIONS # ###################################
@ -422,21 +422,21 @@ class MainGUI(QtWidgets.QMainWindow):
self.menuoptions = self.menu.addMenu(_('Options'))
self.menuoptions_transform_rotate = self.menuoptions.addAction(
QtGui.QIcon(self.app.resource_location + '/rotate.png'), _("&Rotate Selection\tShift+(R)"))
QtGui.QIcon(self.app.resource_location + '/rotate.png'), _("Rotate Selection\tShift+(R)"))
# Separator
self.menuoptions.addSeparator()
self.menuoptions_transform_skewx = self.menuoptions.addAction(
QtGui.QIcon(self.app.resource_location + '/skewX.png'), _("&Skew on X axis\tShift+X"))
QtGui.QIcon(self.app.resource_location + '/skewX.png'), _("Skew on X axis\tShift+X"))
self.menuoptions_transform_skewy = self.menuoptions.addAction(
QtGui.QIcon(self.app.resource_location + '/skewY.png'), _("S&kew on Y axis\tShift+Y"))
QtGui.QIcon(self.app.resource_location + '/skewY.png'), _("Skew on Y axis\tShift+Y"))
# Separator
self.menuoptions.addSeparator()
self.menuoptions_transform_flipx = self.menuoptions.addAction(
QtGui.QIcon(self.app.resource_location + '/flipx.png'), _("Flip on &X axis\tX"))
QtGui.QIcon(self.app.resource_location + '/flipx.png'), _("Flip on X axis\tX"))
self.menuoptions_transform_flipy = self.menuoptions.addAction(
QtGui.QIcon(self.app.resource_location + '/flipy.png'), _("Flip on &Y axis\tY"))
QtGui.QIcon(self.app.resource_location + '/flipy.png'), _("Flip on Y axis\tY"))
# Separator
self.menuoptions.addSeparator()
@ -455,16 +455,19 @@ class MainGUI(QtWidgets.QMainWindow):
QtGui.QIcon(self.app.resource_location + '/replot16.png'), _('Enable all plots\tAlt+1'))
self.menuviewdisableall = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/clear_plot16.png'), _('Disable all plots\tAlt+2'))
self.menuviewenableother = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/replot16.png'), _('Enable non-selected\tAlt+3'))
self.menuviewdisableother = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/clear_plot16.png'), _('Disable non-selected\tAlt+3'))
QtGui.QIcon(self.app.resource_location + '/clear_plot16.png'), _('Disable non-selected\tAlt+4'))
# Separator
self.menuview.addSeparator()
self.menuview_zoom_fit = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/zoom_fit32.png'), _("&Zoom Fit\tV"))
QtGui.QIcon(self.app.resource_location + '/zoom_fit32.png'), _("Zoom Fit\tV"))
self.menuview_zoom_in = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/zoom_in32.png'), _("&Zoom In\t="))
QtGui.QIcon(self.app.resource_location + '/zoom_in32.png'), _("Zoom In\t="))
self.menuview_zoom_out = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/zoom_out32.png'), _("&Zoom Out\t-"))
QtGui.QIcon(self.app.resource_location + '/zoom_out32.png'), _("Zoom Out\t-"))
self.menuview.addSeparator()
# Replot all
@ -476,23 +479,23 @@ class MainGUI(QtWidgets.QMainWindow):
QtGui.QIcon(self.app.resource_location + '/code_editor32.png'), _('Toggle Code Editor\tShift+E'))
self.menuview.addSeparator()
self.menuview_toggle_fscreen = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/fscreen32.png'), _("&Toggle FullScreen\tAlt+F10"))
QtGui.QIcon(self.app.resource_location + '/fscreen32.png'), _("Toggle FullScreen\tAlt+F10"))
self.menuview_toggle_parea = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/plot32.png'), _("&Toggle Plot Area\tCtrl+F10"))
QtGui.QIcon(self.app.resource_location + '/plot32.png'), _("Toggle Plot Area\tCtrl+F10"))
self.menuview_toggle_notebook = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/notebook32.png'), _("&Toggle Project/Sel/Tool\t`"))
QtGui.QIcon(self.app.resource_location + '/notebook32.png'), _("Toggle Project/Sel/Tool\t`"))
self.menuview.addSeparator()
self.menuview_toggle_grid = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/grid32.png'), _("&Toggle Grid Snap\tG"))
QtGui.QIcon(self.app.resource_location + '/grid32.png'), _("Toggle Grid Snap\tG"))
self.menuview_toggle_grid_lines = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/grid_lines32.png'), _("&Toggle Grid Lines\tAlt+G"))
QtGui.QIcon(self.app.resource_location + '/grid_lines32.png'), _("Toggle Grid Lines\tShift+G"))
self.menuview_toggle_axis = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/axis32.png'), _("&Toggle Axis\tShift+G"))
QtGui.QIcon(self.app.resource_location + '/axis32.png'), _("Toggle Axis\tShift+A"))
self.menuview_toggle_workspace = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/workspace24.png'), _("Toggle Workspace\tShift+W"))
self.menuview_toggle_hud = self.menuview.addAction(
QtGui.QIcon(self.app.resource_location + '/hud_32.png'), _("Toggle HUD\tAlt+H"))
QtGui.QIcon(self.app.resource_location + '/hud_32.png'), _("Toggle HUD\tShift+H"))
# ########################################################################
# ########################## Objects # ###################################
@ -511,7 +514,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.menutool = QtWidgets.QMenu(_('Tool'))
self.menutoolaction = self.menu.addMenu(self.menutool)
self.menutoolshell = self.menutool.addAction(
QtGui.QIcon(self.app.resource_location + '/shell16.png'), _('&Command Line\tS'))
QtGui.QIcon(self.app.resource_location + '/shell16.png'), _('Command Line\tS'))
# ########################################################################
# ########################## Help # ######################################
@ -545,7 +548,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.menuhelp.addSeparator()
self.menuhelp_readme = self.menuhelp.addAction(
QtGui.QIcon(self.app.resource_location + '/warning.png'), _('How To'))
QtGui.QIcon(self.app.resource_location + '/warning.png'), _("How To"))
self.menuhelp_about = self.menuhelp.addAction(
QtGui.QIcon(self.app.resource_location + '/about32.png'), _('About FlatCAM'))
@ -873,7 +876,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.copy_btn = self.toolbaredit.addAction(
QtGui.QIcon(self.app.resource_location + '/copy_file32.png'), _("Copy"))
self.delete_btn = self.toolbaredit.addAction(
QtGui.QIcon(self.app.resource_location + '/trash32.png'), _("&Delete"))
QtGui.QIcon(self.app.resource_location + '/trash32.png'), _("Delete"))
self.toolbaredit.addSeparator()
self.distance_btn = self.toolbaredit.addAction(
QtGui.QIcon(self.app.resource_location + '/distance32.png'), _("Distance Tool"))
@ -893,9 +896,9 @@ class MainGUI(QtWidgets.QMainWindow):
# ########################## View Toolbar# ###############################
# ########################################################################
self.replot_btn = self.toolbarview.addAction(
QtGui.QIcon(self.app.resource_location + '/replot32.png'), _("&Replot"))
QtGui.QIcon(self.app.resource_location + '/replot32.png'), _("Replot"))
self.clear_plot_btn = self.toolbarview.addAction(
QtGui.QIcon(self.app.resource_location + '/clear_plot32.png'), _("&Clear plot"))
QtGui.QIcon(self.app.resource_location + '/clear_plot32.png'), _("Clear plot"))
self.zoom_in_btn = self.toolbarview.addAction(
QtGui.QIcon(self.app.resource_location + '/zoom_in32.png'), _("Zoom In"))
self.zoom_out_btn = self.toolbarview.addAction(
@ -909,7 +912,7 @@ class MainGUI(QtWidgets.QMainWindow):
# ########################## Shell Toolbar# ##############################
# ########################################################################
self.shell_btn = self.toolbarshell.addAction(
QtGui.QIcon(self.app.resource_location + '/shell32.png'), _("&Command Line"))
QtGui.QIcon(self.app.resource_location + '/shell32.png'), _("Command Line"))
self.new_script_btn = self.toolbarshell.addAction(
QtGui.QIcon(self.app.resource_location + '/script_new24.png'), _('New Script ...'))
self.open_script_btn = self.toolbarshell.addAction(
@ -1191,7 +1194,7 @@ class MainGUI(QtWidgets.QMainWindow):
# #######################################################################
# ####################### TCL Shell DOCK ################################
# #######################################################################
self.shell_dock = FCDock("TCL Shell", close_callback=self.toggle_shell_ui)
self.shell_dock = FCDock(_("TCL Shell"), close_callback=self.toggle_shell_ui)
self.shell_dock.setObjectName('Shell_DockWidget')
self.shell_dock.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas)
self.shell_dock.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
@ -1230,9 +1233,9 @@ class MainGUI(QtWidgets.QMainWindow):
self.properties_tab_layout = QtWidgets.QVBoxLayout(self.properties_tab)
self.properties_tab_layout.setContentsMargins(2, 2, 2, 2)
self.selected_scroll_area = VerticalScrollArea()
# self.selected_scroll_area.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.properties_tab_layout.addWidget(self.selected_scroll_area)
self.properties_scroll_area = VerticalScrollArea()
# self.properties_scroll_area.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.properties_tab_layout.addWidget(self.properties_scroll_area)
self.notebook.addTab(self.properties_tab, _("Properties"))
# ########################################################################
@ -1595,18 +1598,18 @@ class MainGUI(QtWidgets.QMainWindow):
self.infobar.addWidget(self.fcinfo, stretch=1)
self.infobar.addWidget(self.delta_coords_toolbar)
self.delta_coords_toolbar.setVisible(self.app.defaults["global_delta_coords_show"])
self.delta_coords_toolbar.setVisible(self.app.defaults["global_delta_coordsbar_show"])
self.infobar.addWidget(self.coords_toolbar)
self.coords_toolbar.setVisible(self.app.defaults["global_coords_show"])
self.coords_toolbar.setVisible(self.app.defaults["global_coordsbar_show"])
self.grid_toolbar.setMaximumHeight(24)
self.infobar.addWidget(self.grid_toolbar)
self.grid_toolbar.setVisible(self.app.defaults["global_grid_show"])
self.grid_toolbar.setVisible(self.app.defaults["global_gridbar_show"])
self.status_toolbar.setMaximumHeight(24)
self.infobar.addWidget(self.status_toolbar)
self.status_toolbar.setVisible(self.app.defaults["global_status_show"])
self.status_toolbar.setVisible(self.app.defaults["global_statusbar_show"])
self.units_label = QtWidgets.QLabel("[mm]")
self.units_label.setToolTip(_("Application units"))
@ -1754,6 +1757,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.y_pos = None
self.width = None
self.height = None
self.titlebar_height = None
self.geom_update[int, int, int, int, int].connect(self.save_geometry)
self.final_save.connect(self.app.final_save)
@ -1887,7 +1891,7 @@ class MainGUI(QtWidgets.QMainWindow):
delta_coords_action = QtWidgets.QAction(self)
delta_coords_action.setCheckable(True)
delta_coords_action.setText(delta_coords_action_name)
delta_coords_action.setChecked(self.app.defaults["global_delta_coords_show"])
delta_coords_action.setChecked(self.app.defaults["global_delta_coordsbar_show"])
self.infobar.addAction(delta_coords_action)
delta_coords_action.triggered.connect(self.toggle_delta_coords)
@ -1895,7 +1899,7 @@ class MainGUI(QtWidgets.QMainWindow):
coords_action = QtWidgets.QAction(self)
coords_action.setCheckable(True)
coords_action.setText(coords_action_name)
coords_action.setChecked(self.app.defaults["global_coords_show"])
coords_action.setChecked(self.app.defaults["global_coordsbar_show"])
self.infobar.addAction(coords_action)
coords_action.triggered.connect(self.toggle_coords)
@ -1903,7 +1907,7 @@ class MainGUI(QtWidgets.QMainWindow):
grid_action = QtWidgets.QAction(self)
grid_action.setCheckable(True)
grid_action.setText(grid_action_name)
grid_action.setChecked(self.app.defaults["global_grid_show"])
grid_action.setChecked(self.app.defaults["global_gridbar_show"])
self.infobar.addAction(grid_action)
grid_action.triggered.connect(self.toggle_gridbar)
@ -1911,24 +1915,24 @@ class MainGUI(QtWidgets.QMainWindow):
status_action = QtWidgets.QAction(self)
status_action.setCheckable(True)
status_action.setText(status_action_name)
status_action.setChecked(self.app.defaults["global_status_show"])
status_action.setChecked(self.app.defaults["global_statusbar_show"])
self.infobar.addAction(status_action)
status_action.triggered.connect(self.toggle_statusbar)
def toggle_coords(self, checked):
self.app.defaults["global_coords_show"] = checked
self.app.defaults["global_coordsbar_show"] = checked
self.coords_toolbar.setVisible(checked)
def toggle_delta_coords(self, checked):
self.app.defaults["global_delta_coords_show"] = checked
self.app.defaults["global_delta_coordsbar_show"] = checked
self.delta_coords_toolbar.setVisible(checked)
def toggle_gridbar(self, checked):
self.app.defaults["global_grid_show"] = checked
self.app.defaults["global_gridbar_show"] = checked
self.grid_toolbar.setVisible(checked)
def toggle_statusbar(self, checked):
self.app.defaults["global_status_show"] = checked
self.app.defaults["global_statusbar_show"] = checked
self.status_toolbar.setVisible(checked)
def eventFilter(self, obj, event):
@ -2031,7 +2035,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.copy_btn = self.toolbaredit.addAction(
QtGui.QIcon(self.app.resource_location + '/copy_file32.png'), _("Copy"))
self.delete_btn = self.toolbaredit.addAction(
QtGui.QIcon(self.app.resource_location + '/trash32.png'), _("&Delete"))
QtGui.QIcon(self.app.resource_location + '/trash32.png'), _("Delete"))
self.toolbaredit.addSeparator()
self.distance_btn = self.toolbaredit.addAction(
QtGui.QIcon(self.app.resource_location + '/distance32.png'), _("Distance Tool"))
@ -2050,9 +2054,9 @@ class MainGUI(QtWidgets.QMainWindow):
# ########################## View Toolbar# ###############################
# ########################################################################
self.replot_btn = self.toolbarview.addAction(
QtGui.QIcon(self.app.resource_location + '/replot32.png'), _("&Replot"))
QtGui.QIcon(self.app.resource_location + '/replot32.png'), _("Replot"))
self.clear_plot_btn = self.toolbarview.addAction(
QtGui.QIcon(self.app.resource_location + '/clear_plot32.png'), _("&Clear plot"))
QtGui.QIcon(self.app.resource_location + '/clear_plot32.png'), _("Clear plot"))
self.zoom_in_btn = self.toolbarview.addAction(
QtGui.QIcon(self.app.resource_location + '/zoom_in32.png'), _("Zoom In"))
self.zoom_out_btn = self.toolbarview.addAction(
@ -2064,7 +2068,7 @@ class MainGUI(QtWidgets.QMainWindow):
# ########################## Shell Toolbar# ##############################
# ########################################################################
self.shell_btn = self.toolbarshell.addAction(
QtGui.QIcon(self.app.resource_location + '/shell32.png'), _("&Command Line"))
QtGui.QIcon(self.app.resource_location + '/shell32.png'), _("Command Line"))
self.new_script_btn = self.toolbarshell.addAction(
QtGui.QIcon(self.app.resource_location + '/script_new24.png'), _('New Script ...'))
self.open_script_btn = self.toolbarshell.addAction(
@ -2083,7 +2087,7 @@ class MainGUI(QtWidgets.QMainWindow):
QtGui.QIcon(self.app.resource_location + '/extract_drill32.png'), _("Extract Drills Tool"))
self.cutout_btn = self.toolbartools.addAction(
QtGui.QIcon(self.app.resource_location + '/cut16_bis.png'), _("&Cutout Tool"))
QtGui.QIcon(self.app.resource_location + '/cut16_bis.png'), _("Cutout Tool"))
self.ncc_btn = self.toolbartools.addAction(
QtGui.QIcon(self.app.resource_location + '/ncc16.png'), _("NCC Tool"))
self.paint_btn = self.toolbartools.addAction(
@ -2321,7 +2325,7 @@ class MainGUI(QtWidgets.QMainWindow):
# CTRL + SHIFT
if modifiers == QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier:
if key == QtCore.Qt.Key_S:
self.app.on_file_saveprojectas()
self.app.f_handlers.on_file_saveprojectas()
return
# CTRL
elif modifiers == QtCore.Qt.ControlModifier:
@ -2346,7 +2350,7 @@ class MainGUI(QtWidgets.QMainWindow):
# Open Excellon file
if key == QtCore.Qt.Key_E:
self.app.on_fileopenexcellon(signal=None)
self.app.f_handlers.on_fileopenexcellon(signal=None)
# Open Gerber file
if key == QtCore.Qt.Key_G:
@ -2354,7 +2358,7 @@ class MainGUI(QtWidgets.QMainWindow):
if 'editor' in widget_name.lower():
self.app.goto_text_line()
else:
self.app.on_fileopengerber(signal=None)
self.app.f_handlers.on_fileopengerber(signal=None)
# Distance Tool
if key == QtCore.Qt.Key_M:
@ -2362,15 +2366,15 @@ class MainGUI(QtWidgets.QMainWindow):
# Create New Project
if key == QtCore.Qt.Key_N:
self.app.on_file_new_click()
self.app.f_handlers.on_file_new_click()
# Open Project
if key == QtCore.Qt.Key_O:
self.app.on_file_openproject(signal=None)
self.app.f_handlers.on_file_openproject(signal=None)
# Open Project
if key == QtCore.Qt.Key_P:
self.app.on_file_save_objects_pdf(use_thread=True)
self.app.f_handlers.on_file_save_objects_pdf(use_thread=True)
# PDF Import
if key == QtCore.Qt.Key_Q:
@ -2389,7 +2393,7 @@ class MainGUI(QtWidgets.QMainWindow):
self.app.tools_db_tab.on_save_tools_db()
return
self.app.on_file_saveproject()
self.app.f_handlers.on_file_saveproject()
# Toggle Plot Area
if key == QtCore.Qt.Key_F10 or key == 'F10':
@ -2399,6 +2403,10 @@ class MainGUI(QtWidgets.QMainWindow):
# SHIFT
elif modifiers == QtCore.Qt.ShiftModifier:
# Toggle axis
if key == QtCore.Qt.Key_A:
self.app.plotcanvas.on_toggle_axis()
# Copy Object Name
if key == QtCore.Qt.Key_C:
self.app.on_copy_name()
@ -2407,9 +2415,10 @@ class MainGUI(QtWidgets.QMainWindow):
if key == QtCore.Qt.Key_E:
self.app.on_toggle_code_editor()
# Toggle axis
# Toggle Grid lines
if key == QtCore.Qt.Key_G:
self.app.plotcanvas.on_toggle_axis()
self.app.plotcanvas.on_toggle_grid_lines()
return
# Toggle HUD (Heads-Up Display)
if key == QtCore.Qt.Key_H:
@ -2435,7 +2444,7 @@ class MainGUI(QtWidgets.QMainWindow):
# Run a Script
if key == QtCore.Qt.Key_S:
self.app.on_filerunscript()
self.app.f_handlers.on_filerunscript()
return
# Toggle Workspace
@ -2464,6 +2473,10 @@ class MainGUI(QtWidgets.QMainWindow):
# Disable all other plots
if key == Qt.Key_3:
self.app.enable_other_plots()
# Disable all other plots
if key == Qt.Key_4:
self.app.disable_other_plots()
# Align in Object Tool
@ -2490,10 +2503,9 @@ class MainGUI(QtWidgets.QMainWindow):
self.app.fiducial_tool.run(toggle=True)
return
# Toggle Grid lines
# Punch Gerber Tool
if key == QtCore.Qt.Key_G:
self.app.plotcanvas.on_toggle_grid_lines()
return
self.app.invert_tool.run(toggle=True)
# Punch Gerber Tool
if key == QtCore.Qt.Key_H:
@ -3677,31 +3689,31 @@ class MainGUI(QtWidgets.QMainWindow):
extension = self.filename.lower().rpartition('.')[-1]
if extension in self.app.grb_list:
self.app.worker_task.emit({'fcn': self.app.open_gerber,
self.app.worker_task.emit({'fcn': self.app.f_handlers.open_gerber,
'params': [self.filename]})
else:
event.ignore()
if extension in self.app.exc_list:
self.app.worker_task.emit({'fcn': self.app.open_excellon,
self.app.worker_task.emit({'fcn': self.app.f_handlers.open_excellon,
'params': [self.filename]})
else:
event.ignore()
if extension in self.app.gcode_list:
self.app.worker_task.emit({'fcn': self.app.open_gcode,
self.app.worker_task.emit({'fcn': self.app.f_handlers.open_gcode,
'params': [self.filename]})
else:
event.ignore()
if extension in self.app.svg_list:
object_type = 'geometry'
self.app.worker_task.emit({'fcn': self.app.import_svg,
self.app.worker_task.emit({'fcn': self.app.f_handlers.import_svg,
'params': [self.filename, object_type, None]})
if extension in self.app.dxf_list:
object_type = 'geometry'
self.app.worker_task.emit({'fcn': self.app.import_dxf,
self.app.worker_task.emit({'fcn': self.app.f_handlers.import_dxf,
'params': [self.filename, object_type, None]})
if extension in self.app.pdf_list:
@ -3711,10 +3723,10 @@ class MainGUI(QtWidgets.QMainWindow):
if extension in self.app.prj_list:
# self.app.open_project() is not Thread Safe
self.app.open_project(self.filename)
self.app.f_handlers.open_project(self.filename)
if extension in self.app.conf_list:
self.app.open_config_file(self.filename)
self.app.f_handlers.open_config_file(self.filename)
else:
event.ignore()
else:
@ -3748,13 +3760,14 @@ class MainGUI(QtWidgets.QMainWindow):
self.y_pos = a.y()
self.width = a.width()
self.height = a.height()
self.titlebar_height = self.app.qapp.style().pixelMetric(QtWidgets.QStyle.PM_TitleBarHeight)
# set new geometry to full desktop rect
# Subtracting and adding the pixels below it's hack to bypass a bug in Qt5 and OpenGL that made that a
# window drawn with OpenGL in fullscreen will not show any other windows on top which means that menus and
# everything else will not work without this hack. This happen in Windows.
# https://bugreports.qt.io/browse/QTBUG-41309
desktop = QtWidgets.QApplication.desktop()
desktop = self.app.qapp.desktop()
screen = desktop.screenNumber(QtGui.QCursor.pos())
rec = desktop.screenGeometry(screen)
@ -3762,6 +3775,7 @@ class MainGUI(QtWidgets.QMainWindow):
y = rec.y() - 1
h = rec.height() + 2
w = rec.width() + 2
self.setGeometry(x, y, w, h)
self.show()
@ -3769,13 +3783,17 @@ class MainGUI(QtWidgets.QMainWindow):
for tb in self.findChildren(QtWidgets.QToolBar):
tb.setVisible(False)
self.grid_toolbar.setVisible(self.app.defaults["global_grid_show"])
self.coords_toolbar.setVisible(self.app.defaults["global_coordsbar_show"])
self.delta_coords_toolbar.setVisible(self.app.defaults["global_delta_coordsbar_show"])
self.grid_toolbar.setVisible(self.app.defaults["global_gridbar_show"])
self.status_toolbar.setVisible(self.app.defaults["global_statusbar_show"])
self.splitter.setSizes([0, 1])
self.toggle_fscreen = True
elif self.toggle_fscreen is True or disable is True:
self.setWindowFlags(flags & ~Qt.FramelessWindowHint)
self.setGeometry(self.x_pos, self.y_pos, self.width, self.height)
# the additions are made to account for the pixels we subtracted/added above in the (x, y, h, w)
self.setGeometry(self.x_pos+1, self.y_pos+self.titlebar_height+4, self.width, self.height)
self.showNormal()
self.restore_toolbar_view()
self.toggle_fscreen = False
@ -3788,13 +3806,13 @@ class MainGUI(QtWidgets.QMainWindow):
try:
name = self.plot_tab_area.widget(0).objectName()
except AttributeError:
self.plot_tab_area.addTab(self.plot_tab, "Plot Area")
self.plot_tab_area.addTab(self.plot_tab, _("Plot Area"))
# remove the close button from the Plot Area tab (first tab index = 0) as this one will always be ON
self.plot_tab_area.protectTab(0)
return
if name != 'plotarea_tab':
self.plot_tab_area.insertTab(0, self.plot_tab, "Plot Area")
self.plot_tab_area.insertTab(0, self.plot_tab, _("Plot Area"))
# remove the close button from the Plot Area tab (first tab index = 0) as this one will always be ON
self.plot_tab_area.protectTab(0)
else:
@ -4040,6 +4058,10 @@ class ShortcutsTab(QtWidgets.QWidget):
<td height="20">&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr height="20">
<td height="20"><strong>Shift+A</strong></td>
<td>&nbsp;%s</td>
</tr>
<tr height="20">
<td height="20"><strong>Shift+C</strong></td>
<td>&nbsp;%s</td>
@ -4052,6 +4074,10 @@ class ShortcutsTab(QtWidgets.QWidget):
<td height="20"><strong>Shift+G</strong></td>
<td>&nbsp;%s</td>
</tr>
<tr height="20">
<td height="20"><strong>Shift+H</strong></td>
<td>&nbsp;%s</td>
</tr>
<tr height="20">
<td height="20"><strong>Shift+J</strong></td>
<td>&nbsp;%s</td>
@ -4190,6 +4216,10 @@ class ShortcutsTab(QtWidgets.QWidget):
<td height="20"><strong>Alt+3</strong></td>
<td>&nbsp;%s</td>
</tr>
<tr height="20">
<td height="20"><strong>Alt+4</strong></td>
<td>&nbsp;%s</td>
</tr>
<tr height="20">
<td height="20"><strong>Alt+F10</strong></td>
<td>&nbsp;%s</td>
@ -4270,22 +4300,24 @@ class ShortcutsTab(QtWidgets.QWidget):
_("Open Project"), _("Print (PDF)"), _("PDF Import Tool"), _("Save Project"), _("Toggle Plot Area"),
# SHIFT section
_("Copy Obj_Name"),
_("Toggle Code Editor"), _("Toggle the axis"), _("Locate in Object"), _("Distance Minimum Tool"),
_("Toggle the axis"), _("Copy Obj_Name"),
_("Toggle Code Editor"), _("Toggle Grid Lines"), _("Toggle HUD"), _("Locate in Object"),
_("Distance Minimum Tool"),
_("Open Preferences Window"),
_("Rotate by 90 degree CCW"), _("Run a Script"), _("Toggle the workspace"), _("Skew on X axis"),
_("Skew on Y axis"),
# ALT section
_("Align Objects Tool"), _("Calculators Tool"), _("2-Sided PCB Tool"), _("Extract Drills Tool"),
_("Fiducials Tool"), _("Toggle Grid Lines"),
_("Fiducials Tool"), _("Invert Gerber Tool"),
_("Punch Gerber Tool"), _("Isolation Tool"), _("Copper Thieving Tool"),
_("Solder Paste Dispensing Tool"),
_("Film PCB Tool"), _("Corner Markers Tool"), _("Non-Copper Clearing Tool"), _("Optimal Tool"),
_("Paint Area Tool"), _("QRCode Tool"), _("Rules Check Tool"),
_("View File Source"), _("Transformations Tool"),
_("Subtract Tool"), _("Cutout PCB Tool"), _("Panelize PCB"),
_("Enable all Plots"), _("Disable all Plots"), _("Disable Non-selected Plots"),
_("Enable all Plots"), _("Disable all Plots"),
_("Enable Non-selected Objects"), _("Disable Non-selected Objects"),
_("Toggle Full Screen"),
# CTRL + ALT section

View File

@ -1737,8 +1737,8 @@ class GeometryObjectUI(ObjectUI):
# Button
self.generate_cnc_button = QtWidgets.QPushButton(_('Generate CNCJob object'))
self.generate_cnc_button.setIcon(QtGui.QIcon(self.app.resource_location + '/cnc16.png'))
self.generate_cnc_button.setToolTip('%s\n%s' % (
_("Generate CNCJob object."),
self.generate_cnc_button.setToolTip('%s.\n%s' % (
_("Generate CNCJob object"),
_(
"Add / Select at least one tool in the tool-table.\n"
"Click the # header to select all, or Ctrl + LMB\n"
@ -1783,13 +1783,10 @@ class GeometryObjectUI(ObjectUI):
self.paint_tool_button = QtWidgets.QPushButton(_('Paint Tool'))
self.paint_tool_button.setIcon(QtGui.QIcon(self.app.resource_location + '/paint20_1.png'))
self.paint_tool_button.setToolTip(
_(
"Creates tool paths to cover the\n"
"whole area of a polygon (remove\n"
"all copper). You will be asked\n"
"to click on the desired polygon."
)
_("Creates tool paths to cover the\n"
"whole area of a polygon.")
)
# self.paint_tool_button.setStyleSheet("""
# QPushButton
# {
@ -2050,11 +2047,23 @@ class CNCObjectUI(ObjectUI):
self.custom_box.addWidget(self.snippets_cb)
# Autolevelling
self.sal_cb = FCCheckBox(_("Autolevelling"))
self.sal_cb.setToolTip(
self.sal_btn = FCButton('%s' % _("Autolevelling"), checkable=True)
# self.sal_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/properties32.png'))
self.sal_btn.setToolTip(
_("Enable the autolevelling feature.")
)
self.custom_box.addWidget(self.sal_cb)
self.sal_btn.setStyleSheet("""
QPushButton
{
font-weight: bold;
}
""")
self.custom_box.addWidget(self.sal_btn)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.custom_box.addWidget(separator_line)
self.al_frame = QtWidgets.QFrame()
self.al_frame.setContentsMargins(0, 0, 0, 0)
@ -2206,7 +2215,7 @@ class CNCObjectUI(ObjectUI):
self.al_rows_label = QtWidgets.QLabel('%s:' % _("Rows"))
self.al_rows_label.setToolTip(
_("The number of gird rows.")
_("The number of grid rows.")
)
grid0.addWidget(self.al_rows_label, 21, 0)
grid0.addWidget(self.al_rows_entry, 21, 1)

View File

@ -224,6 +224,7 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
if state:
self.axis_enabled = True
self.fcapp.defaults['global_axis'] = True
self.v_line.parent = self.view.scene
self.h_line.parent = self.view.scene
self.fcapp.ui.axis_status_label.setStyleSheet("""
@ -236,6 +237,7 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
self.fcapp.inform[str, bool].emit(_("Axis enabled."), False)
else:
self.axis_enabled = False
self.fcapp.defaults['global_axis'] = False
self.v_line.parent = None
self.h_line.parent = None
self.fcapp.ui.axis_status_label.setStyleSheet("")
@ -271,10 +273,12 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
state = not self.grid_lines_enabled
if state:
self.fcapp.defaults['global_grid_lines'] = True
self.grid_lines_enabled = True
self.grid.parent = self.view.scene
self.fcapp.inform[str, bool].emit(_("Grid enabled."), False)
else:
self.fcapp.defaults['global_grid_lines'] = False
self.grid_lines_enabled = False
self.grid.parent = None
self.fcapp.inform[str, bool].emit(_("Grid disabled."), False)

View File

@ -332,6 +332,7 @@ class PlotCanvasLegacy(QtCore.QObject):
if state:
self.axis_enabled = True
self.app.defaults['global_axis'] = True
if self.h_line not in self.axes.lines and self.v_line not in self.axes.lines:
self.h_line = self.axes.axhline(color=(0.70, 0.3, 0.3), linewidth=2)
self.v_line = self.axes.axvline(color=(0.70, 0.3, 0.3), linewidth=2)
@ -345,6 +346,7 @@ class PlotCanvasLegacy(QtCore.QObject):
self.app.inform[str, bool].emit(_("Axis enabled."), False)
else:
self.axis_enabled = False
self.app.defaults['global_axis'] = False
if self.h_line in self.axes.lines and self.v_line in self.axes.lines:
self.axes.lines.remove(self.h_line)
self.axes.lines.remove(self.v_line)
@ -442,6 +444,7 @@ class PlotCanvasLegacy(QtCore.QObject):
state = not self.grid_lines_enabled
if state:
self.app.defaults['global_grid_lines'] = True
self.grid_lines_enabled = True
self.axes.grid(True)
try:
@ -450,6 +453,7 @@ class PlotCanvasLegacy(QtCore.QObject):
pass
self.app.inform[str, bool].emit(_("Grid enabled."), False)
else:
self.app.defaults['global_grid_lines'] = False
self.grid_lines_enabled = False
self.axes.grid(False)
try:

View File

@ -389,25 +389,26 @@ class PreferencesUIManager:
"tools_drill_area_overz": self.ui.tools_defaults_form.tools_drill_group.over_z_entry,
# NCC Tool
"tools_ncctools": self.ui.tools_defaults_form.tools_ncc_group.ncc_tool_dia_entry,
"tools_nccorder": self.ui.tools_defaults_form.tools_ncc_group.ncc_order_radio,
"tools_nccoverlap": self.ui.tools_defaults_form.tools_ncc_group.ncc_overlap_entry,
"tools_nccmargin": self.ui.tools_defaults_form.tools_ncc_group.ncc_margin_entry,
"tools_nccmethod": self.ui.tools_defaults_form.tools_ncc_group.ncc_method_combo,
"tools_nccconnect": self.ui.tools_defaults_form.tools_ncc_group.ncc_connect_cb,
"tools_ncccontour": self.ui.tools_defaults_form.tools_ncc_group.ncc_contour_cb,
"tools_nccrest": self.ui.tools_defaults_form.tools_ncc_group.ncc_rest_cb,
"tools_ncc_tools": self.ui.tools_defaults_form.tools_ncc_group.ncc_tool_dia_entry,
"tools_ncc_order": self.ui.tools_defaults_form.tools_ncc_group.ncc_order_radio,
"tools_ncc_overlap": self.ui.tools_defaults_form.tools_ncc_group.ncc_overlap_entry,
"tools_ncc_margin": self.ui.tools_defaults_form.tools_ncc_group.ncc_margin_entry,
"tools_ncc_method": self.ui.tools_defaults_form.tools_ncc_group.ncc_method_combo,
"tools_ncc_connect": self.ui.tools_defaults_form.tools_ncc_group.ncc_connect_cb,
"tools_ncc_contour": self.ui.tools_defaults_form.tools_ncc_group.ncc_contour_cb,
"tools_ncc_rest": self.ui.tools_defaults_form.tools_ncc_group.ncc_rest_cb,
"tools_ncc_offset_choice": self.ui.tools_defaults_form.tools_ncc_group.ncc_choice_offset_cb,
"tools_ncc_offset_value": self.ui.tools_defaults_form.tools_ncc_group.ncc_offset_spinner,
"tools_nccref": self.ui.tools_defaults_form.tools_ncc_group.select_combo,
"tools_ncc_ref": self.ui.tools_defaults_form.tools_ncc_group.select_combo,
"tools_ncc_area_shape": self.ui.tools_defaults_form.tools_ncc_group.area_shape_radio,
"tools_nccmilling_type": self.ui.tools_defaults_form.tools_ncc_group.milling_type_radio,
"tools_ncctool_type": self.ui.tools_defaults_form.tools_ncc_group.tool_type_radio,
"tools_ncccutz": self.ui.tools_defaults_form.tools_ncc_group.cutz_entry,
"tools_ncctipdia": self.ui.tools_defaults_form.tools_ncc_group.tipdia_entry,
"tools_ncctipangle": self.ui.tools_defaults_form.tools_ncc_group.tipangle_entry,
"tools_nccnewdia": self.ui.tools_defaults_form.tools_ncc_group.newdia_entry,
"tools_ncc_milling_type": self.ui.tools_defaults_form.tools_ncc_group.milling_type_radio,
"tools_ncc_tool_type": self.ui.tools_defaults_form.tools_ncc_group.tool_type_radio,
"tools_ncc_cutz": self.ui.tools_defaults_form.tools_ncc_group.cutz_entry,
"tools_ncc_tipdia": self.ui.tools_defaults_form.tools_ncc_group.tipdia_entry,
"tools_ncc_tipangle": self.ui.tools_defaults_form.tools_ncc_group.tipangle_entry,
"tools_ncc_newdia": self.ui.tools_defaults_form.tools_ncc_group.newdia_entry,
"tools_ncc_plotting": self.ui.tools_defaults_form.tools_ncc_group.plotting_radio,
"tools_ncc_check_valid": self.ui.tools_defaults_form.tools_ncc_group.valid_cb,
# CutOut Tool
"tools_cutout_tooldia": self.ui.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry,
@ -427,23 +428,23 @@ class PreferencesUIManager:
"tools_cutout_mb_spacing": self.ui.tools_defaults_form.tools_cutout_group.mb_spacing_entry,
# Paint Area Tool
"tools_painttooldia": self.ui.tools_defaults_form.tools_paint_group.painttooldia_entry,
"tools_paintorder": self.ui.tools_defaults_form.tools_paint_group.paint_order_radio,
"tools_paintoverlap": self.ui.tools_defaults_form.tools_paint_group.paintoverlap_entry,
"tools_paintoffset": self.ui.tools_defaults_form.tools_paint_group.paintmargin_entry,
"tools_paintmethod": self.ui.tools_defaults_form.tools_paint_group.paintmethod_combo,
"tools_selectmethod": self.ui.tools_defaults_form.tools_paint_group.selectmethod_combo,
"tools_paint_tooldia": self.ui.tools_defaults_form.tools_paint_group.painttooldia_entry,
"tools_paint_order": self.ui.tools_defaults_form.tools_paint_group.paint_order_radio,
"tools_paint_overlap": self.ui.tools_defaults_form.tools_paint_group.paintoverlap_entry,
"tools_paint_offset": self.ui.tools_defaults_form.tools_paint_group.paintmargin_entry,
"tools_paint_method": self.ui.tools_defaults_form.tools_paint_group.paintmethod_combo,
"tools_paint_selectmethod": self.ui.tools_defaults_form.tools_paint_group.selectmethod_combo,
"tools_paint_area_shape": self.ui.tools_defaults_form.tools_paint_group.area_shape_radio,
"tools_pathconnect": self.ui.tools_defaults_form.tools_paint_group.pathconnect_cb,
"tools_paintcontour": self.ui.tools_defaults_form.tools_paint_group.contour_cb,
"tools_paint_connect": self.ui.tools_defaults_form.tools_paint_group.pathconnect_cb,
"tools_paint_contour": self.ui.tools_defaults_form.tools_paint_group.contour_cb,
"tools_paint_plotting": self.ui.tools_defaults_form.tools_paint_group.paint_plotting_radio,
"tools_paintrest": self.ui.tools_defaults_form.tools_paint_group.rest_cb,
"tools_painttool_type": self.ui.tools_defaults_form.tools_paint_group.tool_type_radio,
"tools_paintcutz": self.ui.tools_defaults_form.tools_paint_group.cutz_entry,
"tools_painttipdia": self.ui.tools_defaults_form.tools_paint_group.tipdia_entry,
"tools_painttipangle": self.ui.tools_defaults_form.tools_paint_group.tipangle_entry,
"tools_paintnewdia": self.ui.tools_defaults_form.tools_paint_group.newdia_entry,
"tools_paint_rest": self.ui.tools_defaults_form.tools_paint_group.rest_cb,
"tools_paint_tool_type": self.ui.tools_defaults_form.tools_paint_group.tool_type_radio,
"tools_paint_cutz": self.ui.tools_defaults_form.tools_paint_group.cutz_entry,
"tools_paint_tipdia": self.ui.tools_defaults_form.tools_paint_group.tipdia_entry,
"tools_paint_tipangle": self.ui.tools_defaults_form.tools_paint_group.tipangle_entry,
"tools_paint_newdia": self.ui.tools_defaults_form.tools_paint_group.newdia_entry,
# 2-sided Tool
"tools_2sided_mirror_axis": self.ui.tools_defaults_form.tools_2sided_group.mirror_axis_radio,

View File

@ -110,7 +110,7 @@ class CNCJobAdvOptPrefGroupUI(OptionsGroupUI):
self.al_rows_label = QtWidgets.QLabel('%s:' % _("Rows"))
self.al_rows_label.setToolTip(
_("The number of gird rows.")
_("The number of grid rows.")
)
grid0.addWidget(self.al_rows_label, 12, 0)
grid0.addWidget(self.al_rows_entry, 12, 1)

View File

@ -219,7 +219,7 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
"If <<TSA>> is checked then Travelling Salesman algorithm is used for\n"
"drill path optimization.\n"
"\n"
"Some options are disabled when FlatCAM works in 32bit mode.")
"Some options are disabled when the application works in 32bit mode.")
)
self.excellon_optimization_radio = RadioSet([{'label': _('MetaHeuristic'), 'value': 'M'},
@ -257,8 +257,8 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
self.fuse_tools_cb = FCCheckBox(_("Fuse Tools"))
self.fuse_tools_cb.setToolTip(
_("When checked the joined (merged) object tools\n"
"will be merged also but only if they share some of their attributes.")
_("When checked, the tools will be merged\n"
"but only if they share some of their attributes.")
)
grid2.addWidget(self.fuse_tools_cb, 13, 0, 1, 2)

View File

@ -386,9 +386,8 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
self.allow_edit_cb = FCCheckBox(_("Allow Edit"))
self.allow_edit_cb.setToolTip(
_("When cheched, the user can edit the objects in the Project Tab\n"
"by using the left mouse button click on the object name.\n"
"Active after restart.")
_("When checked, the user can edit the object names in the Project Tab\n"
"by clicking on the object name. Active after restart.")
)
grid0.addWidget(self.allow_edit_cb, 31, 0, 1, 2)

View File

@ -100,7 +100,7 @@ class GeometryGenPrefGroupUI(OptionsGroupUI):
"- Basic -> Using Google OR-Tools Basic algorithm\n"
"- TSA -> Using Travelling Salesman algorithm\n"
"\n"
"Some options are disabled when FlatCAM works in 32bit mode.")
"Some options are disabled when the application works in 32bit mode.")
)
self.opt_algorithm_radio = RadioSet(
@ -140,8 +140,8 @@ class GeometryGenPrefGroupUI(OptionsGroupUI):
self.fuse_tools_cb = FCCheckBox(_("Fuse Tools"))
self.fuse_tools_cb.setToolTip(
_("When checked the joined (merged) object tools\n"
"will be merged also but only if they share some of their attributes.")
_("When checked, the tools will be merged\n"
"but only if they share some of their attributes.")
)
grid0.addWidget(self.fuse_tools_cb, 20, 0, 1, 2)

View File

@ -185,7 +185,7 @@ class ToolsCutoutPrefGroupUI(OptionsGroupUI):
# Mouse Bites Tool Diameter
self.mb_dia_label = FCLabel('%s:' % _("Tool Diameter"))
self.mb_dia_label.setToolTip(
_("The drill hole diameter when doing mpuse bites.")
_("The drill hole diameter when doing mouse bites.")
)
self.mb_dia_entry = FCDoubleSpinner()
self.mb_dia_entry.set_precision(self.decimals)

View File

@ -346,4 +346,14 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
grid0.addWidget(plotting_label, 21, 0)
grid0.addWidget(self.plotting_radio, 21, 1)
# Check Tool validity
self.valid_cb = FCCheckBox(label=_('Check validity'))
self.valid_cb.setToolTip(
_("If checked then the tools diameters are verified\n"
"if they will provide a complete isolation.")
)
self.valid_cb.setObjectName("n_check")
grid0.addWidget(self.valid_cb, 23, 0, 1, 2)
self.layout.addStretch()

View File

@ -33,9 +33,7 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
self.paint_label = QtWidgets.QLabel(_('<b>Parameters:</b>'))
self.paint_label.setToolTip(
_("Creates tool paths to cover the\n"
"whole area of a polygon (remove\n"
"all copper). You will be asked\n"
"to click on the desired polygon.")
"whole area of a polygon.")
)
self.layout.addWidget(self.paint_label)

View File

@ -112,7 +112,7 @@ class ToolsPanelizePrefGroupUI(OptionsGroupUI):
_("Active only for Geometry panel type.\n"
"When checked the application will find\n"
"any two overlapping Line elements in the panel\n"
"and remove the overlapping parts, keeping only one of them.")
"and will remove the overlapping parts, keeping only one of them.")
)
grid0.addWidget(self.poptimization_cb, 5, 0, 1, 2)

View File

@ -34,7 +34,7 @@ class AppObject(QtCore.QObject):
# Emitted by app_obj.new_object() and passes the new object as argument, plot flag.
# on_object_created() adds the object to the collection, plots on appropriate flag
# and emits app_obj.new_object_available.
object_created = QtCore.pyqtSignal(object, bool, bool)
object_created = QtCore.pyqtSignal(object, bool, bool, object, list)
# Emitted when a object has been changed (like scaled, mirrored)
object_changed = QtCore.pyqtSignal(object)
@ -56,7 +56,7 @@ class AppObject(QtCore.QObject):
self.object_plotted.connect(self.on_object_plotted)
self.plots_updated.connect(self.app.on_plots_updated)
def new_object(self, kind, name, initialize, plot=True, autoselected=True):
def new_object(self, kind, name, initialize, plot=True, autoselected=True, callback=None, callback_params=None):
"""
Creates a new specialized FlatCAMObj and attaches it to the application,
this is, updates the GUI accordingly, any other records and plots it.
@ -78,10 +78,18 @@ class AppObject(QtCore.QObject):
:param plot: If to plot the resulting object
:param autoselected: if the resulting object is autoselected in the Project tab and therefore in the
self.collection
:param callback: a method that is launched after the object is created
:type callback: function
:param callback_params: a list of parameters for the parameter: callback
:type callback_params: list
:return: Either the object or the string 'fail'
:rtype: object
"""
if callback_params is None:
callback_params = [None]
log.debug("AppObject.new_object()")
obj_plot = plot
obj_autoselected = autoselected
@ -204,7 +212,10 @@ class AppObject(QtCore.QObject):
# Move the object to the main thread and let the app know that it is available.
# ############################################################################################################
obj.moveToThread(self.app.main_thread)
self.object_created.emit(obj, obj_plot, obj_autoselected)
if callback_params is None:
callback_params = []
self.object_created.emit(obj, obj_plot, obj_autoselected, callback, callback_params)
return obj
@ -324,15 +335,18 @@ class AppObject(QtCore.QObject):
self.new_object('document', 'new_document', initialize, plot=False)
def on_object_created(self, obj, plot, auto_select):
def on_object_created(self, obj, plot, auto_select, callback, callback_params):
"""
Event callback for object creation.
It will add the new object to the collection. After that it will plot the object in a threaded way
:param obj: The newly created FlatCAM object.
:param plot: if the newly create object t obe plotted
:param auto_select: if the newly created object to be autoselected after creation
:return: None
:param obj: The newly created FlatCAM object.
:param plot: if the newly create object to be plotted
:param auto_select: if the newly created object to be autoselected after creation
:param callback: a method that is launched after the object is created
:param callback_params: a list of parameters for the parameter: callback
:type callback_params: list
:return: None
"""
t0 = time.time() # DEBUG
@ -435,7 +449,7 @@ class AppObject(QtCore.QObject):
self.app.collection.set_all_inactive()
# here it is done the object plotting
def task(t_obj):
def plotting_task(t_obj):
with self.app.proc_container.new(_("Plotting")):
if t_obj.kind == 'cncjob':
t_obj.plot(kind=self.app.defaults["cncjob_plot_kind"])
@ -456,7 +470,11 @@ class AppObject(QtCore.QObject):
# Send to worker
# self.worker.add_task(worker_task, [self])
if plot is True:
self.app.worker_task.emit({'fcn': task, 'params': [obj]})
self.app.worker_task.emit({'fcn': plotting_task, 'params': [obj]})
if callback is not None:
# callback(*callback_params)
self.app.worker_task.emit({'fcn': callback, 'params': callback_params})
def on_object_changed(self, obj):
"""

View File

@ -26,9 +26,10 @@ from shapely.geometry import Point, MultiPoint, Polygon, LineString, box
import shapely.affinity as affinity
try:
from shapely.ops import voronoi_diagram
VORONOI_ENABLED = True
# from appCommon.Common import voronoi_diagram
except Exception:
pass
VORONOI_ENABLED = False
import os
import sys
@ -234,6 +235,11 @@ class CNCJobObject(FlatCAMObj, CNCjob):
def build_ui(self):
self.ui_disconnect()
# FIXME: until Shapely 1.8 comes this is disabled
self.ui.sal_btn.setChecked(False)
self.ui.sal_btn.setDisabled(True)
self.ui.sal_btn.setToolTip("DISABLED. Work in progress!")
FlatCAMObj.build_ui(self)
self.units = self.app.defaults['units'].upper()
@ -248,7 +254,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
self.ui.exc_cnc_tools_table.show()
self.build_excellon_cnc_tools()
if self.ui.sal_cb.get_value():
if self.ui.sal_btn.isChecked():
self.build_al_table()
self.ui_connect()
@ -573,7 +579,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
self.ui.updateplot_button.clicked.connect(self.on_updateplot_button_click)
self.ui.export_gcode_button.clicked.connect(self.on_exportgcode_button_click)
self.ui.review_gcode_button.clicked.connect(self.on_edit_code_click)
self.ui.review_gcode_button.clicked.connect(self.on_review_code_click)
# Editor Signal
self.ui.editor_button.clicked.connect(lambda: self.app.object2editor())
@ -583,7 +589,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
self.calculations_finished.connect(self.update_area_chull)
# autolevelling signals
self.ui.sal_cb.stateChanged.connect(self.on_toggle_autolevelling)
self.ui.sal_btn.toggled.connect(self.on_toggle_autolevelling)
self.ui.al_mode_radio.activated_custom.connect(self.on_mode_radio)
self.ui.al_method_radio.activated_custom.connect(self.on_method_radio)
self.ui.al_controller_combo.currentIndexChanged.connect(self.on_controller_change)
@ -636,19 +642,19 @@ class CNCJobObject(FlatCAMObj, CNCjob):
'<span style="color:green;"><b>Basic</b></span>'
))
self.ui.sal_cb.hide()
self.ui.sal_cb.set_value(False)
self.ui.sal_btn.hide()
self.ui.sal_btn.setChecked(False)
else:
self.ui.level.setText(_(
'<span style="color:red;"><b>Advanced</b></span>'
))
if 'Roland' in self.pp_excellon_name or 'Roland' in self.pp_geometry_name or 'hpgl' in \
self.pp_geometry_name:
self.ui.sal_cb.hide()
self.ui.sal_cb.set_value(False)
self.ui.sal_btn.hide()
self.ui.sal_btn.setChecked(False)
else:
self.ui.sal_cb.show()
self.ui.sal_cb.set_value(self.app.defaults["cncjob_al_status"])
self.ui.sal_btn.show()
self.ui.sal_btn.setChecked(self.app.defaults["cncjob_al_status"])
preamble = self.append_snippet
postamble = self.prepend_snippet
@ -771,9 +777,13 @@ class CNCJobObject(FlatCAMObj, CNCjob):
al_method = self.ui.al_method_radio.get_value()
if al_method == 'v':
self.generate_voronoi_geometry(pts=vor_pts_list)
# generate Probing GCode
self.probing_gcode_text = self.probing_gcode(storage=self.al_voronoi_geo_storage)
if VORONOI_ENABLED is True:
self.generate_voronoi_geometry(pts=vor_pts_list)
# generate Probing GCode
self.probing_gcode_text = self.probing_gcode(storage=self.al_voronoi_geo_storage)
else:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Voronoi function can not be loaded.\n"
"Shapely >= 1.8 is required"))
else:
self.generate_bilinear_geometry(pts=bl_pts_list)
# generate Probing GCode
@ -1042,12 +1052,16 @@ class CNCJobObject(FlatCAMObj, CNCjob):
al_method = self.ui.al_method_radio.get_value()
if al_method == 'v':
pts_list = []
for k in self.al_voronoi_geo_storage:
pts_list.append(self.al_voronoi_geo_storage[k]['point'])
self.generate_voronoi_geometry(pts=pts_list)
if VORONOI_ENABLED is True:
pts_list = []
for k in self.al_voronoi_geo_storage:
pts_list.append(self.al_voronoi_geo_storage[k]['point'])
self.generate_voronoi_geometry(pts=pts_list)
self.probing_gcode_text = self.probing_gcode(self.al_voronoi_geo_storage)
self.probing_gcode_text = self.probing_gcode(self.al_voronoi_geo_storage)
else:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Voronoi function can not be loaded.\n"
"Shapely >= 1.8 is required"))
# rebuild the al table
self.build_al_table_sig.emit()
@ -1689,7 +1703,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
try:
self.gcode_viewer_tab.load_text(gco, move_to_start=True, clear_text=True)
except Exception as e:
log.debug('FlatCAMCNCJob.on_edit_code_click() -->%s' % str(e))
log.debug('FlatCAMCNCJob.on_edit_probing_gcode() -->%s' % str(e))
return
self.gcode_viewer_tab.t_frame.show()
@ -1940,7 +1954,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
self.app.file_saved.emit("gcode", filename)
self.app.inform.emit('[success] %s: %s' % (_("File saved to"), filename))
def on_edit_code_click(self, *args):
def on_review_code_click(self, *args):
"""
Handler activated by a button clicked when reviewing GCode.
@ -1980,7 +1994,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
try:
self.gcode_editor_tab.load_text(self.app.gcode_edited.getvalue(), move_to_start=True, clear_text=True)
except Exception as e:
log.debug('FlatCAMCNCJob.on_edit_code_click() -->%s' % str(e))
log.debug('FlatCAMCNCJob.on_review_code_click() -->%s' % str(e))
return
self.gcode_editor_tab.t_frame.show()
@ -1988,8 +2002,8 @@ class CNCJobObject(FlatCAMObj, CNCjob):
self.gcode_editor_tab.buttonSave.hide()
self.gcode_editor_tab.buttonOpen.hide()
self.gcode_editor_tab.buttonPrint.hide()
self.gcode_editor_tab.buttonPreview.hide()
# self.gcode_editor_tab.buttonPrint.hide()
# self.gcode_editor_tab.buttonPreview.hide()
self.gcode_editor_tab.buttonReplace.hide()
self.gcode_editor_tab.sel_all_cb.hide()
self.gcode_editor_tab.entryReplace.hide()

View File

@ -172,6 +172,8 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
self.ui.solid_cb.stateChanged.connect(self.on_solid_cb_click)
self.ui.multicolored_cb.stateChanged.connect(self.on_multicolored_cb_click)
self.multicolored_build_sig.connect(self.on_multicolored_build)
self.ui.autoload_db_cb.stateChanged.connect(self.on_autoload_db_toggled)
# Editor
@ -182,6 +184,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.calculations_finished.connect(self.update_area_chull)
self.ui.drill_button.clicked.connect(lambda: self.app.drilling_tool.run(toggle=True))
# FIXME will uncomment when Milling Tool is ready
# self.ui.milling_button.clicked.connect(lambda: self.app.milling_tool.run(toggle=True))
# UTILITIES
@ -189,10 +192,10 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.ui.generate_milling_button.clicked.connect(self.on_generate_milling_button_click)
self.ui.generate_milling_slots_button.clicked.connect(self.on_generate_milling_slots_button_click)
# Toggle all Table rows
self.ui.tools_table.horizontalHeader().sectionClicked.connect(self.on_toggle_rows)
self.ui.table_visibility_cb.stateChanged.connect(self.on_table_visibility_toggle)
self.multicolored_build_sig.connect(self.on_multicolored_build)
self.ui.table_visibility_cb.stateChanged.connect(self.on_table_visibility_toggle)
self.units_found = self.app.defaults['units']
@ -560,11 +563,14 @@ class ExcellonObject(FlatCAMObj, Excellon):
for idx in sel_indexes:
sel_rows.add(idx.row())
if len(sel_rows) == self.ui.tools_table.rowCount():
# subtract the last 2 rows that show the total and are always displayed but not selected
if len(sel_rows) == self.ui.tools_table.rowCount() - 2:
self.ui.tools_table.clearSelection()
else:
self.ui.tools_table.selectAll()
self.on_row_selection_change()
def get_selected_tools_list(self):
"""
Returns the keys to the self.tools dictionary corresponding

View File

@ -269,6 +269,7 @@ class GeometryObject(FlatCAMObj, Geometry):
horizontal_header.resizeSection(0, 20)
horizontal_header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
# horizontal_header.setColumnWidth(2, QtWidgets.QHeaderView.ResizeToContents)
horizontal_header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
horizontal_header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents)
horizontal_header.setSectionResizeMode(4, QtWidgets.QHeaderView.Fixed)
horizontal_header.resizeSection(4, 40)
@ -1914,7 +1915,7 @@ class GeometryObject(FlatCAMObj, Geometry):
log.debug("FlatCAMObj.GeometryObject.mtool_gen_cncjob() --> %s\n" % str(e))
msg = '[ERROR] %s' % _("An internal error has occurred. See shell.\n")
msg += '%s %s' % ('FlatCAMObj.GeometryObject.mtool_gen_cncjob() -->', str(e))
msg += '%s' % str(e)
msg += traceback.format_exc()
self.app.inform.emit(msg)
return

View File

@ -219,12 +219,12 @@ class FlatCAMObj(QtCore.QObject):
# 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.app.ui.properties_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.app.ui.properties_scroll_area.setWidget(self.ui)
# self.ui.setMinimumWidth(100)
# self.ui.setMaximumWidth(self.app.ui.properties_tab.sizeHint().width())

View File

@ -126,36 +126,36 @@ class KeySensitiveListView(QtWidgets.QTreeView):
self.app.inform.emit(_("Cancelled."))
else:
if self.filename.lower().rpartition('.')[-1] in self.app.grb_list:
self.app.worker_task.emit({'fcn': self.app.open_gerber,
self.app.worker_task.emit({'fcn': self.app.f_handlers.open_gerber,
'params': [self.filename]})
else:
event.ignore()
if self.filename.lower().rpartition('.')[-1] in self.app.exc_list:
self.app.worker_task.emit({'fcn': self.app.open_excellon,
self.app.worker_task.emit({'fcn': self.app.f_handlers.open_excellon,
'params': [self.filename]})
else:
event.ignore()
if self.filename.lower().rpartition('.')[-1] in self.app.gcode_list:
self.app.worker_task.emit({'fcn': self.app.open_gcode,
self.app.worker_task.emit({'fcn': self.app.f_handlers.open_gcode,
'params': [self.filename]})
else:
event.ignore()
if self.filename.lower().rpartition('.')[-1] in self.app.svg_list:
object_type = 'geometry'
self.app.worker_task.emit({'fcn': self.app.import_svg,
self.app.worker_task.emit({'fcn': self.app.f_handlers.import_svg,
'params': [self.filename, object_type, None]})
if self.filename.lower().rpartition('.')[-1] in self.app.dxf_list:
object_type = 'geometry'
self.app.worker_task.emit({'fcn': self.app.import_dxf,
self.app.worker_task.emit({'fcn': self.app.f_handlers.import_dxf,
'params': [self.filename, object_type, None]})
if self.filename.lower().rpartition('.')[-1] in self.app.prj_list:
# self.app.open_project() is not Thread Safe
self.app.open_project(self.filename)
self.app.f_handlers.open_project(self.filename)
else:
event.ignore()
else:
@ -967,7 +967,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
# log.debug("on_list_selection_change(): Index Error (Nothing selected?)")
self.app.inform.emit('')
try:
self.app.ui.selected_scroll_area.takeWidget()
self.app.ui.properties_scroll_area.takeWidget()
except Exception as e:
log.debug("Nothing to remove. %s" % str(e))

View File

@ -81,26 +81,26 @@ class HPGL2:
"toolchangexy": self.app.defaults["geometry_toolchangexy"],
"startz": self.app.defaults["geometry_startz"],
"tooldia": self.app.defaults["tools_painttooldia"],
"tools_paintoffset": self.app.defaults["tools_paintoffset"],
"tools_paintmethod": self.app.defaults["tools_paintmethod"],
"tools_selectmethod": self.app.defaults["tools_selectmethod"],
"tools_pathconnect": self.app.defaults["tools_pathconnect"],
"tools_paintcontour": self.app.defaults["tools_paintcontour"],
"tools_paintoverlap": self.app.defaults["tools_paintoverlap"],
"tools_paintrest": self.app.defaults["tools_paintrest"],
"tooldia": self.app.defaults["tools_paint_tooldia"],
"tools_paint_offset": self.app.defaults["tools_paint_offset"],
"tools_paint_method": self.app.defaults["tools_paint_method"],
"tools_paint_selectmethod": self.app.defaults["tools_paint_selectmethod"],
"tools_paint_connect": self.app.defaults["tools_paint_connect"],
"tools_paint_contour": self.app.defaults["tools_paint_contour"],
"tools_paint_overlap": self.app.defaults["tools_paint_overlap"],
"tools_paint_rest": self.app.defaults["tools_paint_rest"],
"tools_nccoperation": self.app.defaults["tools_nccoperation"],
"tools_nccmargin": self.app.defaults["tools_nccmargin"],
"tools_nccmethod": self.app.defaults["tools_nccmethod"],
"tools_nccconnect": self.app.defaults["tools_nccconnect"],
"tools_ncccontour": self.app.defaults["tools_ncccontour"],
"tools_nccoverlap": self.app.defaults["tools_nccoverlap"],
"tools_nccrest": self.app.defaults["tools_nccrest"],
"tools_nccref": self.app.defaults["tools_nccref"],
"tools_ncc_operation": self.app.defaults["tools_ncc_operation"],
"tools_ncc_margin": self.app.defaults["tools_ncc_margin"],
"tools_ncc_method": self.app.defaults["tools_ncc_method"],
"tools_ncc_connect": self.app.defaults["tools_ncc_connect"],
"tools_ncc_contour": self.app.defaults["tools_ncc_contour"],
"tools_ncc_overlap": self.app.defaults["tools_ncc_overlap"],
"tools_ncc_rest": self.app.defaults["tools_ncc_rest"],
"tools_ncc_ref": self.app.defaults["tools_ncc_ref"],
"tools_ncc_offset_choice": self.app.defaults["tools_ncc_offset_choice"],
"tools_ncc_offset_value": self.app.defaults["tools_ncc_offset_value"],
"tools_nccmilling_type": self.app.defaults["tools_nccmilling_type"],
"tools_ncc_milling_type": self.app.defaults["tools_ncc_milling_type"],
"tools_iso_passes": self.app.defaults["tools_iso_passes"],
"tools_iso_overlap": self.app.defaults["tools_iso_overlap"],

View File

@ -90,7 +90,7 @@ class AppTool(QtWidgets.QWidget):
# Remove anything else in the appGUI
self.app.ui.tool_scroll_area.takeWidget()
# Put ourself in the appGUI
# Put ourselves in the appGUI
self.app.ui.tool_scroll_area.setWidget(self)
# Switch notebook to tool page

View File

@ -671,8 +671,8 @@ class ToolCalibration(AppTool):
obj_init.skew(angle_x=skewx, angle_y=skewy, point=(origin_x, origin_y))
try:
obj_init.source_file = self.export_gerber(obj_name=obj_name, filename=None, local_use=obj_init,
use_thread=False)
obj_init.source_file = self.app.f_handlers.export_gerber(obj_name=obj_name, filename=None,
local_use=obj_init, use_thread=False)
except (AttributeError, TypeError):
pass
@ -689,8 +689,8 @@ class ToolCalibration(AppTool):
obj_init.create_geometry()
obj_init.source_file = self.app.export_excellon(obj_name=obj_name, local_use=obj, filename=None,
use_thread=False)
obj_init.source_file = self.app.export.export_excellon(obj_name=obj_name, local_use=obj, filename=None,
use_thread=False)
obj = self.cal_object
obj_name = obj_name

View File

@ -282,10 +282,9 @@ class ToolCopperThieving(AppTool):
self.app.proc_container.update_view_text(' %s' % _("Append source file"))
# update the source file with the new geometry:
self.grb_object.source_file = self.app.export_gerber(obj_name=self.grb_object.options['name'],
filename=None,
local_use=self.grb_object,
use_thread=False)
self.grb_object.source_file = self.app.f_handlers.export_gerber(obj_name=self.grb_object.options['name'],
filename=None, local_use=self.grb_object,
use_thread=False)
self.app.proc_container.update_view_text(' %s' % '')
self.on_exit()
self.app.inform.emit('[success] %s' % _("Copper Thieving Tool done."))
@ -519,9 +518,9 @@ class ToolCopperThieving(AppTool):
ref_selected = self.ui.reference_radio.get_value()
if c_val is None:
c_val = float(self.app.defaults["tools_copperfill_clearance"])
c_val = float(self.app.defaults["tools_copper_thieving_clearance"])
if margin is None:
margin = float(self.app.defaults["tools_copperfill_margin"])
margin = float(self.app.defaults["tools_copper_thieving_margin"])
fill_type = self.ui.fill_type_radio.get_value()
dot_dia = self.ui.dot_dia_entry.get_value()
@ -543,10 +542,8 @@ class ToolCopperThieving(AppTool):
app_obj.app.inform.emit(_("Copper Thieving Tool. Preparing isolation polygons."))
# variables to display the percentage of work done
geo_len = 0
try:
for pol in app_obj.grb_object.solid_geometry:
geo_len += 1
geo_len = len(app_obj.grb_object.solid_geometry)
except TypeError:
geo_len = 1
@ -613,10 +610,12 @@ class ToolCopperThieving(AppTool):
bounding_box = env_obj.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
else:
if isinstance(geo_n, Polygon):
bounding_box = geo_n.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre).exterior
bounding_box = geo_n.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
elif isinstance(geo_n, list):
geo_n = unary_union(geo_n)
bounding_box = geo_n.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre).exterior
geo_n = MultiPolygon(geo_n)
x0, y0, x1, y1 = geo_n.bounds
geo = box(x0, y0, x1, y1)
bounding_box = geo.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
elif isinstance(geo_n, MultiPolygon):
x0, y0, x1, y1 = geo_n.bounds
geo = box(x0, y0, x1, y1)
@ -689,10 +688,16 @@ class ToolCopperThieving(AppTool):
# bounding_box = box(x0, y0, x1, y1)
app_obj.app.proc_container.update_view_text(' %s' % _("Create geometry"))
bounding_box = thieving_obj.solid_geometry.envelope.buffer(
distance=margin,
join_style=base.JOIN_STYLE.mitre
)
try:
bounding_box = thieving_obj.solid_geometry.envelope.buffer(
distance=margin,
join_style=base.JOIN_STYLE.mitre
)
except AttributeError:
bounding_box = MultiPolygon(thieving_obj.solid_geometry).envelope.buffer(
distance=margin,
join_style=base.JOIN_STYLE.mitre
)
x0, y0, x1, y1 = bounding_box.bounds
if fill_type == 'dot' or fill_type == 'square':
@ -870,10 +875,9 @@ class ToolCopperThieving(AppTool):
app_obj.app.proc_container.update_view_text(' %s' % _("Append source file"))
# update the source file with the new geometry:
app_obj.grb_object.source_file = app_obj.app.export_gerber(obj_name=app_obj.grb_object.options['name'],
filename=None,
local_use=app_obj.grb_object,
use_thread=False)
app_obj.grb_object.source_file = app_obj.f_handlers.export_gerber(
obj_name=app_obj.grb_object.options['name'], filename=None, local_use=app_obj.grb_object,
use_thread=False)
app_obj.app.proc_container.update_view_text(' %s' % '')
app_obj.on_exit()
app_obj.app.inform.emit('[success] %s' % _("Copper Thieving Tool done."))
@ -1015,10 +1019,8 @@ class ToolCopperThieving(AppTool):
app_obj.proc_container.update_view_text(' %s' % _("Append source file"))
# update the source file with the new geometry:
grb_obj.source_file = app_obj.export_gerber(obj_name=name,
filename=None,
local_use=grb_obj,
use_thread=False)
grb_obj.source_file = app_obj.f_handlers.export_gerber(obj_name=name, filename=None, local_use=grb_obj,
use_thread=False)
app_obj.proc_container.update_view_text(' %s' % '')
# Object name

View File

@ -133,9 +133,10 @@ class ToolCorners(AppTool):
self.add_corners_geo(points, g_obj=self.grb_object)
self.grb_object.source_file = self.app.export_gerber(obj_name=self.grb_object.options['name'],
filename=None,
local_use=self.grb_object, use_thread=False)
self.grb_object.source_file = self.app.f_handlers.export_gerber(obj_name=self.grb_object.options['name'],
filename=None,
local_use=self.grb_object,
use_thread=False)
self.on_exit()
def add_corners_geo(self, points_storage, g_obj):

View File

@ -875,8 +875,9 @@ class CutOut(AppTool):
exc_obj.tools = tools
exc_obj.create_geometry()
exc_obj.source_file = app_o.export_excellon(obj_name=exc_obj.options['name'], local_use=exc_obj,
filename=None, use_thread=False)
exc_obj.source_file = app_o.f_handlers.export_excellon(obj_name=exc_obj.options['name'],
local_use=exc_obj,filename=None,
use_thread=False)
# calculate the bounds
xmin, ymin, xmax, ymax = CutOut.recursive_bounds(exc_obj.solid_geometry)
exc_obj.options['xmin'] = xmin
@ -1244,8 +1245,10 @@ class CutOut(AppTool):
exc_obj.tools = tools
exc_obj.create_geometry()
exc_obj.source_file = app_o.export_excellon(obj_name=exc_obj.options['name'], local_use=exc_obj,
filename=None, use_thread=False)
exc_obj.source_file = app_o.f_handlers.export_excellon(obj_name=exc_obj.options['name'],
local_use=exc_obj,
filename=None,
use_thread=False)
# calculate the bounds
e_xmin, e_ymin, e_xmax, e_ymax = CutOut.recursive_bounds(exc_obj.solid_geometry)
exc_obj.options['xmin'] = e_xmin
@ -1600,9 +1603,10 @@ class CutOut(AppTool):
exc_obj.tools = tools
exc_obj.create_geometry()
exc_obj.source_file = app_o.export_excellon(obj_name=exc_obj.options['name'],
local_use=exc_obj,
filename=None, use_thread=False)
exc_obj.source_file = app_o.f_handlers.export_excellon(obj_name=exc_obj.options['name'],
local_use=exc_obj,
filename=None,
use_thread=False)
# calculate the bounds
xmin, ymin, xmax, ymax = CutOut.recursive_bounds(exc_obj.solid_geometry)
exc_obj.options['xmin'] = xmin
@ -2219,7 +2223,7 @@ class CutoutUI:
# Mouse Bites Tool Diameter
self.mb_dia_label = FCLabel('%s:' % _("Tool Diameter"))
self.mb_dia_label.setToolTip(
_("The drill hole diameter when doing mpuse bites.")
_("The drill hole diameter when doing mouse bites.")
)
self.mb_dia_entry = FCDoubleSpinner(callback=self.confirmation_message)
self.mb_dia_entry.set_precision(self.decimals)

View File

@ -205,8 +205,10 @@ class DblSidedTool(AppTool):
def obj_init(obj_inst, app_inst):
obj_inst.tools = tools
obj_inst.create_geometry()
obj_inst.source_file = app_inst.export_excellon(obj_name=obj_inst.options['name'], local_use=obj_inst,
filename=None, use_thread=False)
obj_inst.source_file = app_inst.f_handlers.export_excellon(obj_name=obj_inst.options['name'],
local_use=obj_inst,
filename=None,
use_thread=False)
self.app.app_obj.new_object("excellon", "Alignment Drills", obj_init)
self.drill_values = ''
@ -518,10 +520,7 @@ class DsidedUI:
# Type of object to be cutout
self.type_obj_combo_label = QtWidgets.QLabel('%s:' % _("Type"))
self.type_obj_combo_label.setToolTip(
_("Specify the type of object to be cutout.\n"
"It can be of type: Gerber or Geometry.\n"
"What is selected here will dictate the kind\n"
"of objects that will populate the 'Object' combobox.")
_("Select the type of application object to be processed in this tool.")
)
self.object_type_radio = RadioSet([
@ -688,7 +687,7 @@ class DsidedUI:
"- Point -> a set of coordinates (x,y) around which the object is mirrored\n"
"- Box -> a set of coordinates (x, y) obtained from the center of the\n"
"bounding box of another object selected below\n"
"- Hole Snap -> a point defined by the center of a drill hone in a Excellon object")
"- Hole Snap -> a point defined by the center of a drill hole in a Excellon object")
)
self.axis_location = RadioSet(
[
@ -726,7 +725,7 @@ class DsidedUI:
self.exc_hole_lbl = QtWidgets.QLabel('%s:' % _("Excellon"))
self.exc_hole_lbl.setToolTip(
_("Object that holds holes that can be picked as reference for mirroing.")
_("Object that holds holes that can be picked as reference for mirroring.")
)
# Excellon Object that holds the holes

View File

@ -233,8 +233,8 @@ class ToolEtchCompensation(AppTool):
new_obj.apertures = deepcopy(new_apertures)
new_obj.solid_geometry = deepcopy(new_solid_geometry)
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
new_obj.source_file = self.app.f_handlers.export_gerber(obj_name=outname, filename=None, local_use=new_obj,
use_thread=False)
self.app.app_obj.new_object('gerber', outname, init_func)

View File

@ -373,8 +373,9 @@ class ToolExtractDrills(AppTool):
obj_inst.tools = tools
obj_inst.drills = drills
obj_inst.create_geometry()
obj_inst.source_file = self.app.export_excellon(obj_name=outname, local_use=obj_inst, filename=None,
use_thread=False)
obj_inst.source_file = app_inst.f_handlers.export_excellon(obj_name=outname, local_use=obj_inst,
filename=None,
use_thread=False)
self.app.app_obj.new_object("excellon", outname, obj_init)

View File

@ -229,9 +229,9 @@ class ToolFiducials(AppTool):
self.ui.sec_points_coords_entry.set_value('(%.*f, %.*f)' % (self.decimals, x1, self.decimals, y0))
self.add_fiducials_geo(self.click_points, g_obj=self.grb_object, fid_type=fid_type)
self.grb_object.source_file = self.app.export_gerber(obj_name=self.grb_object.options['name'],
filename=None,
local_use=self.grb_object, use_thread=False)
self.grb_object.source_file = self.app.f_handlers.export_gerber(obj_name=self.grb_object.options['name'],
filename=None,
local_use=self.grb_object, use_thread=False)
self.on_exit()
else:
self.app.inform.emit(_("Click to add first Fiducial. Bottom Left..."))
@ -467,8 +467,10 @@ class ToolFiducials(AppTool):
self.sm_obj_set.add(self.sm_object.options['name'])
self.add_fiducials_geo(self.click_points, g_obj=self.sm_object, fid_size=sm_opening_dia, fid_type='circular')
self.sm_object.source_file = self.app.export_gerber(obj_name=self.sm_object.options['name'], filename=None,
local_use=self.sm_object, use_thread=False)
self.sm_object.source_file = self.app.f_handlers.export_gerber(obj_name=self.sm_object.options['name'],
filename=None,
local_use=self.sm_object,
use_thread=False)
self.on_exit()
def on_mouse_release(self, event):
@ -508,18 +510,18 @@ class ToolFiducials(AppTool):
self.ui.sec_points_coords_entry.set_value(self.click_points[2])
self.app.inform.emit('[success] %s' % _("Done. All fiducials have been added."))
self.add_fiducials_geo(self.click_points, g_obj=self.grb_object, fid_type=fid_type)
self.grb_object.source_file = self.app.export_gerber(obj_name=self.grb_object.options['name'],
filename=None,
local_use=self.grb_object, use_thread=False)
self.grb_object.source_file = self.app.f_handlers.export_gerber(
obj_name=self.grb_object.options['name'], filename=None, local_use=self.grb_object,
use_thread=False)
self.on_exit()
else:
if len(self.click_points) == 2:
self.ui.top_right_coords_entry.set_value(self.click_points[1])
self.app.inform.emit('[success] %s' % _("Done. All fiducials have been added."))
self.add_fiducials_geo(self.click_points, g_obj=self.grb_object, fid_type=fid_type)
self.grb_object.source_file = self.app.export_gerber(obj_name=self.grb_object.options['name'],
filename=None,
local_use=self.grb_object, use_thread=False)
self.grb_object.source_file = self.app.f_handlers.export_gerber(
obj_name=self.grb_object.options['name'], filename=None,
local_use=self.grb_object, use_thread=False)
self.on_exit()
def on_mouse_move(self, event):

View File

@ -63,6 +63,8 @@ class Film(AppTool):
self.ui.file_type_radio.activated_custom.connect(self.ui.on_file_type)
self.ui.reset_button.clicked.connect(self.set_tool_ui)
self.screen_dpi = 96
def on_type_obj_index_changed(self, val):
obj_type = 2 if val == 'geo' else 0
self.ui.tf_object_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
@ -446,9 +448,10 @@ class Film(AppTool):
scale_reference = 'center'
default_dpi = 96
self.screen_dpi = self.app.qapp.screens()[0].logicalDotsPerInch()
new_png_dpi = self.ui.png_dpi_spinner.get_value()
dpi_rate = new_png_dpi / default_dpi
dpi_rate = new_png_dpi / self.screen_dpi
# Determine bounding area for svg export
bounds = box.bounds()
tr_scale_reference = (bounds[0], bounds[1])
@ -703,9 +706,10 @@ class Film(AppTool):
scale_reference = 'center'
default_dpi = 96
self.screen_dpi = self.app.qapp.screens()[0].logicalDotsPerInch()
new_png_dpi = self.ui.png_dpi_spinner.get_value()
dpi_rate = new_png_dpi / default_dpi
dpi_rate = new_png_dpi / self.screen_dpi
# Determine bounding area for svg export
bounds = box.bounds()
tr_scale_reference = (bounds[0], bounds[1])
@ -835,11 +839,6 @@ class Film(AppTool):
doc_final = StringIO(doc_final)
drawing = svg2rlg(doc_final)
renderPM.drawToFile(drawing, filename, 'PNG')
# if new_png_dpi == default_dpi:
# renderPM.drawToFile(drawing, filename, 'PNG')
# else:
# renderPM.drawToFile(drawing, filename, 'PNG', dpi=new_png_dpi)
except Exception as e:
log.debug("FilmTool.export_positive() --> PNG output --> %s" % str(e))
return 'fail'

View File

@ -44,7 +44,7 @@ class ToolInvertGerber(AppTool):
self.ui.reset_button.clicked.connect(self.set_tool_ui)
def install(self, icon=None, separator=None, **kwargs):
AppTool.install(self, icon, separator, shortcut='', **kwargs)
AppTool.install(self, icon, separator, shortcut='ALT+G', **kwargs)
def run(self, toggle=True):
self.app.defaults.report_usage("ToolInvertGerber()")
@ -157,8 +157,8 @@ class ToolInvertGerber(AppTool):
new_obj.apertures = deepcopy(new_apertures)
new_obj.solid_geometry = deepcopy(new_solid_geometry)
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
new_obj.source_file = self.app.f_handlers.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.app_obj.new_object('gerber', outname, init_func)
@ -253,9 +253,9 @@ class InvertUI:
"- bevel -> the lines are joined by a third line")
)
self.join_radio = RadioSet([
{'label': 'Rounded', 'value': 'r'},
{'label': 'Square', 'value': 's'},
{'label': 'Bevel', 'value': 'b'}
{'label': _('Rounded'), 'value': 'r'},
{'label': _('Square'), 'value': 's'},
{'label': _('Bevel'), 'value': 'b'}
], orientation='vertical', stretch=False)
grid0.addWidget(self.join_label, 7, 0, 1, 2)

View File

@ -52,7 +52,7 @@ class ToolMilling(AppTool, Excellon):
# #############################################################################
# ######################### Tool GUI ##########################################
# #############################################################################
self.ui = DrillingUI(layout=self.layout, app=self.app)
self.ui = MillingUI(layout=self.layout, app=self.app)
self.toolName = self.ui.toolName
# #############################################################################

View File

@ -192,10 +192,10 @@ class ToolMove(AppTool):
for sel_obj in obj_list:
out_name = sel_obj.options["name"]
if sel_obj.kind == 'gerber':
sel_obj.source_file = self.app.export_gerber(
sel_obj.source_file = self.app.f_handlers.export_gerber(
obj_name=out_name, filename=None, local_use=sel_obj, use_thread=False)
elif sel_obj.kind == 'excellon':
sel_obj.source_file = self.app.export_excellon(
sel_obj.source_file = self.app.f_handlers.export_excellon(
obj_name=out_name, filename=None, local_use=sel_obj, use_thread=False)
except Exception as err:
log.debug('[ERROR_NOTCL] %s --> %s' % ('ToolMove.on_left_click()', str(err)))

View File

@ -98,6 +98,9 @@ class NonCopperClear(AppTool, Gerber):
self.contour = None
self.rest = None
# store here the tool diameter that is guaranteed to isolate the object
self.safe_tooldia = None
self.first_click = False
self.cursor_pos = None
self.mouse_is_dragging = False
@ -126,27 +129,29 @@ class NonCopperClear(AppTool, Gerber):
self.tooldia = None
self.form_fields = {
"tools_nccoperation": self.ui.op_radio,
"tools_nccoverlap": self.ui.ncc_overlap_entry,
"tools_nccmargin": self.ui.ncc_margin_entry,
"tools_nccmethod": self.ui.ncc_method_combo,
"tools_nccconnect": self.ui.ncc_connect_cb,
"tools_ncccontour": self.ui.ncc_contour_cb,
"tools_ncc_offset_choice": self.ui.ncc_choice_offset_cb,
"tools_ncc_offset_value": self.ui.ncc_offset_spinner,
"tools_nccmilling_type": self.ui.milling_type_radio
"tools_ncc_operation": self.ui.op_radio,
"tools_ncc_overlap": self.ui.ncc_overlap_entry,
"tools_ncc_margin": self.ui.ncc_margin_entry,
"tools_ncc_method": self.ui.ncc_method_combo,
"tools_ncc_connect": self.ui.ncc_connect_cb,
"tools_ncc_contour": self.ui.ncc_contour_cb,
"tools_ncc_offset_choice": self.ui.ncc_choice_offset_cb,
"tools_ncc_offset_value": self.ui.ncc_offset_spinner,
"tools_ncc_milling_type": self.ui.milling_type_radio,
"tools_ncc_check_valid": self.ui.valid_cb
}
self.name2option = {
"n_operation": "tools_nccoperation",
"n_overlap": "tools_nccoverlap",
"n_margin": "tools_nccmargin",
"n_method": "tools_nccmethod",
"n_connect": "tools_nccconnect",
"n_contour": "tools_ncccontour",
"n_offset": "tools_ncc_offset_choice",
"n_offset_value": "tools_ncc_offset_value",
"n_milling_type": "tools_nccmilling_type",
"n_operation": "tools_ncc_operation",
"n_overlap": "tools_ncc_overlap",
"n_margin": "tools_ncc_margin",
"n_method": "tools_ncc_method",
"n_connect": "tools_ncc_connect",
"n_contour": "tools_ncc_contour",
"n_offset": "tools_ncc_offset_choice",
"n_offset_value": "tools_ncc_offset_value",
"n_milling_type": "tools_ncc_milling_type",
"n_check": "tools_ncc_check_valid",
}
self.old_tool_dia = None
@ -241,7 +246,7 @@ class NonCopperClear(AppTool, Gerber):
current_row = self.ui.tools_table.currentRow()
try:
current_uid = int(self.ui.tools_table.item(current_row, 3).text())
self.ncc_tools[current_uid]['data']['tools_nccoperation'] = val
self.ncc_tools[current_uid]['data']['tools_ncc_operation'] = val
# TODO got a crash here, a KeyError exception; need to see it again and find out the why
except AttributeError:
return
@ -463,7 +468,10 @@ class NonCopperClear(AppTool, Gerber):
def set_tool_ui(self):
self.units = self.app.defaults['units'].upper()
self.old_tool_dia = self.app.defaults["tools_nccnewdia"]
self.old_tool_dia = self.app.defaults["tools_ncc_newdia"]
# reset the value to prepare for another isolation
self.safe_tooldia = None
self.ui.tools_frame.show()
@ -492,29 +500,32 @@ class NonCopperClear(AppTool, Gerber):
self.on_type_obj_index_changed(val=kind)
self.on_reference_combo_changed()
self.ui.op_radio.set_value(self.app.defaults["tools_nccoperation"])
self.ui.ncc_order_radio.set_value(self.app.defaults["tools_nccorder"])
self.ui.ncc_overlap_entry.set_value(self.app.defaults["tools_nccoverlap"])
self.ui.ncc_margin_entry.set_value(self.app.defaults["tools_nccmargin"])
self.ui.ncc_method_combo.set_value(self.app.defaults["tools_nccmethod"])
self.ui.ncc_connect_cb.set_value(self.app.defaults["tools_nccconnect"])
self.ui.ncc_contour_cb.set_value(self.app.defaults["tools_ncccontour"])
self.ui.op_radio.set_value(self.app.defaults["tools_ncc_operation"])
self.ui.ncc_order_radio.set_value(self.app.defaults["tools_ncc_order"])
self.ui.ncc_overlap_entry.set_value(self.app.defaults["tools_ncc_overlap"])
self.ui.ncc_margin_entry.set_value(self.app.defaults["tools_ncc_margin"])
self.ui.ncc_method_combo.set_value(self.app.defaults["tools_ncc_method"])
self.ui.ncc_connect_cb.set_value(self.app.defaults["tools_ncc_connect"])
self.ui.ncc_contour_cb.set_value(self.app.defaults["tools_ncc_contour"])
self.ui.ncc_choice_offset_cb.set_value(self.app.defaults["tools_ncc_offset_choice"])
self.ui.ncc_offset_spinner.set_value(self.app.defaults["tools_ncc_offset_value"])
self.ui.ncc_rest_cb.set_value(self.app.defaults["tools_nccrest"])
self.ui.rest_ncc_margin_entry.set_value(self.app.defaults["tools_nccmargin"])
self.ui.rest_ncc_connect_cb.set_value(self.app.defaults["tools_nccconnect"])
self.ui.rest_ncc_contour_cb.set_value(self.app.defaults["tools_ncccontour"])
self.ui.ncc_rest_cb.set_value(self.app.defaults["tools_ncc_rest"])
self.ui.on_rest_machining_check(state=self.app.defaults["tools_ncc_rest"])
self.ui.rest_ncc_margin_entry.set_value(self.app.defaults["tools_ncc_margin"])
self.ui.rest_ncc_connect_cb.set_value(self.app.defaults["tools_ncc_connect"])
self.ui.rest_ncc_contour_cb.set_value(self.app.defaults["tools_ncc_contour"])
self.ui.rest_ncc_choice_offset_cb.set_value(self.app.defaults["tools_ncc_offset_choice"])
self.ui.rest_ncc_offset_spinner.set_value(self.app.defaults["tools_ncc_offset_value"])
self.ui.select_combo.set_value(self.app.defaults["tools_nccref"])
self.ui.select_combo.set_value(self.app.defaults["tools_ncc_ref"])
self.ui.area_shape_radio.set_value(self.app.defaults["tools_ncc_area_shape"])
self.ui.valid_cb.set_value(self.app.defaults["tools_ncc_check_valid"])
self.ui.milling_type_radio.set_value(self.app.defaults["tools_nccmilling_type"])
self.ui.milling_type_radio.set_value(self.app.defaults["tools_ncc_milling_type"])
self.ui.new_tooldia_entry.set_value(self.app.defaults["tools_nccnewdia"])
self.ui.new_tooldia_entry.set_value(self.app.defaults["tools_ncc_newdia"])
# init the working variables
self.default_data.clear()
@ -550,26 +561,27 @@ class NonCopperClear(AppTool, Gerber):
"area_overz": float(self.app.defaults["geometry_area_overz"]),
"optimization_type": self.app.defaults["geometry_optimization_type"],
"tools_nccoperation": self.app.defaults["tools_nccoperation"],
"tools_nccmargin": self.app.defaults["tools_nccmargin"],
"tools_nccmethod": self.app.defaults["tools_nccmethod"],
"tools_nccconnect": self.app.defaults["tools_nccconnect"],
"tools_ncccontour": self.app.defaults["tools_ncccontour"],
"tools_nccoverlap": self.app.defaults["tools_nccoverlap"],
"tools_nccrest": self.app.defaults["tools_nccrest"],
"tools_nccref": self.app.defaults["tools_nccref"],
"tools_ncc_operation": self.app.defaults["tools_ncc_operation"],
"tools_ncc_margin": self.app.defaults["tools_ncc_margin"],
"tools_ncc_method": self.app.defaults["tools_ncc_method"],
"tools_ncc_connect": self.app.defaults["tools_ncc_connect"],
"tools_ncc_contour": self.app.defaults["tools_ncc_contour"],
"tools_ncc_overlap": self.app.defaults["tools_ncc_overlap"],
"tools_ncc_rest": self.app.defaults["tools_ncc_rest"],
"tools_ncc_ref": self.app.defaults["tools_ncc_ref"],
"tools_ncc_offset_choice": self.app.defaults["tools_ncc_offset_choice"],
"tools_ncc_offset_value": self.app.defaults["tools_ncc_offset_value"],
"tools_nccmilling_type": self.app.defaults["tools_nccmilling_type"]
"tools_ncc_milling_type": self.app.defaults["tools_ncc_milling_type"],
"tools_ncc_check_valid": self.app.defaults["tools_ncc_check_valid"],
}
try:
dias = [float(self.app.defaults["tools_ncctools"])]
dias = [float(self.app.defaults["tools_ncc_tools"])]
except (ValueError, TypeError):
try:
dias = [float(eval(dia)) for dia in self.app.defaults["tools_ncctools"].split(",") if dia != '']
dias = [float(eval(dia)) for dia in self.app.defaults["tools_ncc_tools"].split(",") if dia != '']
except AttributeError:
dias = self.app.defaults["tools_ncctools"]
dias = self.app.defaults["tools_ncc_tools"]
except Exception:
dias = []
@ -767,11 +779,11 @@ class NonCopperClear(AppTool, Gerber):
pass
try:
self.ui.ncc_rest_cb.stateChanged.disconnect()
self.ui.ncc_rest_cb.stateChanged.disconnect(self.ui.on_rest_machining_check)
except (TypeError, ValueError):
pass
try:
self.ui.ncc_order_radio.activated_custom[str].disconnect()
self.ui.ncc_order_radio.activated_custom[str].disconnect(self.on_order_changed)
except (TypeError, ValueError):
pass
@ -819,6 +831,10 @@ class NonCopperClear(AppTool, Gerber):
})
def on_find_optimal_tooldia(self):
self.find_safe_tooldia_worker(is_displayed=True)
def find_safe_tooldia_worker(self, is_displayed):
self.app.inform.emit(_("NCC Tool. Checking tools for validity."))
self.units = self.app.defaults['units'].upper()
obj_name = self.ui.object_combo.currentText()
@ -836,7 +852,7 @@ class NonCopperClear(AppTool, Gerber):
proc = self.app.proc_container.new(_("Working..."))
def job_thread(app_obj):
def job_thread(app_obj, is_display):
try:
old_disp_number = 0
pol_nr = 0
@ -901,18 +917,48 @@ class NonCopperClear(AppTool, Gerber):
min_dist = min(min_list)
min_dist_truncated = self.app.dec_format(float(min_dist), self.decimals)
self.safe_tooldia = min_dist_truncated
self.optimal_found_sig.emit(min_dist_truncated)
if is_display:
self.optimal_found_sig.emit(min_dist_truncated)
app_obj.inform.emit('[success] %s: %s %s' %
(_("Optimal tool diameter found"), str(min_dist_truncated), self.units.lower()))
app_obj.inform.emit('[success] %s: %s %s' %
(_("Optimal tool diameter found"), str(min_dist_truncated),
self.units.lower()))
else:
# find the selected tool ID's
sorted_tools = []
table_items = self.ui.tools_table.selectedItems()
sel_rows = {t.row() for t in table_items}
for row in sel_rows:
tid = int(self.ui.tools_table.item(row, 3).text())
sorted_tools.append(tid)
if not sorted_tools:
msg = _("There are no tools selected in the Tool Table.")
self.app.inform.emit('[ERROR_NOTCL] %s' % msg)
return 'fail'
# check if the tools diameters are less then the safe tool diameter
suitable_tools = []
for tool in sorted_tools:
tool_dia = float(self.ncc_tools[tool]['tooldia'])
if tool_dia <= self.safe_tooldia:
suitable_tools.append(tool_dia)
if not suitable_tools:
msg = _("Incomplete isolation. None of the selected tools could do a complete isolation.")
self.app.inform.emit('[WARNING] %s' % msg)
else:
msg = _("At least one of the selected tools can do a complete isolation.")
self.app.inform.emit('[success] %s' % msg)
# reset the value to prepare for another isolation
self.safe_tooldia = None
except Exception as ee:
proc.done()
log.debug(str(ee))
return
proc.done()
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app, is_displayed]})
def on_tool_add(self, custom_dia=None):
self.blockSignals(True)
@ -1113,7 +1159,7 @@ class NonCopperClear(AppTool, Gerber):
'offset': 'Path',
'offset_value': 0.0,
'type': 'Iso',
'tool_type': deepcopy(self.app.defaults["tools_ncctool_type"]),
'tool_type': deepcopy(self.app.defaults["tools_ncc_tool_type"]),
'data': deepcopy(self.default_data),
'solid_geometry': []
}
@ -1266,6 +1312,9 @@ class NonCopperClear(AppTool, Gerber):
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Object not found"), str(self.obj_name)))
return
if self.ui.valid_cb.get_value() is True:
self.find_safe_tooldia_worker(is_displayed=False)
# use the selected tools in the tool table; get diameters for isolation
self.iso_dia_list = []
# use the selected tools in the tool table; get diameters for non-copper clear
@ -1288,7 +1337,7 @@ class NonCopperClear(AppTool, Gerber):
# find out which tools is for isolation and which are for copper clearing
for uid_k, uid_v in self.ncc_tools.items():
if round(uid_v['tooldia'], self.decimals) == round(self.tooldia, self.decimals):
if uid_v['data']['tools_nccoperation'] == "iso":
if uid_v['data']['tools_ncc_operation'] == "iso":
self.iso_dia_list.append(self.tooldia)
else:
self.ncc_dia_list.append(self.tooldia)
@ -2113,10 +2162,10 @@ class NonCopperClear(AppTool, Gerber):
break
# parameters that are particular to the current tool
ncc_overlap = float(self.ncc_tools[tool_uid]["data"]["tools_nccoverlap"]) / 100.0
ncc_method = self.ncc_tools[tool_uid]["data"]["tools_nccmethod"]
ncc_connect = self.ncc_tools[tool_uid]["data"]["tools_nccconnect"]
ncc_contour = self.ncc_tools[tool_uid]["data"]["tools_ncccontour"]
ncc_overlap = float(self.ncc_tools[tool_uid]["data"]["tools_ncc_overlap"]) / 100.0
ncc_method = self.ncc_tools[tool_uid]["data"]["tools_ncc_method"]
ncc_connect = self.ncc_tools[tool_uid]["data"]["tools_ncc_connect"]
ncc_contour = self.ncc_tools[tool_uid]["data"]["tools_ncc_contour"]
has_offset = self.ncc_tools[tool_uid]["data"]["tools_ncc_offset_choice"]
ncc_offset = float(self.ncc_tools[tool_uid]["data"]["tools_ncc_offset_value"])
@ -2336,6 +2385,13 @@ class NonCopperClear(AppTool, Gerber):
ncc_margin=ncc_margin, tools_storage=tools_storage,
bounding_box=bbox)
# for testing purposes ----------------------------------
# for po in area.geoms:
# self.app.tool_shapes.add(po, color=self.app.defaults['global_sel_line'],
# face_color=self.app.defaults['global_sel_line'],
# update=True, layer=0, tolerance=None)
# -------------------------------------------------------
# Generate area for each tool
while sorted_clear_tools:
tool = sorted_clear_tools.pop(0)
@ -2355,84 +2411,135 @@ class NonCopperClear(AppTool, Gerber):
tool_uid = 0 # find the current tool_uid
for k, v in self.ncc_tools.items():
if float('%.*f' % (self.decimals, v['tooldia'])) == float('%.*f' % (self.decimals, tool)):
if self.app.dec_format(v['tooldia'], self.decimals) == self.app.dec_format(tool, self.decimals):
tool_uid = int(k)
break
tool_data_dict = self.ncc_tools[tool_uid]["data"]
# parameters that are particular to the current tool
ncc_overlap = float(self.ncc_tools[tool_uid]["data"]["tools_nccoverlap"]) / 100.0
ncc_method = self.ncc_tools[tool_uid]["data"]["tools_nccmethod"]
ncc_overlap = float(tool_data_dict["tools_ncc_overlap"]) / 100.0
ncc_method = tool_data_dict["tools_ncc_method"]
# variables to display the percentage of work done
geo_len = len(area.geoms)
old_disp_number = 0
log.warning("Total number of polygons to be cleared. %s" % str(geo_len))
log.warning("Total number of polygons to be cleared: %s" % str(geo_len))
# def random_color():
# r_color = np.random.rand(4)
# r_color[3] = 0.5
# return r_color
# store here the geometry generated by clear operation
cleared_geo = []
if area.geoms:
if len(area.geoms) > 0:
pol_nr = 0
for p in area.geoms:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
if p is not None and p.is_valid:
# provide the app with a way to process the GUI events when in a blocking loop
QtWidgets.QApplication.processEvents()
poly_failed = 0
# speedup the clearing by not trying to clear polygons that is clear they can't be
# cleared with the current tool. this tremendously reduce the clearing time
check_dist = -tool / 2.0
check_buff = p.buffer(check_dist)
if not check_buff or check_buff.is_empty:
continue
# actual copper claring is done here
if isinstance(p, Polygon):
res = self.clear_polygon_worker(pol=p, tooldia=tool,
ncc_method=ncc_method,
ncc_overlap=ncc_overlap,
ncc_connect=ncc_connect,
ncc_contour=ncc_contour,
prog_plot=prog_plot)
if res is not None:
cleared_geo += res
else:
poly_failed += 1
else:
log.warning("Expected geo is a Polygon. Instead got a %s" % str(type(p)))
if poly_failed > 0:
app_obj.poly_not_cleared = True
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
# log.debug("Polygons cleared: %d" % pol_nr)
if old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %d%%' % disp_number)
old_disp_number = disp_number
# log.debug("Polygons cleared: %d. Percentage done: %d%%" % (pol_nr, disp_number))
poly_failed = 0
if area.geoms and len(area.geoms) > 0:
pol_nr = 0
for p in area.geoms:
if self.app.abort_flag:
raise grace # graceful abort requested by the user
# graceful abort requested by the user
raise grace
# check if there is a geometry at all in the cleared geometry
if cleared_geo:
tools_storage[tool_uid]["solid_geometry"] = deepcopy(cleared_geo)
tools_storage[tool_uid]["data"]["name"] = name + '_' + str(tool)
geo_obj.tools[current_uid] = dict(tools_storage[current_uid])
else:
log.debug("There are no geometries in the cleared polygon.")
if p is not None and p.is_valid and not p.is_empty:
# provide the app with a way to process the GUI events when in a blocking loop
QtWidgets.QApplication.processEvents()
# Area to clear next
buffered_cleared = unary_union(cleared_geo).buffer(tool / 2.0)
area = area.difference(buffered_cleared)
# speedup the clearing by not trying to clear polygons that is clear they can't be
# cleared with the current tool. this tremendously reduce the clearing time
check_dist = -tool / 2
check_buff = p.buffer(check_dist, self.circle_steps)
if not check_buff or check_buff.is_empty:
continue
# if self.app.dec_format(float(tool), self.decimals) == 0.15:
# # for testing purposes ----------------------------------
# self.app.tool_shapes.add(p, color=self.app.defaults['global_sel_line'],
# face_color=random_color(),
# update=True, layer=0, tolerance=None)
# self.app.tool_shapes.add(check_buff, color=self.app.defaults['global_sel_line'],
# face_color='#FFFFFFFF',
# update=True, layer=0, tolerance=None)
# # -------------------------------------------------------
# actual copper clearing is done here
if isinstance(p, Polygon):
res = self.clear_polygon_worker(pol=p, tooldia=tool,
ncc_method=ncc_method,
ncc_overlap=ncc_overlap,
ncc_connect=ncc_connect,
ncc_contour=ncc_contour,
prog_plot=prog_plot)
if res is not None:
cleared_geo += res
else:
poly_failed += 1
else:
log.warning("Expected geo is a Polygon. Instead got a %s" % str(type(p)))
if poly_failed > 0:
app_obj.poly_not_cleared = True
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
# log.debug("Polygons cleared: %d" % pol_nr)
if old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %d%%' % disp_number)
old_disp_number = disp_number
# log.debug("Polygons cleared: %d. Percentage done: %d%%" % (pol_nr, disp_number))
if self.app.abort_flag:
raise grace # graceful abort requested by the user
# check if there is a geometry at all in the cleared geometry
if cleared_geo:
tools_storage[tool_uid]["solid_geometry"] = deepcopy(cleared_geo)
tools_storage[tool_uid]["data"]["name"] = name + '_' + str(tool)
geo_obj.tools[tool_uid] = dict(tools_storage[tool_uid])
else:
log.debug("There are no geometries in the cleared polygon.")
log.warning("Total number of polygons failed to be cleared: %s" % str(poly_failed))
else:
log.warning("The area to be cleared has no polygons.")
# # Area to clear next
# try:
# # buffered_cleared = unary_union(cleared_geo).buffer(tool / 2.0)
# # area = area.difference(buffered_cleared)
# area = area.difference(unary_union(cleared_geo))
# except Exception as e:
# log.debug("Creating new area failed due of: %s" % str(e))
new_area = MultiPolygon([line.buffer(tool / 1.9999999) for line in cleared_geo])
new_area = new_area.buffer(0.0000001)
area = area.difference(new_area)
new_area = [pol for pol in area if pol.is_valid and not pol.is_empty]
area = MultiPolygon(new_area)
# speedup the clearing by not trying to clear polygons that is clear they can't be
# cleared with any tool. this tremendously reduce the clearing time
# found_poly_to_clear = False
# for t in sorted_clear_tools:
# check_dist = -t / 2.000000001
# for pl in area:
# check_buff = pl.buffer(check_dist)
# if not check_buff or check_buff.is_empty or not check_buff.is_valid:
# continue
# else:
# found_poly_to_clear = True
# break
# if found_poly_to_clear is True:
# break
#
# if found_poly_to_clear is False:
# log.warning("The area to be cleared no longer has polygons. Finishing.")
# break
if not area or area.is_empty:
break
@ -2716,9 +2823,9 @@ class NonCopperClear(AppTool, Gerber):
offset_a = sum(sorted_tools)
current_uid = int(1)
try:
tool = eval(self.app.defaults["tools_ncctools"])[0]
tool = eval(self.app.defaults["tools_ncc_tools"])[0]
except TypeError:
tool = eval(self.app.defaults["tools_ncctools"])
tool = eval(self.app.defaults["tools_ncc_tools"])
# ###################################################################################################
# Calculate the empty area by subtracting the solid_geometry from the object bounding box geometry ##
@ -2758,7 +2865,7 @@ class NonCopperClear(AppTool, Gerber):
self.solid_geometry = ncc_obj.solid_geometry
# if milling type is climb then the move is counter-clockwise around features
milling_type = self.app.defaults["tools_nccmilling_type"]
milling_type = self.app.defaults["tools_ncc_milling_type"]
for tool_iso in isotooldia:
new_geometry = []
@ -3106,9 +3213,9 @@ class NonCopperClear(AppTool, Gerber):
rest_geo = []
current_uid = 1
try:
tool = eval(self.app.defaults["tools_ncctools"])[0]
tool = eval(self.app.defaults["tools_ncc_tools"])[0]
except TypeError:
tool = eval(self.app.defaults["tools_ncctools"])
tool = eval(self.app.defaults["tools_ncc_tools"])
# repurposed flag for final object, geo_obj. True if it has any solid_geometry, False if not.
app_obj.poly_not_cleared = True
@ -3137,7 +3244,7 @@ class NonCopperClear(AppTool, Gerber):
self.solid_geometry = ncc_obj.solid_geometry
# if milling type is climb then the move is counter-clockwise around features
milling_type = self.app.defaults["tools_nccmilling_type"]
milling_type = self.app.defaults["tools_ncc_milling_type"]
for tool_iso in isotooldia:
new_geometry = []
@ -4247,10 +4354,20 @@ class NccUI:
self.area_shape_label.hide()
self.area_shape_radio.hide()
# Check Tool validity
self.valid_cb = FCCheckBox(label=_('Check validity'))
self.valid_cb.setToolTip(
_("If checked then the tools diameters are verified\n"
"if they will provide a complete isolation.")
)
self.valid_cb.setObjectName("n_check")
self.grid3.addWidget(self.valid_cb, 33, 0, 1, 2)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.grid3.addWidget(separator_line, 32, 0, 1, 2)
self.grid3.addWidget(separator_line, 35, 0, 1, 2)
self.generate_ncc_button = FCButton(_('Generate Geometry'))
self.generate_ncc_button.setIcon(QtGui.QIcon(self.app.resource_location + '/geometry32.png'))

View File

@ -106,19 +106,19 @@ class ToolPaint(AppTool, Gerber):
self.tool_type_item_options = ["C1", "C2", "C3", "C4", "B", "V"]
self.form_fields = {
"tools_paintoverlap": self.ui.paintoverlap_entry,
"tools_paintoffset": self.ui.offset_entry,
"tools_paintmethod": self.ui.paintmethod_combo,
"tools_pathconnect": self.ui.pathconnect_cb,
"tools_paintcontour": self.ui.paintcontour_cb,
"tools_paint_overlap": self.ui.paintoverlap_entry,
"tools_paint_offset": self.ui.offset_entry,
"tools_paint_method": self.ui.paintmethod_combo,
"tools_paint_connect": self.ui.pathconnect_cb,
"tools_paint_contour": self.ui.paintcontour_cb,
}
self.name2option = {
'p_overlap': "tools_paintoverlap",
'p_offset': "tools_paintoffset",
'p_method': "tools_paintmethod",
'p_connect': "tools_pathconnect",
'p_contour': "tools_paintcontour",
'p_overlap': "tools_paint_overlap",
'p_offset': "tools_paint_offset",
'p_method': "tools_paint_method",
'p_connect': "tools_paint_connect",
'p_contour': "tools_paint_contour",
}
# store here the points for the "Polygon" area selection shape
@ -439,9 +439,9 @@ class ToolPaint(AppTool, Gerber):
self.default_data.update({
"name": '_paint',
"plot": self.app.defaults["geometry_plot"],
"cutz": float(self.app.defaults["tools_paintcutz"]),
"vtipdia": float(self.app.defaults["tools_painttipdia"]),
"vtipangle": float(self.app.defaults["tools_painttipangle"]),
"cutz": float(self.app.defaults["tools_paint_cutz"]),
"vtipdia": float(self.app.defaults["tools_paint_tipdia"]),
"vtipangle": float(self.app.defaults["tools_paint_tipangle"]),
"travelz": float(self.app.defaults["geometry_travelz"]),
"feedrate": float(self.app.defaults["geometry_feedrate"]),
"feedrate_z": float(self.app.defaults["geometry_feedrate_z"]),
@ -468,28 +468,28 @@ class ToolPaint(AppTool, Gerber):
"area_overz": float(self.app.defaults["geometry_area_overz"]),
"optimization_type": self.app.defaults["geometry_optimization_type"],
"tooldia": self.app.defaults["tools_painttooldia"],
"tools_paintoffset": self.app.defaults["tools_paintoffset"],
"tools_paintmethod": self.app.defaults["tools_paintmethod"],
"tools_selectmethod": self.app.defaults["tools_selectmethod"],
"tools_pathconnect": self.app.defaults["tools_pathconnect"],
"tools_paintcontour": self.app.defaults["tools_paintcontour"],
"tools_paintoverlap": self.app.defaults["tools_paintoverlap"],
"tools_paintrest": self.app.defaults["tools_paintrest"],
"tooldia": self.app.defaults["tools_paint_tooldia"],
"tools_paint_offset": self.app.defaults["tools_paint_offset"],
"tools_paint_method": self.app.defaults["tools_paint_method"],
"tools_paint_selectmethod": self.app.defaults["tools_paint_selectmethod"],
"tools_paint_connect": self.app.defaults["tools_paint_connect"],
"tools_paint_contour": self.app.defaults["tools_paint_contour"],
"tools_paint_overlap": self.app.defaults["tools_paint_overlap"],
"tools_paint_rest": self.app.defaults["tools_paint_rest"],
})
# ## Init the GUI interface
self.ui.order_radio.set_value(self.app.defaults["tools_paintorder"])
self.ui.offset_entry.set_value(self.app.defaults["tools_paintoffset"])
self.ui.paintmethod_combo.set_value(self.app.defaults["tools_paintmethod"])
self.ui.selectmethod_combo.set_value(self.app.defaults["tools_selectmethod"])
self.ui.order_radio.set_value(self.app.defaults["tools_paint_order"])
self.ui.offset_entry.set_value(self.app.defaults["tools_paint_offset"])
self.ui.paintmethod_combo.set_value(self.app.defaults["tools_paint_method"])
self.ui.selectmethod_combo.set_value(self.app.defaults["tools_paint_selectmethod"])
self.ui.area_shape_radio.set_value(self.app.defaults["tools_paint_area_shape"])
self.ui.pathconnect_cb.set_value(self.app.defaults["tools_pathconnect"])
self.ui.paintcontour_cb.set_value(self.app.defaults["tools_paintcontour"])
self.ui.paintoverlap_entry.set_value(self.app.defaults["tools_paintoverlap"])
self.ui.pathconnect_cb.set_value(self.app.defaults["tools_paint_connect"])
self.ui.paintcontour_cb.set_value(self.app.defaults["tools_paint_contour"])
self.ui.paintoverlap_entry.set_value(self.app.defaults["tools_paint_overlap"])
self.ui.new_tooldia_entry.set_value(self.app.defaults["tools_paintnewdia"])
self.ui.rest_cb.set_value(self.app.defaults["tools_paintrest"])
self.ui.new_tooldia_entry.set_value(self.app.defaults["tools_paint_newdia"])
self.ui.rest_cb.set_value(self.app.defaults["tools_paint_rest"])
# # make the default object type, "Geometry"
# self.type_obj_radio.set_value("geometry")
@ -521,29 +521,29 @@ class ToolPaint(AppTool, Gerber):
self.on_reference_combo_changed()
try:
diameters = [float(self.app.defaults["tools_painttooldia"])]
diameters = [float(self.app.defaults["tools_paint_tooldia"])]
except (ValueError, TypeError):
if isinstance(self.app.defaults["tools_painttooldia"], str):
diameters = [eval(x) for x in self.app.defaults["tools_painttooldia"].split(",") if x != '']
if isinstance(self.app.defaults["tools_paint_tooldia"], str):
diameters = [eval(x) for x in self.app.defaults["tools_paint_tooldia"].split(",") if x != '']
else:
diameters = self.app.defaults["tools_painttooldia"]
diameters = self.app.defaults["tools_paint_tooldia"]
if not diameters:
log.error("At least one tool diameter needed. Verify in Edit -> Preferences -> TOOLS -> NCC Tools.")
self.build_ui()
# if the Paint Method is "Single" disable the tool table context menu
if self.default_data["tools_selectmethod"] == "single":
if self.default_data["tools_paint_selectmethod"] == "single":
self.ui.tools_table.setContextMenuPolicy(Qt.NoContextMenu)
return
for dia in diameters:
self.on_tool_add(custom_dia=dia)
self.ui.on_rest_machining_check(state=self.app.defaults["tools_paintrest"])
self.ui.on_rest_machining_check(state=self.app.defaults["tools_paint_rest"])
# if the Paint Method is "Single" disable the tool table context menu
if self.default_data["tools_selectmethod"] == "single":
if self.default_data["tools_paint_selectmethod"] == "single":
self.ui.tools_table.setContextMenuPolicy(Qt.NoContextMenu)
self.ui.tools_table.drag_drop_sig.connect(self.rebuild_ui)
@ -1777,11 +1777,11 @@ class ToolPaint(AppTool, Gerber):
return "fail"
# determine the tool parameters to use
over = float(tools_storage[current_uid]['data']['tools_paintoverlap']) / 100.0
conn = tools_storage[current_uid]['data']['tools_pathconnect']
cont = tools_storage[current_uid]['data']['tools_paintcontour']
over = float(tools_storage[current_uid]['data']['tools_paint_overlap']) / 100.0
conn = tools_storage[current_uid]['data']['tools_paint_connect']
cont = tools_storage[current_uid]['data']['tools_paint_contour']
paint_offset = float(tools_storage[current_uid]['data']['tools_paintoffset'])
paint_offset = float(tools_storage[current_uid]['data']['tools_paint_offset'])
poly_buf = []
for pol in geometry:
@ -1967,9 +1967,9 @@ class ToolPaint(AppTool, Gerber):
# cleared_geo = []
# determine the tool parameters to use
over = float(tools_storage[current_uid]['data']['tools_paintoverlap']) / 100.0
conn = tools_storage[current_uid]['data']['tools_pathconnect']
cont = tools_storage[current_uid]['data']['tools_paintcontour']
over = float(tools_storage[current_uid]['data']['tools_paint_overlap']) / 100.0
conn = tools_storage[current_uid]['data']['tools_paint_connect']
cont = tools_storage[current_uid]['data']['tools_paint_contour']
pol_nr = 0

View File

@ -360,8 +360,8 @@ class Panelize(AppTool):
obj_fin.zeros = panel_source_obj.zeros
obj_fin.units = panel_source_obj.units
app_obj.inform.emit('%s' % _("Generating panel ... Adding the source code."))
obj_fin.source_file = self.app.export_excellon(obj_name=self.outname, filename=None,
local_use=obj_fin, use_thread=False)
obj_fin.source_file = self.app.export.export_excellon(obj_name=self.outname, filename=None,
local_use=obj_fin, use_thread=False)
app_obj.proc_container.update_view_text('')
def job_init_geometry(obj_fin, app_obj):
@ -583,11 +583,11 @@ class Panelize(AppTool):
app_obj.inform.emit('%s' % _("Generating panel ... Adding the source code."))
if panel_type == 'gerber':
obj_fin.source_file = self.app.export_gerber(obj_name=self.outname, filename=None,
local_use=obj_fin, use_thread=False)
obj_fin.source_file = self.app.f_handlers.export_gerber(obj_name=self.outname, filename=None,
local_use=obj_fin, use_thread=False)
if panel_type == 'geometry':
obj_fin.source_file = self.app.export_dxf(obj_name=self.outname, filename=None,
local_use=obj_fin, use_thread=False)
obj_fin.source_file = self.app.f_handlers.export_dxf(obj_name=self.outname, filename=None,
local_use=obj_fin, use_thread=False)
# obj_fin.solid_geometry = unary_union(obj_fin.solid_geometry)
# app_obj.log.debug("Finished creating a unary_union for the panel.")
@ -823,7 +823,7 @@ class PanelizeUI:
_("Active only for Geometry panel type.\n"
"When checked the application will find\n"
"any two overlapping Line elements in the panel\n"
"and remove the overlapping parts, keeping only one of them.")
"and will remove the overlapping parts, keeping only one of them.")
)
form_layout.addRow(self.optimization_cb)

View File

@ -35,9 +35,10 @@ class Properties(AppTool):
def __init__(self, app):
AppTool.__init__(self, app)
self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
# self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
self.decimals = self.app.decimals
self.layout.setContentsMargins(0, 0, 0, 0)
# this way I can hide/show the frame
self.properties_frame = QtWidgets.QFrame()
@ -48,27 +49,22 @@ class Properties(AppTool):
self.properties_frame.setLayout(self.properties_box)
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel
{
font-size: 16px;
font-weight: bold;
}
""")
self.properties_box.addWidget(title_label)
# self.layout.setMargin(0) # PyQt4
self.properties_box.setContentsMargins(0, 0, 0, 0) # PyQt5
self.vlay = QtWidgets.QVBoxLayout()
self.properties_box.addLayout(self.vlay)
# title_label = QtWidgets.QLabel("%s" % self.toolName)
# title_label.setStyleSheet("""
# QLabel
# {
# font-size: 16px;
# font-weight: bold;
# }
# """)
# self.properties_box.addWidget(title_label)
self.treeWidget = FCTree(columns=2)
self.treeWidget.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
self.treeWidget.setStyleSheet("QTreeWidget {border: 0px;}")
self.vlay.addWidget(self.treeWidget)
self.vlay.setStretch(0, 0)
self.properties_box.addWidget(self.treeWidget)
# self.properties_box.setStretch(0, 0)
self.calculations_finished.connect(self.show_area_chull)

View File

@ -233,21 +233,24 @@ class ToolPunchGerber(AppTool):
for elem in val['geometry']:
# make it work only for Gerber Flashes who are Points in 'follow'
if 'solid' in elem and isinstance(elem['follow'], Point):
for drill in exc_obj.drills:
clear_apid_size = exc_obj.tools[drill['tool']]['tooldia']
for tool in exc_obj.tools:
clear_apid_size = exc_obj.tools[tool]['tooldia']
# since there may be drills that do not drill into a pad we test only for drills in a pad
if drill['point'].within(elem['solid']):
geo_elem = {}
geo_elem['clear'] = drill['point']
if 'drills' in exc_obj.tools[tool]['drills']:
for drill_pt in exc_obj.tools[tool]['drills']:
# since there may be drills that do not drill into a pad we test only for
# drills in a pad
if drill_pt.within(elem['solid']):
geo_elem = {}
geo_elem['clear'] = drill_pt
if clear_apid_size not in holes_apertures:
holes_apertures[clear_apid_size] = {}
holes_apertures[clear_apid_size]['type'] = 'C'
holes_apertures[clear_apid_size]['size'] = clear_apid_size
holes_apertures[clear_apid_size]['geometry'] = []
if clear_apid_size not in holes_apertures:
holes_apertures[clear_apid_size] = {}
holes_apertures[clear_apid_size]['type'] = 'C'
holes_apertures[clear_apid_size]['size'] = clear_apid_size
holes_apertures[clear_apid_size]['geometry'] = []
holes_apertures[clear_apid_size]['geometry'].append(deepcopy(geo_elem))
holes_apertures[clear_apid_size]['geometry'].append(deepcopy(geo_elem))
# add the clear geometry to new apertures; it's easier than to test if there are apertures with the same
# size and add there the clear geometry
@ -264,8 +267,8 @@ class ToolPunchGerber(AppTool):
new_obj.apertures = deepcopy(new_apertures)
new_obj.solid_geometry = deepcopy(punched_solid_geometry)
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
new_obj.source_file = self.app.f_handlers.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.app_obj.new_object('gerber', outname, init_func)
elif punch_method == 'fixed':
@ -387,8 +390,8 @@ class ToolPunchGerber(AppTool):
new_obj.apertures = deepcopy(new_apertures)
new_obj.solid_geometry = deepcopy(punched_solid_geometry)
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
new_obj.source_file = self.app.f_handlers.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.app_obj.new_object('gerber', outname, init_func)
elif punch_method == 'ring':
@ -529,8 +532,8 @@ class ToolPunchGerber(AppTool):
new_obj.apertures = deepcopy(new_apertures)
new_obj.solid_geometry = deepcopy(punched_solid_geometry)
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
new_obj.source_file = self.app.f_handlers.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.app_obj.new_object('gerber', outname, init_func)
@ -668,8 +671,8 @@ class ToolPunchGerber(AppTool):
new_obj.apertures = deepcopy(new_apertures)
new_obj.solid_geometry = deepcopy(punched_solid_geometry)
new_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
new_obj.source_file = self.app.f_handlers.export_gerber(obj_name=outname, filename=None,
local_use=new_obj, use_thread=False)
self.app.app_obj.new_object('gerber', outname, init_func)

View File

@ -314,8 +314,9 @@ class QRCode(AppTool):
self.grb_object.apertures[new_apid]['geometry'].append(deepcopy(geo_elem))
# update the source file with the new geometry:
self.grb_object.source_file = self.app.export_gerber(obj_name=self.grb_object.options['name'], filename=None,
local_use=self.grb_object, use_thread=False)
self.grb_object.source_file = self.app.f_handlers.export_gerber(obj_name=self.grb_object.options['name'],
filename=None,
local_use=self.grb_object, use_thread=False)
self.replot(obj=self.grb_object)
self.app.inform.emit('[success] %s' % _("QRCode Tool done."))

View File

@ -357,7 +357,7 @@ class RulesCheck(AppTool):
name = elem['name']
for tool in elem['tools']:
tool_dia = float('%.*f' % (4, float(elem['tools'][tool]['C'])))
tool_dia = float('%.*f' % (4, float(elem['tools'][tool]['tooldia'])))
if tool_dia < float(size):
dia_list.append(tool_dia)
obj_violations['name'] = name
@ -623,7 +623,8 @@ class RulesCheck(AppTool):
log.debug("RuleCheck() executing")
def worker_job(app_obj):
self.app.proc_container.new(_("Working..."))
# self.app.proc_container.new(_("Working..."))
self.app.proc_container.view.set_busy('%s' % _("Working..."))
# RULE: Check Trace Size
if self.ui.trace_size_cb.get_value():
@ -1055,6 +1056,7 @@ class RulesCheck(AppTool):
output.append(p.get())
self.tool_finished.emit(output)
self.app.proc_container.view.set_idle()
log.debug("RuleCheck() finished")

View File

@ -290,7 +290,7 @@ class FCShell(TermWidget):
self._edit.set_model_data(self.app.myKeywords)
self.setWindowIcon(self.app.ui.app_icon)
self.setWindowTitle("FlatCAM Shell")
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"))

View File

@ -320,8 +320,8 @@ class ToolSub(AppTool):
grb_obj.solid_geometry = deepcopy(poly_buff)
grb_obj.follow_geometry = deepcopy(follow_buff)
grb_obj.source_file = self.app.export_gerber(obj_name=outname, filename=None,
local_use=grb_obj, use_thread=False)
grb_obj.source_file = self.app.f_handlers.export_gerber(obj_name=outname, filename=None,
local_use=grb_obj, use_thread=False)
with self.app.proc_container.new(_("Generating new object ...")):
ret = self.app.app_obj.new_object('gerber', outname, obj_init, autoselected=False)
@ -635,11 +635,13 @@ class SubUI:
self.tools_frame.setLayout(self.tools_box)
# Form Layout
form_layout = QtWidgets.QFormLayout()
self.tools_box.addLayout(form_layout)
grid0 = QtWidgets.QGridLayout()
grid0.setColumnStretch(0, 0)
grid0.setColumnStretch(1, 1)
self.tools_box.addLayout(grid0)
self.gerber_title = QtWidgets.QLabel("<b>%s</b>" % _("GERBER"))
form_layout.addRow(self.gerber_title)
grid0.addWidget(self.gerber_title, 0, 0, 1, 2)
# Target Gerber Object
self.target_gerber_combo = FCComboBox()
@ -655,7 +657,8 @@ class SubUI:
"the subtractor Gerber object.")
)
form_layout.addRow(self.target_gerber_label, self.target_gerber_combo)
grid0.addWidget(self.target_gerber_label, 2, 0)
grid0.addWidget(self.target_gerber_combo, 2, 1)
# Substractor Gerber Object
self.sub_gerber_combo = FCComboBox()
@ -669,9 +672,9 @@ class SubUI:
_("Gerber object that will be subtracted\n"
"from the target Gerber object.")
)
e_lab_1 = QtWidgets.QLabel('')
form_layout.addRow(self.sub_gerber_label, self.sub_gerber_combo)
grid0.addWidget(self.sub_gerber_label, 4, 0)
grid0.addWidget(self.sub_gerber_combo, 4, 1)
self.intersect_btn = FCButton(_('Subtract Gerber'))
self.intersect_btn.setToolTip(
@ -686,15 +689,11 @@ class SubUI:
font-weight: bold;
}
""")
self.tools_box.addWidget(self.intersect_btn)
self.tools_box.addWidget(e_lab_1)
# Form Layout
form_geo_layout = QtWidgets.QFormLayout()
self.tools_box.addLayout(form_geo_layout)
grid0.addWidget(self.intersect_btn, 6, 0, 1, 2)
grid0.addWidget(QtWidgets.QLabel(''), 8, 0, 1, 2)
self.geo_title = QtWidgets.QLabel("<b>%s</b>" % _("GEOMETRY"))
form_geo_layout.addRow(self.geo_title)
grid0.addWidget(self.geo_title, 10, 0, 1, 2)
# Target Geometry Object
self.target_geo_combo = FCComboBox()
@ -710,7 +709,8 @@ class SubUI:
"the subtractor Geometry object.")
)
form_geo_layout.addRow(self.target_geo_label, self.target_geo_combo)
grid0.addWidget(self.target_geo_label, 12, 0)
grid0.addWidget(self.target_geo_combo, 12, 1)
# Substractor Geometry Object
self.sub_geo_combo = FCComboBox()
@ -724,13 +724,14 @@ class SubUI:
_("Geometry object that will be subtracted\n"
"from the target Geometry object.")
)
e_lab_1 = QtWidgets.QLabel('')
form_geo_layout.addRow(self.sub_geo_label, self.sub_geo_combo)
grid0.addWidget(self.sub_geo_label, 14, 0)
grid0.addWidget(self.sub_geo_combo, 14, 1)
self.close_paths_cb = FCCheckBox(_("Close paths"))
self.close_paths_cb.setToolTip(_("Checking this will close the paths cut by the Geometry subtractor object."))
self.tools_box.addWidget(self.close_paths_cb)
grid0.addWidget(self.close_paths_cb, 16, 0, 1, 2)
self.intersect_geo_btn = FCButton(_('Subtract Geometry'))
self.intersect_geo_btn.setToolTip(
@ -743,8 +744,9 @@ class SubUI:
font-weight: bold;
}
""")
self.tools_box.addWidget(self.intersect_geo_btn)
self.tools_box.addWidget(e_lab_1)
grid0.addWidget(self.intersect_geo_btn, 18, 0, 1, 2)
grid0.addWidget(QtWidgets.QLabel(''), 20, 0, 1, 2)
self.tools_box.addStretch()

View File

@ -457,14 +457,14 @@ class ToolTransform(AppTool):
self.app.inform.emit(_("CNCJob objects can't be buffered."))
elif sel_obj.kind.lower() == 'gerber':
sel_obj.buffer(value, join, factor)
sel_obj.source_file = self.app.export_gerber(obj_name=sel_obj.options['name'],
filename=None, local_use=sel_obj,
use_thread=False)
sel_obj.source_file = self.app.f_handlers.export_gerber(obj_name=sel_obj.options['name'],
filename=None, local_use=sel_obj,
use_thread=False)
elif sel_obj.kind.lower() == 'excellon':
sel_obj.buffer(value, join, factor)
sel_obj.source_file = self.app.export_excellon(obj_name=sel_obj.options['name'],
filename=None, local_use=sel_obj,
use_thread=False)
sel_obj.source_file = self.app.f_handlers.export_excellon(obj_name=sel_obj.options['name'],
filename=None, local_use=sel_obj,
use_thread=False)
elif sel_obj.kind.lower() == 'geometry':
sel_obj.buffer(value, join, factor)

View File

@ -29,7 +29,6 @@ languages_dict = {
'en': 'English',
'es': 'Spanish',
'fr': 'French',
'hu': 'Hungarian',
'it': 'Italian',
'pt_BR': 'Brazilian Portuguese',
'ro': 'Romanian',

File diff suppressed because it is too large Load Diff

View File

@ -3444,7 +3444,7 @@ class CNCjob(Geometry):
# Move to End position
t_gcode += self.doformat(p.end_code, x=0, y=0)
self.app.inform.emit(_("Finished G-Code generation for tool: %s" % str(tool)))
self.app.inform.emit('%s %s' % (_("Finished G-Code generation for tool:"), str(tool)))
return t_gcode, (locx, locy), start_gcode
def generate_from_excellon_by_tool(self, exobj, tools="all", order='fwd', use_ui=False):

View File

@ -31,10 +31,9 @@ class FlatCAMDefaults:
"global_stats": dict(),
"global_tabs_detachable": True,
"global_coords_show": True,
"global_delta_coords_show": False,
"global_grid_show": True,
"global_status_show": True,
"global_coordsbar_show": True,
"global_delta_coordsbar_show": False,
"global_statusbar_show": True,
"global_jump_ref": 'abs',
"global_locate_pt": 'bl',
@ -51,7 +50,6 @@ class FlatCAMDefaults:
'in': [0.01, 0.02, 0.025, 0.05, 0.1],
'mm': [0.1, 0.2, 0.5, 1, 2.54]
},
"global_hud": True,
# Persistence
"global_last_folder": None,
@ -126,6 +124,7 @@ class FlatCAMDefaults:
"global_project_autohide": True,
# General App Settings
"global_gridbar_show": True,
"global_gridx": 1.0,
"global_gridy": 1.0,
"global_snap_max": 0.05,
@ -133,6 +132,10 @@ class FlatCAMDefaults:
"global_workspace": False,
"global_workspaceT": "A4",
"global_workspace_orientation": 'p',
"global_axis": True,
"global_hud": True,
"global_grid_lines": True,
"global_grid_snap": True,
"global_cursor_type": "small",
"global_cursor_size": 20,
@ -461,26 +464,27 @@ class FlatCAMDefaults:
"tools_drill_area_overz": 1.0,
# NCC Tool
"tools_ncctools": "1.0, 0.5",
"tools_nccorder": 'rev',
"tools_nccoperation": 'clear',
"tools_nccoverlap": 40,
"tools_nccmargin": 1.0,
"tools_nccmethod": _("Seed"),
"tools_nccconnect": True,
"tools_ncccontour": True,
"tools_nccrest": False,
"tools_ncc_tools": "1.0, 0.5",
"tools_ncc_order": 'rev',
"tools_ncc_operation": 'clear',
"tools_ncc_overlap": 40,
"tools_ncc_margin": 1.0,
"tools_ncc_method": _("Seed"),
"tools_ncc_connect": True,
"tools_ncc_contour": True,
"tools_ncc_rest": False,
"tools_ncc_offset_choice": False,
"tools_ncc_offset_value": 0.0000,
"tools_nccref": _('Itself'),
"tools_ncc_ref": _('Itself'),
"tools_ncc_area_shape": "square",
"tools_nccmilling_type": 'cl',
"tools_ncctool_type": 'C1',
"tools_ncccutz": -0.05,
"tools_ncctipdia": 0.1,
"tools_ncctipangle": 30,
"tools_nccnewdia": 0.1,
"tools_ncc_milling_type": 'cl',
"tools_ncc_tool_type": 'C1',
"tools_ncc_cutz": -0.05,
"tools_ncc_tipdia": 0.1,
"tools_ncc_tipangle": 30,
"tools_ncc_newdia": 0.1,
"tools_ncc_plotting": 'normal',
"tools_ncc_check_valid": True,
# Cutout Tool
"tools_cutout_tooldia": 2.4,
@ -499,22 +503,22 @@ class FlatCAMDefaults:
"tools_cutout_mb_spacing": 0.3,
# Paint Tool
"tools_painttooldia": 0.3,
"tools_paintorder": 'rev',
"tools_paintoverlap": 20,
"tools_paintoffset": 0.0,
"tools_paintmethod": _("Seed"),
"tools_selectmethod": _("All"),
"tools_paint_tooldia": 0.3,
"tools_paint_order": 'rev',
"tools_paint_overlap": 20,
"tools_paint_offset": 0.0,
"tools_paint_method": _("Seed"),
"tools_paint_selectmethod": _("All"),
"tools_paint_area_shape": "square",
"tools_pathconnect": True,
"tools_paintcontour": True,
"tools_paint_connect": True,
"tools_paint_contour": True,
"tools_paint_plotting": 'normal',
"tools_paintrest": False,
"tools_painttool_type": 'C1',
"tools_paintcutz": -0.05,
"tools_painttipdia": 0.1,
"tools_painttipangle": 30,
"tools_paintnewdia": 0.1,
"tools_paint_rest": False,
"tools_paint_tool_type": 'C1',
"tools_paint_cutz": -0.05,
"tools_paint_tipdia": 0.1,
"tools_paint_tipangle": 30,
"tools_paint_newdia": 0.1,
# 2-Sided Tool
"tools_2sided_mirror_axis": "X",

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,249 @@
# ##########################################################
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Matthieu Berthomé #
# Date: 5/26/2017 #
# MIT Licence #
# ##########################################################
from appPreProcessor import *
class Default_no_M6(PreProc):
include_header = True
coordinate_format = "%.*f"
feedrate_format = '%.*f'
def start_code(self, p):
units = ' ' + str(p['units']).lower()
coords_xy = p['xy_toolchange']
end_coords_xy = p['xy_end']
gcode = '(This preprocessor is the default preprocessor used by FlatCAM.)\n'
gcode += '(It is made to work with MACH3 compatible motion controllers.)\n\n'
xmin = '%.*f' % (p.coords_decimals, p['options']['xmin'])
xmax = '%.*f' % (p.coords_decimals, p['options']['xmax'])
ymin = '%.*f' % (p.coords_decimals, p['options']['ymin'])
ymax = '%.*f' % (p.coords_decimals, p['options']['ymax'])
if str(p['options']['type']) == 'Geometry':
gcode += '(TOOL DIAMETER: ' + str(p['options']['tool_dia']) + units + ')\n'
gcode += '(Feedrate_XY: ' + str(p['feedrate']) + units + '/min' + ')\n'
gcode += '(Feedrate_Z: ' + str(p['z_feedrate']) + units + '/min' + ')\n'
gcode += '(Feedrate rapids ' + str(p['feedrate_rapid']) + units + '/min' + ')\n' + '\n'
gcode += '(Z_Cut: ' + str(p['z_cut']) + units + ')\n'
if p['multidepth'] is True:
gcode += '(DepthPerCut: ' + str(p['z_depthpercut']) + units + ' <=>' + \
str(math.ceil(abs(p['z_cut']) / p['z_depthpercut'])) + ' passes' + ')\n'
gcode += '(Z_Move: ' + str(p['z_move']) + units + ')\n'
elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True:
gcode += '\n(TOOLS DIAMETER: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n'
gcode += '\n(FEEDRATE Z: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Feedrate: %s' % \
str(val['data']["tools_drill_feedrate_z"]) + ')\n'
gcode += '\n(FEEDRATE RAPIDS: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Feedrate Rapids: %s' % \
str(val['data']["tools_drill_feedrate_rapid"]) + ')\n'
gcode += '\n(Z_CUT: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Z_Cut: %s' % str(val['data']["tools_drill_cutz"]) + ')\n'
gcode += '\n(Tools Offset: )\n'
for tool, val in p['exc_cnc_tools'].items():
gcode += '(Tool: %s -> ' % str(val['tool']) + 'Offset Z: %s' % \
str(val['data']["tools_drill_offset"]) + ')\n'
if p['multidepth'] is True:
gcode += '\n(DEPTH_PER_CUT: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'DeptPerCut: %s' % \
str(val['data']["tools_drill_depthperpass"]) + ')\n'
gcode += '\n(Z_MOVE: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Z_Move: %s' % str(val['data']["tools_drill_travelz"]) + ')\n'
gcode += '\n'
if p['toolchange'] is True:
gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
if coords_xy is not None:
gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
p.decimals, coords_xy[1]) + units + ')\n'
else:
gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
gcode += '(Z Start: ' + str(p['startz']) + units + ')\n'
gcode += '(Z End: ' + str(p['z_end']) + units + ')\n'
if end_coords_xy is not None:
gcode += '(X,Y End: ' + "%.*f, %.*f" % (p.decimals, end_coords_xy[0],
p.decimals, end_coords_xy[1]) + units + ')\n'
else:
gcode += '(X,Y End: ' + "None" + units + ')\n'
gcode += '(Steps per circle: ' + str(p['steps_per_circle']) + ')\n'
if str(p['options']['type']) == 'Excellon' or str(p['options']['type']) == 'Excellon Geometry':
gcode += '(Preprocessor Excellon: ' + str(p['pp_excellon_name']) + ')\n' + '\n'
else:
gcode += '(Preprocessor Geometry: ' + str(p['pp_geometry_name']) + ')\n' + '\n'
gcode += '(X range: ' + '{: >9s}'.format(xmin) + ' ... ' + '{: >9s}'.format(xmax) + ' ' + units + ')\n'
gcode += '(Y range: ' + '{: >9s}'.format(ymin) + ' ... ' + '{: >9s}'.format(ymax) + ' ' + units + ')\n\n'
gcode += '(Spindle Speed: %s RPM)\n' % str(p['spindlespeed'])
gcode += ('G20\n' if p.units.upper() == 'IN' else 'G21\n')
gcode += 'G90\n'
gcode += 'G94'
return gcode
def startz_code(self, p):
if p.startz is not None:
return 'G00 Z' + self.coordinate_format % (p.coords_decimals, p.startz)
else:
return ''
def lift_code(self, p):
return 'G00 Z' + self.coordinate_format % (p.coords_decimals, p.z_move)
def down_code(self, p):
return 'G01 Z' + self.coordinate_format % (p.coords_decimals, p.z_cut)
def toolchange_code(self, p):
z_toolchange = p.z_toolchange
toolchangexy = p.xy_toolchange
f_plunge = p.f_plunge
if toolchangexy is not None:
x_toolchange = toolchangexy[0]
y_toolchange = toolchangexy[1]
else:
x_toolchange = 0.0
y_toolchange = 0.0
no_drills = 1
if int(p.tool) == 1 and p.startz is not None:
z_toolchange = p.startz
toolC_formatted = '%.*f' % (p.decimals, p.toolC)
if str(p['options']['type']) == 'Excellon':
for i in p['options']['Tools_in_use']:
if i[0] == p.tool:
no_drills = i[2]
if toolchangexy is not None:
gcode = """
M5
G00 Z{z_toolchange}
T{tool}
G00 X{x_toolchange} Y{y_toolchange}
(MSG, Change to Tool Dia = {toolC} ||| Total drills for tool T{tool} = {t_drills})
M0
G00 Z{z_toolchange}
""".format(x_toolchange=self.coordinate_format % (p.coords_decimals, x_toolchange),
y_toolchange=self.coordinate_format % (p.coords_decimals, y_toolchange),
z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
tool=int(p.tool),
t_drills=no_drills,
toolC=toolC_formatted)
else:
gcode = """
M5
G00 Z{z_toolchange}
T{tool}
(MSG, Change to Tool Dia = {toolC} ||| Total drills for tool T{tool} = {t_drills})
M0
G00 Z{z_toolchange}
""".format(z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
tool=int(p.tool),
t_drills=no_drills,
toolC=toolC_formatted)
if f_plunge is True:
gcode += '\nG00 Z%.*f' % (p.coords_decimals, p.z_move)
return gcode
else:
if toolchangexy is not None:
gcode = """
M5
G00 Z{z_toolchange}
G00 X{x_toolchange} Y{y_toolchange}
T{tool}
(MSG, Change to Tool Dia = {toolC})
M0
G00 Z{z_toolchange}
""".format(x_toolchange=self.coordinate_format % (p.coords_decimals, x_toolchange),
y_toolchange=self.coordinate_format % (p.coords_decimals, y_toolchange),
z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
tool=int(p.tool),
toolC=toolC_formatted)
else:
gcode = """
M5
G00 Z{z_toolchange}
T{tool}
(MSG, Change to Tool Dia = {toolC})
M0
G00 Z{z_toolchange}
""".format(z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
tool=int(p.tool),
toolC=toolC_formatted)
if f_plunge is True:
gcode += '\nG00 Z%.*f' % (p.coords_decimals, p.z_move)
return gcode
def up_to_zero_code(self, p):
return 'G01 Z0'
def position_code(self, p):
return ('X' + self.coordinate_format + ' Y' + self.coordinate_format) % \
(p.coords_decimals, p.x, p.coords_decimals, p.y)
def rapid_code(self, p):
return ('G00 ' + self.position_code(p)).format(**p)
def linear_code(self, p):
return ('G01 ' + self.position_code(p)).format(**p)
def end_code(self, p):
end_coords_xy = p['xy_end']
gcode = ('G00 Z' + self.feedrate_format % (p.fr_decimals, p.z_end) + "\n")
if end_coords_xy and end_coords_xy != '':
gcode += 'G00 X{x} Y{y}'.format(x=end_coords_xy[0], y=end_coords_xy[1]) + "\n"
return gcode
def feedrate_code(self, p):
return 'G01 F' + str(self.feedrate_format % (p.fr_decimals, p.feedrate))
def z_feedrate_code(self, p):
return 'G01 F' + str(self.feedrate_format % (p.fr_decimals, p.z_feedrate))
def spindle_code(self, p):
sdir = {'CW': 'M03', 'CCW': 'M04'}[p.spindledir]
if p.spindlespeed:
return '%s S%s' % (sdir, str(p.spindlespeed))
else:
return sdir
def dwell_code(self, p):
if p.dwelltime:
return 'G4 P' + str(p.dwelltime)
def spindle_stop_code(self, p):
return 'M05'

View File

@ -0,0 +1,251 @@
# ##########################################################
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# File Author: Matthieu Berthomé #
# Date: 5/26/2017 #
# MIT Licence #
# ##########################################################
from appPreProcessor import *
class GRBL_11_no_M6(PreProc):
include_header = True
coordinate_format = "%.*f"
feedrate_format = '%.*f'
def start_code(self, p):
units = ' ' + str(p['units']).lower()
coords_xy = p['xy_toolchange']
end_coords_xy = p['xy_end']
gcode = '(This preprocessor is used with a motion controller loaded with GRBL firmware.)\n'
gcode += '(It is configured to be compatible with almost any version of GRBL firmware.)\n\n'
xmin = '%.*f' % (p.coords_decimals, p['options']['xmin'])
xmax = '%.*f' % (p.coords_decimals, p['options']['xmax'])
ymin = '%.*f' % (p.coords_decimals, p['options']['ymin'])
ymax = '%.*f' % (p.coords_decimals, p['options']['ymax'])
if str(p['options']['type']) == 'Geometry':
gcode += '(TOOL DIAMETER: ' + str(p['options']['tool_dia']) + units + ')\n'
gcode += '(Feedrate_XY: ' + str(p['feedrate']) + units + '/min' + ')\n'
gcode += '(Feedrate_Z: ' + str(p['z_feedrate']) + units + '/min' + ')\n'
gcode += '(Feedrate rapids ' + str(p['feedrate_rapid']) + units + '/min' + ')\n' + '\n'
gcode += '(Z_Cut: ' + str(p['z_cut']) + units + ')\n'
if p['multidepth'] is True:
gcode += '(DepthPerCut: ' + str(p['z_depthpercut']) + units + ' <=>' + \
str(math.ceil(abs(p['z_cut']) / p['z_depthpercut'])) + ' passes' + ')\n'
gcode += '(Z_Move: ' + str(p['z_move']) + units + ')\n'
elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True:
gcode += '\n(TOOLS DIAMETER: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n'
gcode += '\n(FEEDRATE Z: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Feedrate: %s' % \
str(val['data']["tools_drill_feedrate_z"]) + ')\n'
gcode += '\n(FEEDRATE RAPIDS: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Feedrate Rapids: %s' % \
str(val['data']["tools_drill_feedrate_rapid"]) + ')\n'
gcode += '\n(Z_CUT: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Z_Cut: %s' % str(val['data']["tools_drill_cutz"]) + ')\n'
gcode += '\n(Tools Offset: )\n'
for tool, val in p['exc_cnc_tools'].items():
gcode += '(Tool: %s -> ' % str(val['tool']) + 'Offset Z: %s' % \
str(val['data']["tools_drill_offset"]) + ')\n'
if p['multidepth'] is True:
gcode += '\n(DEPTH_PER_CUT: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'DeptPerCut: %s' % \
str(val['data']["tools_drill_depthperpass"]) + ')\n'
gcode += '\n(Z_MOVE: )\n'
for tool, val in p['exc_tools'].items():
gcode += '(Tool: %s -> ' % str(tool) + 'Z_Move: %s' % str(val['data']["tools_drill_travelz"]) + ')\n'
gcode += '\n'
if p['toolchange'] is True:
gcode += '(Z Toolchange: ' + str(p['z_toolchange']) + units + ')\n'
if coords_xy is not None:
gcode += '(X,Y Toolchange: ' + "%.*f, %.*f" % (p.decimals, coords_xy[0],
p.decimals, coords_xy[1]) + units + ')\n'
else:
gcode += '(X,Y Toolchange: ' + "None" + units + ')\n'
gcode += '(Z Start: ' + str(p['startz']) + units + ')\n'
gcode += '(Z End: ' + str(p['z_end']) + units + ')\n'
if end_coords_xy is not None:
gcode += '(X,Y End: ' + "%.*f, %.*f" % (p.decimals, end_coords_xy[0],
p.decimals, end_coords_xy[1]) + units + ')\n'
else:
gcode += '(X,Y End: ' + "None" + units + ')\n'
gcode += '(Steps per circle: ' + str(p['steps_per_circle']) + ')\n'
gcode += '(Steps per circle: ' + str(p['steps_per_circle']) + ')\n'
if str(p['options']['type']) == 'Excellon' or str(p['options']['type']) == 'Excellon Geometry':
gcode += '(Preprocessor Excellon: ' + str(p['pp_excellon_name']) + ')\n' + '\n'
else:
gcode += '(Preprocessor Geometry: ' + str(p['pp_geometry_name']) + ')\n' + '\n'
gcode += '(X range: ' + '{: >9s}'.format(xmin) + ' ... ' + '{: >9s}'.format(xmax) + ' ' + units + ')\n'
gcode += '(Y range: ' + '{: >9s}'.format(ymin) + ' ... ' + '{: >9s}'.format(ymax) + ' ' + units + ')\n\n'
gcode += '(Spindle Speed: %s RPM)\n' % str(p['spindlespeed'])
gcode += ('G20' if p.units.upper() == 'IN' else 'G21') + "\n"
gcode += 'G90\n'
gcode += 'G17\n'
gcode += 'G94\n'
return gcode
def startz_code(self, p):
if p.startz is not None:
return 'G00 Z' + self.coordinate_format % (p.coords_decimals, p.startz)
else:
return ''
def lift_code(self, p):
return 'G00 Z' + self.coordinate_format % (p.coords_decimals, p.z_move)
def down_code(self, p):
return 'G01 Z' + self.coordinate_format % (p.coords_decimals, p.z_cut)
def toolchange_code(self, p):
z_toolchange = p.z_toolchange
toolchangexy = p.xy_toolchange
f_plunge = p.f_plunge
if toolchangexy is not None:
x_toolchange = toolchangexy[0]
y_toolchange = toolchangexy[1]
else:
x_toolchange = 0.0
y_toolchange = 0.0
no_drills = 1
if int(p.tool) == 1 and p.startz is not None:
z_toolchange = p.startz
toolC_formatted = '%.*f' % (p.decimals, p.toolC)
if str(p['options']['type']) == 'Excellon':
for i in p['options']['Tools_in_use']:
if i[0] == p.tool:
no_drills = i[2]
if toolchangexy is not None:
gcode = """
M5
G00 Z{z_toolchange}
G00 X{x_toolchange} Y{y_toolchange}
T{tool}
(MSG, Change to Tool Dia = {toolC} ||| Total drills for tool T{tool} = {t_drills})
M0
G00 Z{z_toolchange}
""".format(x_toolchange=self.coordinate_format % (p.coords_decimals, x_toolchange),
y_toolchange=self.coordinate_format % (p.coords_decimals, y_toolchange),
z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
tool=int(p.tool),
t_drills=no_drills,
toolC=toolC_formatted)
else:
gcode = """
M5
G00 Z{z_toolchange}
T{tool}
(MSG, Change to Tool Dia = {toolC} ||| Total drills for tool T{tool} = {t_drills})
M0
G00 Z{z_toolchange}
""".format(z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
tool=int(p.tool),
t_drills=no_drills,
toolC=toolC_formatted)
if f_plunge is True:
gcode += '\nG00 Z%.*f' % (p.coords_decimals, p.z_move)
return gcode
else:
if toolchangexy is not None:
gcode = """
M5
G00 Z{z_toolchange}
G00 X{x_toolchange} Y{y_toolchange}
T{tool}
(MSG, Change to Tool Dia = {toolC})
M0
G00 Z{z_toolchange}
""".format(x_toolchange=self.coordinate_format % (p.coords_decimals, x_toolchange),
y_toolchange=self.coordinate_format % (p.coords_decimals, y_toolchange),
z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
tool=int(p.tool),
toolC=toolC_formatted)
else:
gcode = """
M5
G00 Z{z_toolchange}
T{tool}
(MSG, Change to Tool Dia = {toolC})
M0
G00 Z{z_toolchange}
""".format(z_toolchange=self.coordinate_format % (p.coords_decimals, z_toolchange),
tool=int(p.tool),
toolC=toolC_formatted)
if f_plunge is True:
gcode += '\nG00 Z%.*f' % (p.coords_decimals, p.z_move)
return gcode
def up_to_zero_code(self, p):
return 'G01 Z0'
def position_code(self, p):
return ('X' + self.coordinate_format + ' Y' + self.coordinate_format) % \
(p.coords_decimals, p.x, p.coords_decimals, p.y)
def rapid_code(self, p):
return ('G00 ' + self.position_code(p)).format(**p)
def linear_code(self, p):
return ('G01 ' + self.position_code(p)).format(**p) + \
' F' + str(self.feedrate_format % (p.fr_decimals, p.feedrate))
def end_code(self, p):
coords_xy = p['xy_end']
gcode = ('G00 Z' + self.feedrate_format % (p.fr_decimals, p.z_end) + "\n")
if coords_xy and coords_xy != '':
gcode += 'G00 X{x} Y{y}'.format(x=coords_xy[0], y=coords_xy[1]) + "\n"
return gcode
def feedrate_code(self, p):
return 'G01 F' + str(self.feedrate_format % (p.fr_decimals, p.feedrate))
def z_feedrate_code(self, p):
return 'G01 F' + str(self.feedrate_format % (p.fr_decimals, p.z_feedrate))
def spindle_code(self, p):
sdir = {'CW': 'M03', 'CCW': 'M04'}[p.spindledir]
if p.spindlespeed:
return '%s S%s' % (sdir, str(p.spindlespeed))
else:
return sdir
def dwell_code(self, p):
if p.dwelltime:
return 'G4 P' + str(p.dwelltime)
def spindle_stop_code(self, p):
return 'M05'

View File

@ -103,22 +103,22 @@ class TclCommandCopperClear(TclCommand):
if 'tooldia' in args:
tooldia = str(args['tooldia'])
else:
tooldia = self.app.defaults["tools_ncctools"]
tooldia = self.app.defaults["tools_ncc_tools"]
if 'overlap' in args:
overlap = float(args['overlap']) / 100.0
else:
overlap = float(self.app.defaults["tools_nccoverlap"]) / 100.0
overlap = float(self.app.defaults["tools_ncc_overlap"]) / 100.0
if 'order' in args:
order = args['order']
else:
order = str(self.app.defaults["tools_nccorder"])
order = str(self.app.defaults["tools_ncc_order"])
if 'margin' in args:
margin = float(args['margin'])
else:
margin = float(self.app.defaults["tools_nccmargin"])
margin = float(self.app.defaults["tools_ncc_margin"])
if 'method' in args:
method = args['method']
@ -129,7 +129,7 @@ class TclCommandCopperClear(TclCommand):
else:
method_data = _("Lines")
else:
method = str(self.app.defaults["tools_nccmethod"])
method = str(self.app.defaults["tools_ncc_method"])
method_data = method
if method == _("Standard"):
method = "standard"
@ -145,7 +145,7 @@ class TclCommandCopperClear(TclCommand):
par = args['connect']
connect = bool(eval(par))
else:
connect = bool(eval(str(self.app.defaults["tools_nccconnect"])))
connect = bool(eval(str(self.app.defaults["tools_ncc_connect"])))
if 'contour' in args:
try:
@ -154,7 +154,7 @@ class TclCommandCopperClear(TclCommand):
par = args['contour']
contour = bool(eval(par))
else:
contour = bool(eval(str(self.app.defaults["tools_ncccontour"])))
contour = bool(eval(str(self.app.defaults["tools_ncc_contour"])))
offset = 0.0
if 'offset' in args:
@ -175,7 +175,7 @@ class TclCommandCopperClear(TclCommand):
par = args['rest']
rest = bool(eval(par))
else:
rest = bool(eval(str(self.app.defaults["tools_nccrest"])))
rest = bool(eval(str(self.app.defaults["tools_ncc_rest"])))
if 'outname' in args:
outname = args['outname']
@ -223,19 +223,19 @@ class TclCommandCopperClear(TclCommand):
"area_strategy": self.app.defaults["geometry_area_strategy"],
"area_overz": float(self.app.defaults["geometry_area_overz"]),
"tooldia": self.app.defaults["tools_painttooldia"],
"tools_nccoperation": self.app.defaults["tools_nccoperation"],
"tooldia": self.app.defaults["tools_paint_tooldia"],
"tools_ncc_operation": self.app.defaults["tools_ncc_operation"],
"tools_nccmargin": margin,
"tools_nccmethod": method_data,
"tools_nccref": select,
"tools_nccconnect": connect,
"tools_ncccontour": contour,
"tools_nccoverlap": overlap,
"tools_ncc_margin": margin,
"tools_ncc_method": method_data,
"tools_ncc_ref": select,
"tools_ncc_connect": connect,
"tools_ncc_contour": contour,
"tools_ncc_overlap": overlap,
"tools_ncc_offset_choice": self.app.defaults["tools_ncc_offset_choice"],
"tools_ncc_offset_value": self.app.defaults["tools_ncc_offset_value"],
"tools_nccmilling_type": self.app.defaults["tools_nccmilling_type"]
"tools_ncc_milling_type": self.app.defaults["tools_ncc_milling_type"]
})
ncc_tools = {}

View File

@ -49,4 +49,4 @@ class TclCommandExportDXF(TclCommand):
"""
if 'filename' not in args:
args['filename'] = self.app.defaults["global_last_save_folder"] + '/' + args['name']
self.app.export_dxf(use_thread=False, local_use=None, **args)
self.app.f_handlers.export_dxf(use_thread=False, local_use=None, **args)

View File

@ -49,4 +49,4 @@ class TclCommandExportExcellon(TclCommand):
"""
if 'filename' not in args:
args['filename'] = self.app.defaults["global_last_save_folder"] + '/' + args['name']
self.app.export_excellon(use_thread=False, **args)
self.app.f_handlers.export_excellon(use_thread=False, **args)

View File

@ -49,4 +49,4 @@ class TclCommandExportGerber(TclCommand):
"""
if 'filename' not in args:
args['filename'] = self.app.defaults["global_last_save_folder"] + '/' + args['name']
self.app.export_gerber(use_thread=False,**args)
self.app.f_handlers.export_gerber(use_thread=False,**args)

View File

@ -52,4 +52,4 @@ class TclCommandExportSVG(TclCommand):
:return:
"""
self.app.export_svg(**args)
self.app.f_handlers.export_svg(**args)

View File

@ -57,3 +57,5 @@ class TclCommandGetSys(TclCommand):
if name in self.app.defaults:
return self.app.defaults[name]
else:
return "The keyword: %s does not exist as a parameter" % str(name)

View File

@ -59,4 +59,4 @@ class TclCommandOpenExcellon(TclCommandSignaled):
args['plot'] = False
args['from_tcl'] = True
self.app.open_excellon(filename, **args)
self.app.f_handlers.open_excellon(filename, **args)

View File

@ -58,4 +58,4 @@ class TclCommandOpenGCode(TclCommandSignaled):
# return "The absolute path to the project file contain spaces which is not allowed.\n" \
# "Please enclose the path within quotes."
self.app.open_gcode(filename, **args)
self.app.f_handlers.open_gcode(filename, **args)

View File

@ -62,4 +62,4 @@ class TclCommandOpenGerber(TclCommandSignaled):
args['plot'] = False
args['from_tcl'] = True
self.app.open_gerber(filename, outname, **args)
self.app.f_handlers.open_gerber(filename, outname, **args)

View File

@ -53,4 +53,4 @@ class TclCommandOpenProject(TclCommandSignaled):
# return "The absolute path to the project file contain spaces which is not allowed.\n" \
# "Please enclose the path within quotes."
self.app.open_project(filename, cli=True, plot=False, from_tcl=True)
self.app.f_handlers.open_project(filename, cli=True, plot=False, from_tcl=True)

View File

@ -102,22 +102,22 @@ class TclCommandPaint(TclCommand):
if 'tooldia' in args:
tooldia = str(args['tooldia'])
else:
tooldia = float(self.app.defaults["tools_paintoverlap"])
tooldia = float(self.app.defaults["tools_paint_overlap"])
if 'overlap' in args:
overlap = float(args['overlap']) / 100.0
else:
overlap = float(self.app.defaults["tools_paintoverlap"]) / 100.0
overlap = float(self.app.defaults["tools_paint_overlap"]) / 100.0
if 'order' in args:
order = args['order']
else:
order = str(self.app.defaults["tools_paintorder"])
order = str(self.app.defaults["tools_paint_order"])
if 'offset' in args:
offset = float(args['offset'])
else:
offset = float(self.app.defaults["tools_paintoffset"])
offset = float(self.app.defaults["tools_paint_offset"])
if 'method' in args:
method = args['method']
@ -132,7 +132,7 @@ class TclCommandPaint(TclCommand):
else:
method = _("Combo")
else:
method = str(self.app.defaults["tools_paintmethod"])
method = str(self.app.defaults["tools_paint_method"])
if 'connect' in args:
try:
@ -141,7 +141,7 @@ class TclCommandPaint(TclCommand):
par = args['connect']
connect = bool(eval(par))
else:
connect = bool(eval(str(self.app.defaults["tools_pathconnect"])))
connect = bool(eval(str(self.app.defaults["tools_paint_connect"])))
if 'contour' in args:
try:
@ -150,7 +150,7 @@ class TclCommandPaint(TclCommand):
par = args['contour']
contour = bool(eval(par))
else:
contour = bool(eval(str(self.app.defaults["tools_paintcontour"])))
contour = bool(eval(str(self.app.defaults["tools_paint_contour"])))
if 'outname' in args:
outname = args['outname']
@ -175,8 +175,8 @@ class TclCommandPaint(TclCommand):
"name": outname,
"plot": False,
"cutz": self.app.defaults["geometry_cutz"],
"vtipdia": float(self.app.defaults["tools_painttipdia"]),
"vtipangle": float(self.app.defaults["tools_painttipangle"]),
"vtipdia": float(self.app.defaults["tools_paint_tipdia"]),
"vtipangle": float(self.app.defaults["tools_paint_tipangle"]),
"travelz": self.app.defaults["geometry_travelz"],
"feedrate": self.app.defaults["geometry_feedrate"],
"feedrate_z": self.app.defaults["geometry_feedrate_z"],
@ -202,13 +202,13 @@ class TclCommandPaint(TclCommand):
"area_strategy": self.app.defaults["geometry_area_strategy"],
"area_overz": float(self.app.defaults["geometry_area_overz"]),
"tooldia": self.app.defaults["tools_painttooldia"],
"tools_paintoffset": offset,
"tools_paintmethod": method,
"tools_selectmethod": select,
"tools_pathconnect": connect,
"tools_paintcontour": contour,
"tools_paintoverlap": overlap
"tooldia": self.app.defaults["tools_paint_tooldia"],
"tools_paint_offset": offset,
"tools_paint_method": method,
"tools_paint_selectmethod": select,
"tools_paint_connect": connect,
"tools_paint_contour": contour,
"tools_paint_overlap": overlap
})
paint_tools = {}