- maintenance_2

This commit is contained in:
Marius Stanciu
2020-06-02 18:29:45 +03:00
committed by Marius
parent 38fa25ed3d
commit f5c84fdc49
255 changed files with 162378 additions and 152106 deletions

View File

@@ -1,5 +1,5 @@
from PyQt5 import QtGui, QtCore, QtWidgets from PyQt5 import QtGui, QtCore, QtWidgets
from flatcamGUI.GUIElements import FCTable, FCEntry, FCButton, FCDoubleSpinner, FCComboBox, FCCheckBox, FCSpinner, \ from AppGUI.GUIElements import FCTable, FCEntry, FCButton, FCDoubleSpinner, FCComboBox, FCCheckBox, FCSpinner, \
FCTree, RadioSet, FCFileSaveDialog FCTree, RadioSet, FCFileSaveDialog
from camlib import to_dict from camlib import to_dict
@@ -8,8 +8,10 @@ import json
from copy import deepcopy from copy import deepcopy
from datetime import datetime from datetime import datetime
import math
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -117,7 +119,7 @@ class ToolsDB(QtWidgets.QWidget):
) )
self.buttons_box.addWidget(import_db_btn) self.buttons_box.addWidget(import_db_btn)
self.add_tool_from_db = FCButton(_("Add Tool from Tools DB")) self.add_tool_from_db = FCButton(_("Transfer the Tool"))
self.add_tool_from_db.setToolTip( self.add_tool_from_db.setToolTip(
_("Add a new tool in the Tools Table of the\n" _("Add a new tool in the Tools Table of the\n"
"active Geometry object after selecting a tool\n" "active Geometry object after selecting a tool\n"
@@ -313,7 +315,7 @@ class ToolsDB(QtWidgets.QWidget):
self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file.")) self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
return return
self.app.inform.emit('[success] %s: %s' % (_("Loaded FlatCAM Tools DB from"), filename)) self.app.inform.emit('[success] %s: %s' % (_("Loaded Tools DB from"), filename))
self.build_db_ui() self.build_db_ui()
@@ -655,7 +657,7 @@ class ToolsDB(QtWidgets.QWidget):
l_save=str(self.app.get_last_save_folder()), l_save=str(self.app.get_last_save_folder()),
n=_("Tools_Database"), n=_("Tools_Database"),
date=date), date=date),
filter=filter__) ext_filter=filter__)
filename = str(filename) filename = str(filename)
@@ -724,7 +726,7 @@ class ToolsDB(QtWidgets.QWidget):
self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file.")) self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
return return
self.app.inform.emit('[success] %s: %s' % (_("Loaded FlatCAM Tools DB from"), filename)) self.app.inform.emit('[success] %s: %s' % (_("Loaded Tools DB from"), filename))
self.build_db_ui() self.build_db_ui()
self.callback_on_edited() self.callback_on_edited()
@@ -1030,6 +1032,7 @@ class ToolsDB2(QtWidgets.QWidget):
self.advanced_box.setTitle(_("Advanced Geo Parameters")) self.advanced_box.setTitle(_("Advanced Geo Parameters"))
self.advanced_box.setFixedWidth(250) self.advanced_box.setFixedWidth(250)
# NCC TOOL BOX
self.ncc_box = QtWidgets.QGroupBox() self.ncc_box = QtWidgets.QGroupBox()
self.ncc_box.setStyleSheet(""" self.ncc_box.setStyleSheet("""
QGroupBox QGroupBox
@@ -1042,6 +1045,7 @@ class ToolsDB2(QtWidgets.QWidget):
self.ncc_box.setTitle(_("NCC Parameters")) self.ncc_box.setTitle(_("NCC Parameters"))
self.ncc_box.setFixedWidth(250) self.ncc_box.setFixedWidth(250)
# PAINT TOOL BOX
self.paint_box = QtWidgets.QGroupBox() self.paint_box = QtWidgets.QGroupBox()
self.paint_box.setStyleSheet(""" self.paint_box.setStyleSheet("""
QGroupBox QGroupBox
@@ -1054,10 +1058,24 @@ class ToolsDB2(QtWidgets.QWidget):
self.paint_box.setTitle(_("Paint Parameters")) self.paint_box.setTitle(_("Paint Parameters"))
self.paint_box.setFixedWidth(250) self.paint_box.setFixedWidth(250)
# ISOLATION TOOL BOX
self.iso_box = QtWidgets.QGroupBox()
self.iso_box.setStyleSheet("""
QGroupBox
{
font-size: 16px;
font-weight: bold;
}
""")
self.iso_vlay = QtWidgets.QVBoxLayout()
self.iso_box.setTitle(_("Isolation Parameters"))
self.iso_box.setFixedWidth(250)
self.basic_box.setLayout(self.basic_vlay) self.basic_box.setLayout(self.basic_vlay)
self.advanced_box.setLayout(self.advanced_vlay) self.advanced_box.setLayout(self.advanced_vlay)
self.ncc_box.setLayout(self.ncc_vlay) self.ncc_box.setLayout(self.ncc_vlay)
self.paint_box.setLayout(self.paint_vlay) self.paint_box.setLayout(self.paint_vlay)
self.iso_box.setLayout(self.iso_vlay)
geo_vlay = QtWidgets.QVBoxLayout() geo_vlay = QtWidgets.QVBoxLayout()
geo_vlay.addWidget(self.basic_box) geo_vlay.addWidget(self.basic_box)
@@ -1067,6 +1085,7 @@ class ToolsDB2(QtWidgets.QWidget):
tools_vlay = QtWidgets.QVBoxLayout() tools_vlay = QtWidgets.QVBoxLayout()
tools_vlay.addWidget(self.ncc_box) tools_vlay.addWidget(self.ncc_box)
tools_vlay.addWidget(self.paint_box) tools_vlay.addWidget(self.paint_box)
tools_vlay.addWidget(self.iso_box)
tools_vlay.addStretch() tools_vlay.addStretch()
param_hlay.addLayout(geo_vlay) param_hlay.addLayout(geo_vlay)
@@ -1478,7 +1497,7 @@ class ToolsDB2(QtWidgets.QWidget):
self.ncc_method_combo = FCComboBox() self.ncc_method_combo = FCComboBox()
self.ncc_method_combo.addItems( self.ncc_method_combo.addItems(
[_("Standard"), _("Seed"), _("Lines")] [_("Standard"), _("Seed"), _("Lines"), _("Combo")]
) )
self.ncc_method_combo.setObjectName("gdb_n_method") self.ncc_method_combo.setObjectName("gdb_n_method")
@@ -1621,6 +1640,101 @@ class ToolsDB2(QtWidgets.QWidget):
self.grid3.addWidget(self.pathconnect_cb, 10, 0) self.grid3.addWidget(self.pathconnect_cb, 10, 0)
self.grid3.addWidget(self.paintcontour_cb, 10, 1) self.grid3.addWidget(self.paintcontour_cb, 10, 1)
# ###########################################################################
# ############### Paint UI form #############################################
# ###########################################################################
self.grid4 = QtWidgets.QGridLayout()
self.iso_vlay.addLayout(self.grid4)
self.grid4.setColumnStretch(0, 0)
self.grid4.setColumnStretch(1, 1)
self.iso_vlay.addStretch()
# Passes
passlabel = QtWidgets.QLabel('%s:' % _('Passes'))
passlabel.setToolTip(
_("Width of the isolation gap in\n"
"number (integer) of tool widths.")
)
self.passes_entry = FCSpinner()
self.passes_entry.set_range(1, 999)
self.passes_entry.setObjectName("gdb_i_passes")
self.grid4.addWidget(passlabel, 0, 0)
self.grid4.addWidget(self.passes_entry, 0, 1)
# Overlap Entry
overlabel = QtWidgets.QLabel('%s:' % _('Overlap'))
overlabel.setToolTip(
_("How much (percentage) of the tool width to overlap each tool pass.")
)
self.iso_overlap_entry = FCDoubleSpinner(suffix='%')
self.iso_overlap_entry.set_precision(self.decimals)
self.iso_overlap_entry.setWrapping(True)
self.iso_overlap_entry.set_range(0.0000, 99.9999)
self.iso_overlap_entry.setSingleStep(0.1)
self.iso_overlap_entry.setObjectName("gdb_i_overlap")
self.grid4.addWidget(overlabel, 2, 0)
self.grid4.addWidget(self.iso_overlap_entry, 2, 1)
# Milling Type Radio Button
self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
self.milling_type_label.setToolTip(
_("Milling type when the selected tool is of type: 'iso_op':\n"
"- climb / best for precision milling and to reduce tool usage\n"
"- conventional / useful when there is no backlash compensation")
)
self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
{'label': _('Conventional'), 'value': 'cv'}])
self.milling_type_radio.setToolTip(
_("Milling type when the selected tool is of type: 'iso_op':\n"
"- climb / best for precision milling and to reduce tool usage\n"
"- conventional / useful when there is no backlash compensation")
)
self.milling_type_radio.setObjectName("gdb_i_milling_type")
self.grid4.addWidget(self.milling_type_label, 4, 0)
self.grid4.addWidget(self.milling_type_radio, 4, 1)
# Follow
self.follow_label = QtWidgets.QLabel('%s:' % _('Follow'))
self.follow_label.setToolTip(
_("Generate a 'Follow' geometry.\n"
"This means that it will cut through\n"
"the middle of the trace.")
)
self.follow_cb = FCCheckBox()
self.follow_cb.setToolTip(_("Generate a 'Follow' geometry.\n"
"This means that it will cut through\n"
"the middle of the trace."))
self.follow_cb.setObjectName("gdb_i_follow")
self.grid4.addWidget(self.follow_label, 6, 0)
self.grid4.addWidget(self.follow_cb, 6, 1)
# Isolation Type
self.iso_type_label = QtWidgets.QLabel('%s:' % _('Isolation Type'))
self.iso_type_label.setToolTip(
_("Choose how the isolation will be executed:\n"
"- 'Full' -> complete isolation of polygons\n"
"- 'Ext' -> will isolate only on the outside\n"
"- 'Int' -> will isolate only on the inside\n"
"'Exterior' isolation is almost always possible\n"
"(with the right tool) but 'Interior'\n"
"isolation can be done only when there is an opening\n"
"inside of the polygon (e.g polygon is a 'doughnut' shape).")
)
self.iso_type_radio = RadioSet([{'label': _('Full'), 'value': 'full'},
{'label': _('Ext'), 'value': 'ext'},
{'label': _('Int'), 'value': 'int'}])
self.iso_type_radio.setObjectName("gdb_i_iso_type")
self.grid4.addWidget(self.iso_type_label, 8, 0)
self.grid4.addWidget(self.iso_type_radio, 8, 1)
# #################################################################### # ####################################################################
# #################################################################### # ####################################################################
# GUI for the lower part of the window # GUI for the lower part of the window
@@ -1678,12 +1792,19 @@ class ToolsDB2(QtWidgets.QWidget):
) )
self.buttons_box.addWidget(self.save_db_btn) self.buttons_box.addWidget(self.save_db_btn)
self.add_tool_from_db = FCButton(_("Add Tool from Tools DB")) self.add_tool_from_db = FCButton(_("Transfer the Tool"))
self.add_tool_from_db.setToolTip( self.add_tool_from_db.setToolTip(
_("Add a new tool in the Tools Table of the\n" _("Insert a new tool in the Tools Table of the\n"
"active Geometry object after selecting a tool\n" "object/application tool after selecting a tool\n"
"in the Tools Database.") "in the Tools Database.")
) )
self.add_tool_from_db.setStyleSheet("""
QPushButton
{
font-weight: bold;
color: green;
}
""")
self.add_tool_from_db.hide() self.add_tool_from_db.hide()
self.cancel_tool_from_db = FCButton(_("Cancel")) self.cancel_tool_from_db = FCButton(_("Cancel"))
@@ -1693,7 +1814,7 @@ class ToolsDB2(QtWidgets.QWidget):
tree_layout.addLayout(hlay) tree_layout.addLayout(hlay)
hlay.addWidget(self.add_tool_from_db) hlay.addWidget(self.add_tool_from_db)
hlay.addWidget(self.cancel_tool_from_db) hlay.addWidget(self.cancel_tool_from_db)
hlay.addStretch() # hlay.addStretch()
# ############################################################################## # ##############################################################################
# ############################################################################## # ##############################################################################
@@ -1743,6 +1864,13 @@ class ToolsDB2(QtWidgets.QWidget):
"tools_paintmethod": self.paintmethod_combo, "tools_paintmethod": self.paintmethod_combo,
"tools_pathconnect": self.pathconnect_cb, "tools_pathconnect": self.pathconnect_cb,
"tools_paintcontour": self.paintcontour_cb, "tools_paintcontour": self.paintcontour_cb,
# Isolation
"tools_iso_passes": self.passes_entry,
"tools_iso_overlap": self.iso_overlap_entry,
"tools_iso_milling_type": self.milling_type_radio,
"tools_iso_follow": self.follow_cb,
"tools_iso_isotype": self.iso_type_radio
} }
self.name2option = { self.name2option = {
@@ -1787,6 +1915,13 @@ class ToolsDB2(QtWidgets.QWidget):
'gdb_p_method': "tools_paintmethod", 'gdb_p_method': "tools_paintmethod",
'gdb_p_connect': "tools_pathconnect", 'gdb_p_connect': "tools_pathconnect",
'gdb_p_contour': "tools_paintcontour", 'gdb_p_contour': "tools_paintcontour",
# Isolation
"gdb_i_passes": "tools_iso_passes",
"gdb_i_overlap": "tools_iso_overlap",
"gdb_i_milling_type": "tools_iso_milling_type",
"gdb_i_follow": "tools_iso_follow",
"gdb_i_iso_type": "tools_iso_isotype"
} }
self.current_toolid = None self.current_toolid = None
@@ -1887,7 +2022,7 @@ class ToolsDB2(QtWidgets.QWidget):
self.blockSignals(False) self.blockSignals(False)
def setup_db_ui(self): def setup_db_ui(self):
filename = self.app.data_path + '/geo_tools_db.FlatDB' filename = self.app.data_path + '\geo_tools_db.FlatDB'
# load the database tools from the file # load the database tools from the file
try: try:
@@ -1906,7 +2041,7 @@ class ToolsDB2(QtWidgets.QWidget):
self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file.")) self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
return return
self.app.inform.emit('[success] %s: %s' % (_("Loaded FlatCAM Tools DB from"), filename)) self.app.inform.emit('[success] %s: %s' % (_("Loaded Tools DB from"), filename))
self.build_db_ui() self.build_db_ui()
@@ -1939,21 +2074,23 @@ class ToolsDB2(QtWidgets.QWidget):
if self.db_tool_dict: if self.db_tool_dict:
self.storage_to_form(self.db_tool_dict['1']) self.storage_to_form(self.db_tool_dict['1'])
# Enable GUI # Enable AppGUI
self.basic_box.setEnabled(True) self.basic_box.setEnabled(True)
self.advanced_box.setEnabled(True) self.advanced_box.setEnabled(True)
self.ncc_box.setEnabled(True) self.ncc_box.setEnabled(True)
self.paint_box.setEnabled(True) self.paint_box.setEnabled(True)
self.iso_box.setEnabled(True)
self.tree_widget.setCurrentItem(self.tree_widget.topLevelItem(0)) self.tree_widget.setCurrentItem(self.tree_widget.topLevelItem(0))
# self.tree_widget.setFocus() # self.tree_widget.setFocus()
else: else:
# Disable GUI # Disable AppGUI
self.basic_box.setEnabled(False) self.basic_box.setEnabled(False)
self.advanced_box.setEnabled(False) self.advanced_box.setEnabled(False)
self.ncc_box.setEnabled(False) self.ncc_box.setEnabled(False)
self.paint_box.setEnabled(False) self.paint_box.setEnabled(False)
self.iso_box.setEnabled(False)
else: else:
self.storage_to_form(self.db_tool_dict[str(self.current_toolid)]) self.storage_to_form(self.db_tool_dict[str(self.current_toolid)])
@@ -2006,10 +2143,27 @@ class ToolsDB2(QtWidgets.QWidget):
"tools_paintmethod": self.app.defaults["tools_paintmethod"], "tools_paintmethod": self.app.defaults["tools_paintmethod"],
"tools_pathconnect": self.app.defaults["tools_pathconnect"], "tools_pathconnect": self.app.defaults["tools_pathconnect"],
"tools_paintcontour": self.app.defaults["tools_paintcontour"], "tools_paintcontour": self.app.defaults["tools_paintcontour"],
# Isolation
"tools_iso_passes": int(self.app.defaults["tools_iso_passes"]),
"tools_iso_overlap": float(self.app.defaults["tools_iso_overlap"]),
"tools_iso_milling_type": self.app.defaults["tools_iso_milling_type"],
"tools_iso_follow": self.app.defaults["tools_iso_follow"],
"tools_iso_isotype": self.app.defaults["tools_iso_isotype"],
}) })
temp = []
for k, v in self.db_tool_dict.items():
if "new_tool_" in v['name']:
temp.append(float(v['name'].rpartition('_')[2]))
if temp:
new_name = "new_tool_%d" % int(max(temp) + 1)
else:
new_name = "new_tool_1"
dict_elem = {} dict_elem = {}
dict_elem['name'] = 'new_tool' dict_elem['name'] = new_name
if type(self.app.defaults["geometry_cnctooldia"]) == float: if type(self.app.defaults["geometry_cnctooldia"]) == float:
dict_elem['tooldia'] = self.app.defaults["geometry_cnctooldia"] dict_elem['tooldia'] = self.app.defaults["geometry_cnctooldia"]
else: else:
@@ -2117,7 +2271,7 @@ class ToolsDB2(QtWidgets.QWidget):
l_save=str(self.app.get_last_save_folder()), l_save=str(self.app.get_last_save_folder()),
n=_("Tools_Database"), n=_("Tools_Database"),
date=date), date=date),
filter=filter__) ext_filter=filter__)
filename = str(filename) filename = str(filename)
@@ -2186,7 +2340,7 @@ class ToolsDB2(QtWidgets.QWidget):
self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file.")) self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
return return
self.app.inform.emit('[success] %s: %s' % (_("Loaded FlatCAM Tools DB from"), filename)) self.app.inform.emit('[success] %s: %s' % (_("Loaded Tools DB from"), filename))
self.build_db_ui() self.build_db_ui()
self.update_storage() self.update_storage()
@@ -2218,6 +2372,18 @@ class ToolsDB2(QtWidgets.QWidget):
self.app.tools_db_changed_flag = False self.app.tools_db_changed_flag = False
self.on_save_tools_db() self.on_save_tools_db()
def on_calculate_tooldia(self):
if self.shape_combo.get_value() == 'V':
tip_dia = float(self.vdia_entry.get_value())
half_tip_angle = float(self.vangle_entry.get_value()) / 2.0
cut_z = float(self.cutz_entry.get_value())
cut_z = -cut_z if cut_z < 0 else cut_z
# calculated tool diameter so the cut_z parameter is obeyed
tool_dia = tip_dia + (2 * cut_z * math.tan(math.radians(half_tip_angle)))
self.dia_entry.set_value(tool_dia)
def ui_connect(self): def ui_connect(self):
# make sure that we don't make multiple connections to the widgets # make sure that we don't make multiple connections to the widgets
self.ui_disconnect() self.ui_disconnect()
@@ -2247,12 +2413,40 @@ class ToolsDB2(QtWidgets.QWidget):
if isinstance(wdg, FCSpinner) or isinstance(wdg, FCDoubleSpinner): if isinstance(wdg, FCSpinner) or isinstance(wdg, FCDoubleSpinner):
wdg.valueChanged.connect(self.update_storage) wdg.valueChanged.connect(self.update_storage)
# connect the calculate tooldia method to the controls
# if the tool shape is 'V' the tool dia will be calculated to obey Cut Z parameter
self.shape_combo.currentIndexChanged.connect(self.on_calculate_tooldia)
self.cutz_entry.valueChanged.connect(self.on_calculate_tooldia)
self.vdia_entry.valueChanged.connect(self.on_calculate_tooldia)
self.vangle_entry.valueChanged.connect(self.on_calculate_tooldia)
def ui_disconnect(self): def ui_disconnect(self):
try: try:
self.name_entry.editingFinished.disconnect(self.update_tree_name) self.name_entry.editingFinished.disconnect(self.update_tree_name)
except (TypeError, AttributeError): except (TypeError, AttributeError):
pass pass
try:
self.shape_combo.currentIndexChanged.disconnect(self.on_calculate_tooldia)
except (TypeError, AttributeError):
pass
try:
self.cutz_entry.valueChanged.disconnect(self.on_calculate_tooldia)
except (TypeError, AttributeError):
pass
try:
self.vdia_entry.valueChanged.disconnect(self.on_calculate_tooldia)
except (TypeError, AttributeError):
pass
try:
self.vangle_entry.valueChanged.disconnect(self.on_calculate_tooldia)
except (TypeError, AttributeError):
pass
for key in self.form_fields: for key in self.form_fields:
wdg = self.form_fields[key] wdg = self.form_fields[key]
@@ -2398,6 +2592,18 @@ class ToolsDB2(QtWidgets.QWidget):
elif wdg_name == "gdb_p_contour": elif wdg_name == "gdb_p_contour":
self.db_tool_dict[tool_id]['data']['tools_paintcontour'] = val self.db_tool_dict[tool_id]['data']['tools_paintcontour'] = val
# Isolation Tool
elif wdg_name == "gdb_i_passes":
self.db_tool_dict[tool_id]['data']['tools_iso_passes'] = val
elif wdg_name == "gdb_i_overlap":
self.db_tool_dict[tool_id]['data']['tools_iso_overlap'] = val
elif wdg_name == "gdb_i_milling_type":
self.db_tool_dict[tool_id]['data']['tools_iso_milling_type'] = val
elif wdg_name == "gdb_i_follow":
self.db_tool_dict[tool_id]['data']['tools_iso_follow'] = val
elif wdg_name == "gdb_i_iso_type":
self.db_tool_dict[tool_id]['data']['tools_iso_isotype'] = val
self.callback_app() self.callback_app()
def on_tool_requested_from_app(self): def on_tool_requested_from_app(self):

View File

@@ -9,9 +9,9 @@ from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QSettings from PyQt5.QtCore import Qt, QSettings
from camlib import distance, arc, FlatCAMRTreeStorage from camlib import distance, arc, FlatCAMRTreeStorage
from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, RadioSet, FCSpinner from AppGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, RadioSet, FCSpinner
from flatcamEditors.FlatCAMGeoEditor import FCShapeTool, DrawTool, DrawToolShape, DrawToolUtilityShape, FlatCAMGeoEditor from AppEditors.FlatCAMGeoEditor import FCShapeTool, DrawTool, DrawToolShape, DrawToolUtilityShape, FlatCAMGeoEditor
from flatcamParsers.ParseExcellon import Excellon from AppParsers.ParseExcellon import Excellon
from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon, Point from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon, Point
import shapely.affinity as affinity import shapely.affinity as affinity
@@ -26,7 +26,7 @@ import logging
from copy import deepcopy from copy import deepcopy
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -2123,7 +2123,7 @@ class FlatCAMExcEditor(QtCore.QObject):
else: else:
self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1)
else: else:
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_exc_editor') self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_exc_editor')
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_exc_editor') self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_exc_editor')
@@ -2239,7 +2239,7 @@ class FlatCAMExcEditor(QtCore.QObject):
# store the status of the editor so the Delete at object level will not work until the edit is finished # store the status of the editor so the Delete at object level will not work until the edit is finished
self.editor_active = False self.editor_active = False
log.debug("Initialization of the FlatCAM Excellon Editor is finished ...") log.debug("Initialization of the Excellon Editor is finished ...")
def pool_recreated(self, pool): def pool_recreated(self, pool):
self.shapes.pool = pool self.shapes.pool = pool
@@ -2312,7 +2312,7 @@ class FlatCAMExcEditor(QtCore.QObject):
tool_dia = float('%.*f' % (self.decimals, v['C'])) tool_dia = float('%.*f' % (self.decimals, v['C']))
self.tool2tooldia[int(k)] = tool_dia self.tool2tooldia[int(k)] = tool_dia
# Init GUI # Init AppGUI
self.addtool_entry.set_value(float(self.app.defaults['excellon_editor_newdia'])) self.addtool_entry.set_value(float(self.app.defaults['excellon_editor_newdia']))
self.drill_array_size_entry.set_value(int(self.app.defaults['excellon_editor_array_size'])) self.drill_array_size_entry.set_value(int(self.app.defaults['excellon_editor_array_size']))
self.drill_axis_radio.set_value(self.app.defaults['excellon_editor_lin_dir']) self.drill_axis_radio.set_value(self.app.defaults['excellon_editor_lin_dir'])
@@ -2819,10 +2819,8 @@ class FlatCAMExcEditor(QtCore.QObject):
self.tool_shape.enabled = True self.tool_shape.enabled = True
# self.app.app_cursor.enabled = True # self.app.app_cursor.enabled = True
self.app.ui.snap_max_dist_entry.setEnabled(True)
self.app.ui.corner_snap_btn.setEnabled(True)
self.app.ui.snap_magnet.setVisible(True)
self.app.ui.corner_snap_btn.setVisible(True) self.app.ui.corner_snap_btn.setVisible(True)
self.app.ui.snap_magnet.setVisible(True)
self.app.ui.exc_editor_menu.setDisabled(False) self.app.ui.exc_editor_menu.setDisabled(False)
self.app.ui.exc_editor_menu.menuAction().setVisible(True) self.app.ui.exc_editor_menu.menuAction().setVisible(True)
@@ -2832,12 +2830,11 @@ class FlatCAMExcEditor(QtCore.QObject):
self.app.ui.exc_edit_toolbar.setDisabled(False) self.app.ui.exc_edit_toolbar.setDisabled(False)
self.app.ui.exc_edit_toolbar.setVisible(True) self.app.ui.exc_edit_toolbar.setVisible(True)
# self.app.ui.snap_toolbar.setDisabled(False) # self.app.ui.status_toolbar.setDisabled(False)
# start with GRID toolbar activated # start with GRID toolbar activated
if self.app.ui.grid_snap_btn.isChecked() is False: if self.app.ui.grid_snap_btn.isChecked() is False:
self.app.ui.grid_snap_btn.trigger() self.app.ui.grid_snap_btn.trigger()
self.app.ui.on_grid_snap_triggered(state=True)
self.app.ui.popmenu_disable.setVisible(False) self.app.ui.popmenu_disable.setVisible(False)
self.app.ui.cmenu_newmenu.menuAction().setVisible(False) self.app.ui.cmenu_newmenu.menuAction().setVisible(False)
@@ -2869,30 +2866,8 @@ class FlatCAMExcEditor(QtCore.QObject):
self.clear() self.clear()
self.app.ui.exc_edit_toolbar.setDisabled(True) self.app.ui.exc_edit_toolbar.setDisabled(True)
settings = QSettings("Open Source", "FlatCAM") self.app.ui.corner_snap_btn.setVisible(False)
if settings.contains("layout"): self.app.ui.snap_magnet.setVisible(False)
layout = settings.value('layout', type=str)
if layout == 'standard':
# self.app.ui.exc_edit_toolbar.setVisible(False)
self.app.ui.snap_max_dist_entry.setEnabled(False)
self.app.ui.corner_snap_btn.setEnabled(False)
self.app.ui.snap_magnet.setVisible(False)
self.app.ui.corner_snap_btn.setVisible(False)
else:
# self.app.ui.exc_edit_toolbar.setVisible(True)
self.app.ui.snap_max_dist_entry.setEnabled(False)
self.app.ui.corner_snap_btn.setEnabled(False)
self.app.ui.snap_magnet.setVisible(True)
self.app.ui.corner_snap_btn.setVisible(True)
else:
# self.app.ui.exc_edit_toolbar.setVisible(False)
self.app.ui.snap_max_dist_entry.setEnabled(False)
self.app.ui.corner_snap_btn.setEnabled(False)
self.app.ui.snap_magnet.setVisible(False)
self.app.ui.corner_snap_btn.setVisible(False)
# set the Editor Toolbar visibility to what was before entering in the Editor # set the Editor Toolbar visibility to what was before entering in the Editor
self.app.ui.exc_edit_toolbar.setVisible(False) if self.toolbar_old_state is False \ self.app.ui.exc_edit_toolbar.setVisible(False) if self.toolbar_old_state is False \
@@ -3068,7 +3043,7 @@ class FlatCAMExcEditor(QtCore.QObject):
self.set_ui() self.set_ui()
# now that we hava data, create the GUI interface and add it to the Tool Tab # now that we hava data, create the AppGUI interface and add it to the Tool Tab
self.build_ui(first_run=True) self.build_ui(first_run=True)
# we activate this after the initial build as we don't need to see the tool been populated # we activate this after the initial build as we don't need to see the tool been populated
@@ -3361,15 +3336,17 @@ class FlatCAMExcEditor(QtCore.QObject):
with self.app.proc_container.new(_("Creating Excellon.")): with self.app.proc_container.new(_("Creating Excellon.")):
try: try:
edited_obj = self.app.new_object("excellon", outname, obj_init) 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'], edited_obj.source_file = self.app.export_excellon(obj_name=edited_obj.options['name'],
local_use=edited_obj, local_use=edited_obj,
filename=None, filename=None,
use_thread=False) use_thread=False)
except Exception as e: except Exception as e:
self.deactivate()
log.error("Error on Edited object creation: %s" % str(e)) log.error("Error on Edited object creation: %s" % str(e))
return return
self.deactivate()
self.app.inform.emit('[success] %s' % _("Excellon editing finished.")) self.app.inform.emit('[success] %s' % _("Excellon editing finished."))
def on_tool_select(self, tool): def on_tool_select(self, tool):
@@ -3463,8 +3440,8 @@ class FlatCAMExcEditor(QtCore.QObject):
self.pos = (self.pos[0], self.pos[1]) self.pos = (self.pos[0], self.pos[1])
if event.button == 1: if event.button == 1:
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: " # self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0)) # "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0))
# Selection with left mouse button # Selection with left mouse button
if self.active_tool is not None and event.button == 1: if self.active_tool is not None and event.button == 1:
@@ -3801,18 +3778,22 @@ class FlatCAMExcEditor(QtCore.QObject):
self.snap_x = x self.snap_x = x
self.snap_y = y self.snap_y = y
# update the position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"<b>Y</b>: %.4f" % (x, y))
if self.pos is None: if self.pos is None:
self.pos = (0, 0) self.pos = (0, 0)
self.app.dx = x - self.pos[0] self.app.dx = x - self.pos[0]
self.app.dy = y - self.pos[1] self.app.dy = y - self.pos[1]
# update the reference position label in the infobar since the APP mouse event handlers are disconnected # # update the position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: " self.app.ui.position_label.setText("&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (self.app.dx, self.app.dy)) "<b>Y</b>: %.4f&nbsp;" % (x, y))
# # update the reference position label in the infobar since the APP mouse event handlers are disconnected
# self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
# "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (self.app.dx, self.app.dy))
units = self.app.defaults["units"].lower()
self.app.plotcanvas.text_hud.text = \
'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\n\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format(
self.app.dx, units, self.app.dy, units, x, units, y, units)
# ## Utility geometry (animated) # ## Utility geometry (animated)
self.update_utility_geometry(data=(x, y)) self.update_utility_geometry(data=(x, y))
@@ -4045,7 +4026,7 @@ class FlatCAMExcEditor(QtCore.QObject):
def select_tool(self, toolname): def select_tool(self, toolname):
""" """
Selects a drawing tool. Impacts the object and GUI. Selects a drawing tool. Impacts the object and AppGUI.
:param toolname: Name of the tool. :param toolname: Name of the tool.
:return: None :return: None

View File

@@ -15,11 +15,10 @@ from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QSettings from PyQt5.QtCore import Qt, QSettings
from camlib import distance, arc, three_point_circle, Geometry, FlatCAMRTreeStorage from camlib import distance, arc, three_point_circle, Geometry, FlatCAMRTreeStorage
from FlatCAMTool import FlatCAMTool from AppTool import AppTool
from flatcamGUI.ObjectUI import RadioSet from AppGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \
from flatcamGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \ FCDoubleSpinner, FCButton, FCInputDialog, FCTree
FCTable, FCDoubleSpinner, FCButton, EvalEntry2, FCInputDialog, FCTree from AppParsers.ParseFont import *
from flatcamParsers.ParseFont import *
from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon
from shapely.ops import cascaded_union, unary_union, linemerge from shapely.ops import cascaded_union, unary_union, linemerge
@@ -34,7 +33,7 @@ from rtree import index as rtindex
from copy import deepcopy from copy import deepcopy
# from vispy.io import read_png # from vispy.io import read_png
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -42,7 +41,7 @@ if '_' not in builtins.__dict__:
_ = gettext.gettext _ = gettext.gettext
class BufferSelectionTool(FlatCAMTool): class BufferSelectionTool(AppTool):
""" """
Simple input for buffer distance. Simple input for buffer distance.
""" """
@@ -50,7 +49,7 @@ class BufferSelectionTool(FlatCAMTool):
toolName = "Buffer Selection" toolName = "Buffer Selection"
def __init__(self, app, draw_app): def __init__(self, app, draw_app):
FlatCAMTool.__init__(self, app) AppTool.__init__(self, app)
self.draw_app = draw_app self.draw_app = draw_app
self.decimals = app.decimals self.decimals = app.decimals
@@ -118,12 +117,12 @@ class BufferSelectionTool(FlatCAMTool):
self.buffer_int_button.clicked.connect(self.on_buffer_int) self.buffer_int_button.clicked.connect(self.on_buffer_int)
self.buffer_ext_button.clicked.connect(self.on_buffer_ext) self.buffer_ext_button.clicked.connect(self.on_buffer_ext)
# Init GUI # Init AppGUI
self.buffer_distance_entry.set_value(0.01) self.buffer_distance_entry.set_value(0.01)
def run(self): def run(self):
self.app.defaults.report_usage("Geo Editor ToolBuffer()") self.app.defaults.report_usage("Geo Editor ToolBuffer()")
FlatCAMTool.run(self) AppTool.run(self)
# if the splitter us hidden, display it # if the splitter us hidden, display it
if self.app.ui.splitter.sizes()[0] == 0: if self.app.ui.splitter.sizes()[0] == 0:
@@ -187,7 +186,7 @@ class BufferSelectionTool(FlatCAMTool):
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab) self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
class TextInputTool(FlatCAMTool): class TextInputTool(AppTool):
""" """
Simple input for buffer distance. Simple input for buffer distance.
""" """
@@ -195,7 +194,7 @@ class TextInputTool(FlatCAMTool):
toolName = "Text Input Tool" toolName = "Text Input Tool"
def __init__(self, app): def __init__(self, app):
FlatCAMTool.__init__(self, app) AppTool.__init__(self, app)
self.app = app self.app = app
self.text_path = [] self.text_path = []
@@ -340,7 +339,7 @@ class TextInputTool(FlatCAMTool):
def run(self): def run(self):
self.app.defaults.report_usage("Geo Editor TextInputTool()") self.app.defaults.report_usage("Geo Editor TextInputTool()")
FlatCAMTool.run(self) AppTool.run(self)
# if the splitter us hidden, display it # if the splitter us hidden, display it
if self.app.ui.splitter.sizes()[0] == 0: if self.app.ui.splitter.sizes()[0] == 0:
@@ -405,7 +404,7 @@ class TextInputTool(FlatCAMTool):
self.app.ui.notebook.setTabText(2, _("Tool")) self.app.ui.notebook.setTabText(2, _("Tool"))
class PaintOptionsTool(FlatCAMTool): class PaintOptionsTool(AppTool):
""" """
Inputs to specify how to paint the selected polygons. Inputs to specify how to paint the selected polygons.
""" """
@@ -413,7 +412,7 @@ class PaintOptionsTool(FlatCAMTool):
toolName = "Paint Tool" toolName = "Paint Tool"
def __init__(self, app, fcdraw): def __init__(self, app, fcdraw):
FlatCAMTool.__init__(self, app) AppTool.__init__(self, app)
self.app = app self.app = app
self.fcdraw = fcdraw self.fcdraw = fcdraw
@@ -538,7 +537,7 @@ class PaintOptionsTool(FlatCAMTool):
def run(self): def run(self):
self.app.defaults.report_usage("Geo Editor ToolPaint()") self.app.defaults.report_usage("Geo Editor ToolPaint()")
FlatCAMTool.run(self) AppTool.run(self)
# if the splitter us hidden, display it # if the splitter us hidden, display it
if self.app.ui.splitter.sizes()[0] == 0: if self.app.ui.splitter.sizes()[0] == 0:
@@ -547,7 +546,7 @@ class PaintOptionsTool(FlatCAMTool):
self.app.ui.notebook.setTabText(2, _("Paint Tool")) self.app.ui.notebook.setTabText(2, _("Paint Tool"))
def set_tool_ui(self): def set_tool_ui(self):
# Init GUI # Init AppGUI
if self.app.defaults["tools_painttooldia"]: if self.app.defaults["tools_painttooldia"]:
self.painttooldia_entry.set_value(self.app.defaults["tools_painttooldia"]) self.painttooldia_entry.set_value(self.app.defaults["tools_painttooldia"])
else: else:
@@ -599,7 +598,7 @@ class PaintOptionsTool(FlatCAMTool):
self.app.ui.splitter.setSizes([0, 1]) self.app.ui.splitter.setSizes([0, 1])
class TransformEditorTool(FlatCAMTool): class TransformEditorTool(AppTool):
""" """
Inputs to specify how to paint the selected polygons. Inputs to specify how to paint the selected polygons.
""" """
@@ -612,7 +611,7 @@ class TransformEditorTool(FlatCAMTool):
offsetName = _("Offset") offsetName = _("Offset")
def __init__(self, app, draw_app): def __init__(self, app, draw_app):
FlatCAMTool.__init__(self, app) AppTool.__init__(self, app)
self.app = app self.app = app
self.draw_app = draw_app self.draw_app = draw_app
@@ -981,7 +980,7 @@ class TransformEditorTool(FlatCAMTool):
def run(self): def run(self):
self.app.defaults.report_usage("Geo Editor Transform Tool()") self.app.defaults.report_usage("Geo Editor Transform Tool()")
FlatCAMTool.run(self) AppTool.run(self)
self.set_tool_ui() self.set_tool_ui()
# if the splitter us hidden, display it # if the splitter us hidden, display it
@@ -991,7 +990,7 @@ class TransformEditorTool(FlatCAMTool):
self.app.ui.notebook.setTabText(2, _("Transform Tool")) self.app.ui.notebook.setTabText(2, _("Transform Tool"))
def install(self, icon=None, separator=None, **kwargs): def install(self, icon=None, separator=None, **kwargs):
FlatCAMTool.install(self, icon, separator, shortcut='Alt+T', **kwargs) AppTool.install(self, icon, separator, shortcut='Alt+T', **kwargs)
def set_tool_ui(self): def set_tool_ui(self):
# Initialize form # Initialize form
@@ -3383,7 +3382,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1) self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1)
else: else:
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_geo_editor') self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_geo_editor')
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_geo_editor') self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_geo_editor')
@@ -3467,22 +3466,32 @@ class FlatCAMGeoEditor(QtCore.QObject):
:return: :return:
""" """
try: try:
self.options[opt] = float(entry.text()) text_value = entry.text()
if ',' in text_value:
text_value = text_value.replace(',', '.')
self.options[opt] = float(text_value)
except Exception as e: except Exception as e:
entry.set_value(self.app.defaults[opt])
log.debug("FlatCAMGeoEditor.__init__().entry2option() --> %s" % str(e)) log.debug("FlatCAMGeoEditor.__init__().entry2option() --> %s" % str(e))
return return
def gridx_changed(goption, gentry): def grid_changed(goption, gentry):
""" """
:param goption: String. Can be either 'global_gridx' or 'global_gridy' :param goption: String. Can be either 'global_gridx' or 'global_gridy'
:param gentry: A GUI element which text value is read and used :param gentry: A GUI element which text value is read and used
:return: :return:
""" """
if goption not in ['global_gridx', 'global_gridy']:
return
entry2option(opt=goption, entry=gentry) entry2option(opt=goption, entry=gentry)
# if the grid link is checked copy the value in the GridX field to GridY # if the grid link is checked copy the value in the GridX field to GridY
try: try:
val = float(gentry.get_value()) text_value = gentry.text()
if ',' in text_value:
text_value = text_value.replace(',', '.')
val = float(text_value)
except ValueError: except ValueError:
return return
@@ -3491,7 +3500,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.ui.grid_gap_x_entry.setValidator(QtGui.QDoubleValidator()) self.app.ui.grid_gap_x_entry.setValidator(QtGui.QDoubleValidator())
self.app.ui.grid_gap_x_entry.textChanged.connect( self.app.ui.grid_gap_x_entry.textChanged.connect(
lambda: gridx_changed("global_gridx", self.app.ui.grid_gap_x_entry)) lambda: grid_changed("global_gridx", self.app.ui.grid_gap_x_entry))
self.app.ui.grid_gap_y_entry.setValidator(QtGui.QDoubleValidator()) self.app.ui.grid_gap_y_entry.setValidator(QtGui.QDoubleValidator())
self.app.ui.grid_gap_y_entry.textChanged.connect( self.app.ui.grid_gap_y_entry.textChanged.connect(
@@ -3542,7 +3551,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
# store the status of the editor so the Delete at object level will not work until the edit is finished # store the status of the editor so the Delete at object level will not work until the edit is finished
self.editor_active = False self.editor_active = False
log.debug("Initialization of the FlatCAM Geometry Editor is finished ...") log.debug("Initialization of the Geometry Editor is finished ...")
def pool_recreated(self, pool): def pool_recreated(self, pool):
self.shapes.pool = pool self.shapes.pool = pool
@@ -3559,14 +3568,14 @@ class FlatCAMGeoEditor(QtCore.QObject):
# Remove anything else in the GUI Selected Tab # Remove anything else in the GUI Selected Tab
self.app.ui.selected_scroll_area.takeWidget() self.app.ui.selected_scroll_area.takeWidget()
# Put ourselves in the GUI Selected Tab # Put ourselves in the AppGUI Selected Tab
self.app.ui.selected_scroll_area.setWidget(self.geo_edit_widget) self.app.ui.selected_scroll_area.setWidget(self.geo_edit_widget)
# Switch notebook to Selected page # Switch notebook to Selected page
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab) self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
def build_ui(self): def build_ui(self):
""" """
Build the GUI in the Selected Tab for this editor Build the AppGUI in the Selected Tab for this editor
:return: :return:
""" """
@@ -3644,10 +3653,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.tool_shape.enabled = True self.tool_shape.enabled = True
self.app.app_cursor.enabled = True self.app.app_cursor.enabled = True
self.app.ui.snap_max_dist_entry.setEnabled(True)
self.app.ui.corner_snap_btn.setEnabled(True)
self.app.ui.snap_magnet.setVisible(True)
self.app.ui.corner_snap_btn.setVisible(True) self.app.ui.corner_snap_btn.setVisible(True)
self.app.ui.snap_magnet.setVisible(True)
self.app.ui.geo_editor_menu.setDisabled(False) self.app.ui.geo_editor_menu.setDisabled(False)
self.app.ui.geo_editor_menu.menuAction().setVisible(True) self.app.ui.geo_editor_menu.menuAction().setVisible(True)
@@ -3658,7 +3665,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.ui.geo_edit_toolbar.setDisabled(False) self.app.ui.geo_edit_toolbar.setDisabled(False)
self.app.ui.geo_edit_toolbar.setVisible(True) self.app.ui.geo_edit_toolbar.setVisible(True)
self.app.ui.snap_toolbar.setDisabled(False) self.app.ui.status_toolbar.setDisabled(False)
self.app.ui.popmenu_disable.setVisible(False) self.app.ui.popmenu_disable.setVisible(False)
self.app.ui.cmenu_newmenu.menuAction().setVisible(False) self.app.ui.cmenu_newmenu.menuAction().setVisible(False)
@@ -3675,7 +3682,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.item_selected.connect(self.on_geo_elem_selected) self.item_selected.connect(self.on_geo_elem_selected)
# ## GUI Events # ## AppGUI Events
self.tw.itemSelectionChanged.connect(self.on_tree_selection_change) self.tw.itemSelectionChanged.connect(self.on_tree_selection_change)
# self.tw.keyPressed.connect(self.app.ui.keyPressEvent) # self.tw.keyPressed.connect(self.app.ui.keyPressEvent)
# self.tw.customContextMenuRequested.connect(self.on_menu_request) # self.tw.customContextMenuRequested.connect(self.on_menu_request)
@@ -3703,27 +3710,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.app.ui.geo_edit_toolbar.setDisabled(True) self.app.ui.geo_edit_toolbar.setDisabled(True)
settings = QSettings("Open Source", "FlatCAM") settings = QSettings("Open Source", "FlatCAM")
if settings.contains("layout"): self.app.ui.corner_snap_btn.setVisible(False)
layout = settings.value('layout', type=str) self.app.ui.snap_magnet.setVisible(False)
if layout == 'standard':
# self.app.ui.geo_edit_toolbar.setVisible(False)
self.app.ui.snap_max_dist_entry.setEnabled(False)
self.app.ui.corner_snap_btn.setEnabled(False)
self.app.ui.snap_magnet.setVisible(False)
self.app.ui.corner_snap_btn.setVisible(False)
else:
# self.app.ui.geo_edit_toolbar.setVisible(True)
self.app.ui.snap_max_dist_entry.setEnabled(False)
self.app.ui.corner_snap_btn.setEnabled(False)
else:
# self.app.ui.geo_edit_toolbar.setVisible(False)
self.app.ui.snap_magnet.setVisible(False)
self.app.ui.corner_snap_btn.setVisible(False)
self.app.ui.snap_max_dist_entry.setEnabled(False)
self.app.ui.corner_snap_btn.setEnabled(False)
# set the Editor Toolbar visibility to what was before entering in the Editor # set the Editor Toolbar visibility to what was before entering in the Editor
self.app.ui.geo_edit_toolbar.setVisible(False) if self.toolbar_old_state is False \ self.app.ui.geo_edit_toolbar.setVisible(False) if self.toolbar_old_state is False \
@@ -3757,7 +3745,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
pass pass
try: try:
# ## GUI Events # ## AppGUI Events
self.tw.itemSelectionChanged.disconnect(self.on_tree_selection_change) self.tw.itemSelectionChanged.disconnect(self.on_tree_selection_change)
# self.tw.keyPressed.connect(self.app.ui.keyPressEvent) # self.tw.keyPressed.connect(self.app.ui.keyPressEvent)
# self.tw.customContextMenuRequested.connect(self.on_menu_request) # self.tw.customContextMenuRequested.connect(self.on_menu_request)
@@ -4100,7 +4088,6 @@ class FlatCAMGeoEditor(QtCore.QObject):
# start with GRID toolbar activated # start with GRID toolbar activated
if self.app.ui.grid_snap_btn.isChecked() is False: if self.app.ui.grid_snap_btn.isChecked() is False:
self.app.ui.grid_snap_btn.trigger() self.app.ui.grid_snap_btn.trigger()
self.app.ui.on_grid_snap_triggered(state=True)
def on_buffer_tool(self): def on_buffer_tool(self):
buff_tool = BufferSelectionTool(self.app, self) buff_tool = BufferSelectionTool(self.app, self)
@@ -4148,9 +4135,11 @@ class FlatCAMGeoEditor(QtCore.QObject):
# make sure that the cursor shape is enabled/disabled, too # make sure that the cursor shape is enabled/disabled, too
if self.options['grid_snap'] is True: if self.options['grid_snap'] is True:
self.app.inform[str, bool].emit(_("Grid Snap enabled."), False)
self.app.app_cursor.enabled = True self.app.app_cursor.enabled = True
else: else:
self.app.app_cursor.enabled = False self.app.app_cursor.enabled = False
self.app.inform[str, bool].emit(_("Grid Snap disabled."), False)
def on_canvas_click(self, event): def on_canvas_click(self, event):
""" """
@@ -4173,8 +4162,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.pos = (self.pos[0], self.pos[1]) self.pos = (self.pos[0], self.pos[1])
if event.button == 1: if event.button == 1:
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: " # self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0)) # "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0))
modifiers = QtWidgets.QApplication.keyboardModifiers() modifiers = QtWidgets.QApplication.keyboardModifiers()
# If the SHIFT key is pressed when LMB is clicked then the coordinates are copied to clipboard # If the SHIFT key is pressed when LMB is clicked then the coordinates are copied to clipboard
@@ -4261,18 +4250,23 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.snap_y = y self.snap_y = y
self.app.mouse = [x, y] self.app.mouse = [x, y]
# update the position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"<b>Y</b>: %.4f" % (x, y))
if self.pos is None: if self.pos is None:
self.pos = (0, 0) self.pos = (0, 0)
self.app.dx = x - self.pos[0] self.app.dx = x - self.pos[0]
self.app.dy = y - self.pos[1] self.app.dy = y - self.pos[1]
# update the reference position label in the infobar since the APP mouse event handlers are disconnected # # update the position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: " self.app.ui.position_label.setText("&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (self.app.dx, self.app.dy)) "<b>Y</b>: %.4f&nbsp;" % (x, y))
#
# # update the reference position label in the infobar since the APP mouse event handlers are disconnected
# self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
# "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (self.app.dx, self.app.dy))
units = self.app.defaults["units"].lower()
self.app.plotcanvas.text_hud.text = \
'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\n\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format(
self.app.dx, units, self.app.dy, units, x, units, y, units)
if event.button == 1 and event_is_dragging and isinstance(self.active_tool, FCEraser): if event.button == 1 and event_is_dragging and isinstance(self.active_tool, FCEraser):
pass pass
@@ -4665,7 +4659,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
def select_tool(self, toolname): def select_tool(self, toolname):
""" """
Selects a drawing tool. Impacts the object and GUI. Selects a drawing tool. Impacts the object and AppGUI.
:param toolname: Name of the tool. :param toolname: Name of the tool.
:return: None :return: None
@@ -4750,8 +4744,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
Transfers the geometry tool shape buffer to the selected geometry Transfers the geometry tool shape buffer to the selected geometry
object. The geometry already in the object are removed. object. The geometry already in the object are removed.
:param fcgeometry: GeometryObject :param fcgeometry: GeometryObject
:return: None :return: None
""" """
if self.multigeo_tool: if self.multigeo_tool:
fcgeometry.tools[self.multigeo_tool]['solid_geometry'] = [] fcgeometry.tools[self.multigeo_tool]['solid_geometry'] = []
@@ -4776,6 +4770,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
new_geo = linemerge(new_geo) new_geo = linemerge(new_geo)
fcgeometry.solid_geometry.append(new_geo) fcgeometry.solid_geometry.append(new_geo)
self.deactivate()
def update_options(self, obj): def update_options(self, obj):
if self.paint_tooldia: if self.paint_tooldia:
obj.options['cnctooldia'] = deepcopy(str(self.paint_tooldia)) obj.options['cnctooldia'] = deepcopy(str(self.paint_tooldia))

View File

@@ -14,15 +14,13 @@ import shapely.affinity as affinity
from vispy.geometry import Rect from vispy.geometry import Rect
import threading
import time
from copy import copy, deepcopy from copy import copy, deepcopy
import logging import logging
from camlib import distance, arc, three_point_circle from camlib import distance, arc, three_point_circle
from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, FCSpinner, RadioSet, \ from AppGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, FCSpinner, RadioSet, \
EvalEntry2, FCInputDialog, FCButton, OptionalInputSection, FCCheckBox EvalEntry2, FCInputDialog, FCButton, OptionalInputSection, FCCheckBox
from FlatCAMTool import FlatCAMTool from AppTool import AppTool
import numpy as np import numpy as np
from numpy.linalg import norm as numpy_norm from numpy.linalg import norm as numpy_norm
@@ -32,7 +30,7 @@ import math
# import pngcanvas # import pngcanvas
import traceback import traceback
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -1086,15 +1084,6 @@ class FCRegion(FCShapeTool):
self.draw_app.app.inform.emit('[success] %s' % _("Done.")) self.draw_app.app.inform.emit('[success] %s' % _("Done."))
def clean_up(self):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
def on_key(self, key): def on_key(self, key):
# Jump to coords # Jump to coords
if key == QtCore.Qt.Key_J or key == 'J': if key == QtCore.Qt.Key_J or key == 'J':
@@ -1160,16 +1149,36 @@ class FCRegion(FCShapeTool):
return msg return msg
def clean_up(self):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCTrack(FCRegion):
class FCTrack(FCShapeTool):
""" """
Resulting type: Polygon Resulting type: Polygon
""" """
def __init__(self, draw_app): def __init__(self, draw_app):
FCRegion.__init__(self, draw_app) DrawTool.__init__(self, draw_app)
self.name = 'track' self.name = 'track'
self.draw_app = draw_app self.draw_app = draw_app
self.steps_per_circle = self.draw_app.app.defaults["gerber_circle_steps"]
size_ap = float(self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['size'])
self.buf_val = (size_ap / 2) if size_ap > 0 else 0.0000001
self.gridx_size = float(self.draw_app.app.ui.grid_gap_x_entry.get_value())
self.gridy_size = float(self.draw_app.app.ui.grid_gap_y_entry.get_value())
self.temp_points = []
self. final_click = False
try: try:
QtGui.QGuiApplication.restoreOverrideCursor() QtGui.QGuiApplication.restoreOverrideCursor()
except Exception as e: except Exception as e:
@@ -1183,52 +1192,23 @@ class FCTrack(FCRegion):
self.draw_app.app.inform.emit(_('Track Mode 1: 45 degrees ...')) self.draw_app.app.inform.emit(_('Track Mode 1: 45 degrees ...'))
def make(self):
new_geo_el = {}
if len(self.temp_points) == 1:
new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val,
resolution=int(self.steps_per_circle / 4))
new_geo_el['follow'] = Point(self.temp_points)
else:
new_geo_el['solid'] = (LineString(self.temp_points).buffer(
self.buf_val, resolution=int(self.steps_per_circle / 4))).buffer(0)
new_geo_el['follow'] = LineString(self.temp_points)
self.geometry = DrawToolShape(new_geo_el)
self.draw_app.in_action = False
self.complete = True
self.draw_app.app.jump_signal.disconnect()
self.draw_app.app.inform.emit('[success] %s' % _("Done."))
def clean_up(self):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
def click(self, point): def click(self, point):
self.draw_app.in_action = True self.draw_app.in_action = True
try:
if point != self.points[-1]: if not self.points:
self.points.append(point)
except IndexError:
self.points.append(point) self.points.append(point)
elif point != self.points[-1]:
self.points.append(point)
else:
return
new_geo_el = {} new_geo_el = {}
if len(self.temp_points) == 1: if len(self.temp_points) == 1:
new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle))
resolution=int(self.steps_per_circle / 4))
new_geo_el['follow'] = Point(self.temp_points) new_geo_el['follow'] = Point(self.temp_points)
else: else:
new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle))
resolution=int(self.steps_per_circle / 4))
new_geo_el['follow'] = LineString(self.temp_points) new_geo_el['follow'] = LineString(self.temp_points)
self.draw_app.add_gerber_shape(DrawToolShape(new_geo_el), self.draw_app.add_gerber_shape(DrawToolShape(new_geo_el),
@@ -1241,23 +1221,25 @@ class FCTrack(FCRegion):
return "" return ""
def update_grid_info(self):
self.gridx_size = float(self.draw_app.app.ui.grid_gap_x_entry.get_value())
self.gridy_size = float(self.draw_app.app.ui.grid_gap_y_entry.get_value())
def utility_geometry(self, data=None): def utility_geometry(self, data=None):
self.update_grid_info() self.update_grid_info()
new_geo_el = {} new_geo_el = {}
if len(self.points) == 0: if not self.points:
new_geo_el['solid'] = Point(data).buffer(self.buf_val, new_geo_el['solid'] = Point(data).buffer(self.buf_val, int(self.steps_per_circle))
resolution=int(self.steps_per_circle / 4))
return DrawToolUtilityShape(new_geo_el) return DrawToolUtilityShape(new_geo_el)
elif len(self.points) > 0: else:
self.temp_points = [self.points[-1]]
old_x = self.points[-1][0] old_x = self.points[-1][0]
old_y = self.points[-1][1] old_y = self.points[-1][1]
x = data[0] x = data[0]
y = data[1] y = data[1]
self.temp_points = [self.points[-1]]
mx = abs(round((x - old_x) / self.gridx_size)) mx = abs(round((x - old_x) / self.gridx_size))
my = abs(round((y - old_y) / self.gridy_size)) my = abs(round((y - old_y) / self.gridy_size))
@@ -1305,14 +1287,30 @@ class FCTrack(FCRegion):
self.temp_points.append(data) self.temp_points.append(data)
if len(self.temp_points) == 1: if len(self.temp_points) == 1:
new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle))
resolution=int(self.steps_per_circle / 4))
return DrawToolUtilityShape(new_geo_el) return DrawToolUtilityShape(new_geo_el)
new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle))
resolution=int(self.steps_per_circle / 4))
return DrawToolUtilityShape(new_geo_el) return DrawToolUtilityShape(new_geo_el)
def make(self):
new_geo_el = {}
if len(self.temp_points) == 1:
new_geo_el['solid'] = Point(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle))
new_geo_el['follow'] = Point(self.temp_points)
else:
new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle))
new_geo_el['solid'] = new_geo_el['solid'].buffer(0) # try to clean the geometry
new_geo_el['follow'] = LineString(self.temp_points)
self.geometry = DrawToolShape(new_geo_el)
self.draw_app.in_action = False
self.complete = True
self.draw_app.app.jump_signal.disconnect()
self.draw_app.app.inform.emit('[success] %s' % _("Done."))
def on_key(self, key): def on_key(self, key):
if key == 'Backspace' or key == QtCore.Qt.Key_Backspace: if key == 'Backspace' or key == QtCore.Qt.Key_Backspace:
if len(self.points) > 0: if len(self.points) > 0:
@@ -1405,6 +1403,15 @@ class FCTrack(FCRegion):
return msg return msg
def clean_up(self):
self.draw_app.selected = []
self.draw_app.apertures_table.clearSelection()
self.draw_app.plot_all()
try:
self.draw_app.app.jump_signal.disconnect()
except (TypeError, AttributeError):
pass
class FCDisc(FCShapeTool): class FCDisc(FCShapeTool):
""" """
@@ -2955,7 +2962,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
# this var will store the state of the toolbar before starting the editor # this var will store the state of the toolbar before starting the editor
self.toolbar_old_state = False self.toolbar_old_state = False
# Init GUI # Init AppGUI
self.apdim_lbl.hide() self.apdim_lbl.hide()
self.apdim_entry.hide() self.apdim_entry.hide()
self.gerber_obj = None self.gerber_obj = None
@@ -2967,7 +2974,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.tool_shape = self.canvas.new_shape_collection(layers=1) self.tool_shape = self.canvas.new_shape_collection(layers=1)
self.ma_annotation = self.canvas.new_text_group() self.ma_annotation = self.canvas.new_text_group()
else: else:
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_grb_editor') self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_grb_editor')
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_grb_editor') self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_grb_editor')
self.ma_annotation = ShapeCollectionLegacy( self.ma_annotation = ShapeCollectionLegacy(
@@ -3110,7 +3117,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.complete = True self.complete = True
self.set_ui() self.set_ui()
log.debug("Initialization of the FlatCAM Gerber Editor is finished ...") log.debug("Initialization of the Gerber Editor is finished ...")
def pool_recreated(self, pool): def pool_recreated(self, pool):
self.shapes.pool = pool self.shapes.pool = pool
@@ -3139,7 +3146,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
tt_aperture = self.sorted_apcode[i] tt_aperture = self.sorted_apcode[i]
self.tid2apcode[i + 1] = tt_aperture self.tid2apcode[i + 1] = tt_aperture
# Init GUI # Init AppGUI
self.buffer_distance_entry.set_value(self.app.defaults["gerber_editor_buff_f"]) self.buffer_distance_entry.set_value(self.app.defaults["gerber_editor_buff_f"])
self.scale_factor_entry.set_value(self.app.defaults["gerber_editor_scale_f"]) self.scale_factor_entry.set_value(self.app.defaults["gerber_editor_scale_f"])
@@ -3428,7 +3435,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
else: else:
# deleted_tool_dia = float(self.apertures_table.item(self.apertures_table.currentRow(), 1).text()) # deleted_tool_dia = float(self.apertures_table.item(self.apertures_table.currentRow(), 1).text())
if len(self.apertures_table.selectionModel().selectedRows()) == 0: if len(self.apertures_table.selectionModel().selectedRows()) == 0:
self.app.inform.emit('[WARNING_NOTCL]%s' % _(" Select an aperture in Aperture Table")) self.app.inform.emit('[WARNING_NOTCL] %s' % _(" Select an aperture in Aperture Table"))
return return
deleted_apcode_list = [] deleted_apcode_list = []
@@ -3685,10 +3692,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.shapes.enabled = True self.shapes.enabled = True
self.tool_shape.enabled = True self.tool_shape.enabled = True
self.app.ui.snap_max_dist_entry.setEnabled(True)
self.app.ui.corner_snap_btn.setEnabled(True)
self.app.ui.snap_magnet.setVisible(True)
self.app.ui.corner_snap_btn.setVisible(True) self.app.ui.corner_snap_btn.setVisible(True)
self.app.ui.snap_magnet.setVisible(True)
self.app.ui.grb_editor_menu.setDisabled(False) self.app.ui.grb_editor_menu.setDisabled(False)
self.app.ui.grb_editor_menu.menuAction().setVisible(True) self.app.ui.grb_editor_menu.menuAction().setVisible(True)
@@ -3698,12 +3703,11 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.ui.grb_edit_toolbar.setDisabled(False) self.app.ui.grb_edit_toolbar.setDisabled(False)
self.app.ui.grb_edit_toolbar.setVisible(True) self.app.ui.grb_edit_toolbar.setVisible(True)
# self.app.ui.snap_toolbar.setDisabled(False) # self.app.ui.status_toolbar.setDisabled(False)
# start with GRID toolbar activated # start with GRID toolbar activated
if self.app.ui.grid_snap_btn.isChecked() is False: if self.app.ui.grid_snap_btn.isChecked() is False:
self.app.ui.grid_snap_btn.trigger() self.app.ui.grid_snap_btn.trigger()
self.app.ui.on_grid_snap_triggered(state=True)
# adjust the visibility of some of the canvas context menu # adjust the visibility of some of the canvas context menu
self.app.ui.popmenu_edit.setVisible(False) self.app.ui.popmenu_edit.setVisible(False)
@@ -3736,29 +3740,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.ui.grb_edit_toolbar.setDisabled(True) self.app.ui.grb_edit_toolbar.setDisabled(True)
settings = QSettings("Open Source", "FlatCAM") settings = QSettings("Open Source", "FlatCAM")
if settings.contains("layout"): self.app.ui.corner_snap_btn.setVisible(False)
layout = settings.value('layout', type=str) self.app.ui.snap_magnet.setVisible(False)
if layout == 'standard':
# self.app.ui.exc_edit_toolbar.setVisible(False)
self.app.ui.snap_max_dist_entry.setEnabled(False)
self.app.ui.corner_snap_btn.setEnabled(False)
self.app.ui.snap_magnet.setVisible(False)
self.app.ui.corner_snap_btn.setVisible(False)
else:
# self.app.ui.exc_edit_toolbar.setVisible(True)
self.app.ui.snap_max_dist_entry.setEnabled(False)
self.app.ui.corner_snap_btn.setEnabled(False)
self.app.ui.snap_magnet.setVisible(True)
self.app.ui.corner_snap_btn.setVisible(True)
else:
# self.app.ui.exc_edit_toolbar.setVisible(False)
self.app.ui.snap_max_dist_entry.setEnabled(False)
self.app.ui.corner_snap_btn.setEnabled(False)
self.app.ui.snap_magnet.setVisible(False)
self.app.ui.corner_snap_btn.setVisible(False)
# set the Editor Toolbar visibility to what was before entering in the Editor # set the Editor Toolbar visibility to what was before entering in the Editor
self.app.ui.grb_edit_toolbar.setVisible(False) if self.toolbar_old_state is False \ self.app.ui.grb_edit_toolbar.setVisible(False) if self.toolbar_old_state is False \
@@ -4210,7 +4193,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
def on_multiprocessing_finished(self): def on_multiprocessing_finished(self):
self.app.proc_container.update_view_text(' %s' % _("Setting up the UI")) self.app.proc_container.update_view_text(' %s' % _("Setting up the UI"))
self.app.inform.emit('[success] %s.' % _("Adding geometry finished. Preparing the GUI")) self.app.inform.emit('[success] %s.' % _("Adding geometry finished. Preparing the AppGUI"))
self.set_ui() self.set_ui()
self.build_ui(first_run=True) self.build_ui(first_run=True)
self.plot_all() self.plot_all()
@@ -4245,6 +4228,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
new_grb_name = self.edited_obj_name + "_edit" new_grb_name = self.edited_obj_name + "_edit"
self.app.worker_task.emit({'fcn': self.new_edited_gerber, 'params': [new_grb_name, self.storage_dict]}) self.app.worker_task.emit({'fcn': self.new_edited_gerber, 'params': [new_grb_name, self.storage_dict]})
# self.new_edited_gerber(new_grb_name, self.storage_dict)
@staticmethod @staticmethod
def update_options(obj): def update_options(obj):
@@ -4266,9 +4250,10 @@ class FlatCAMGrbEditor(QtCore.QObject):
""" """
Creates a new Gerber object for the edited Gerber. Thread-safe. Creates a new Gerber object for the edited Gerber. Thread-safe.
:param outname: Name of the resulting object. None causes the name to be that of the file. :param outname: Name of the resulting object. None causes the name to be that of the file.
:type outname: str :type outname: str
:param aperture_storage: a dictionary that holds all the objects geometry :param aperture_storage: a dictionary that holds all the objects geometry
:type aperture_storage: dict
:return: None :return: None
""" """
@@ -4360,26 +4345,27 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.inform.emit('[ERROR_NOTCL] %s' % self.app.inform.emit('[ERROR_NOTCL] %s' %
_("There are no Aperture definitions in the file. Aborting Gerber creation.")) _("There are no Aperture definitions in the file. Aborting Gerber creation."))
except Exception: except Exception:
msg = '[ERROR] %s' % \ msg = '[ERROR] %s' % _("An internal error has occurred. See shell.\n")
_("An internal error has occurred. See shell.\n")
msg += traceback.format_exc() msg += traceback.format_exc()
app_obj.inform.emit(msg) app_obj.inform.emit(msg)
raise raise
grb_obj.source_file = self.app.export_gerber(obj_name=out_name, filename=None, grb_obj.source_file = self.app.export_gerber(obj_name=out_name, filename=None,
local_use=grb_obj, use_thread=False) local_use=grb_obj, use_thread=False)
with self.app.proc_container.new(_("Creating Gerber.")): with self.app.proc_container.new(_("Creating Gerber.")):
try: try:
self.app.new_object("gerber", outname, obj_init) self.app.app_obj.new_object("gerber", outname, obj_init)
except Exception as e: except Exception as e:
log.error("Error on Edited object creation: %s" % str(e)) log.error("Error on Edited object creation: %s" % str(e))
# make sure to clean the previous results # make sure to clean the previous results
self.results = [] self.results = []
return return
self.app.inform.emit('[success] %s' % _("Done. Gerber editing finished."))
# make sure to clean the previous results # make sure to clean the previous results
self.results = [] self.results = []
self.deactivate_grb_editor()
self.app.inform.emit('[success] %s' % _("Done. Gerber editing finished."))
def on_tool_select(self, tool): def on_tool_select(self, tool):
""" """
@@ -4537,8 +4523,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.pos = (self.pos[0], self.pos[1]) self.pos = (self.pos[0], self.pos[1])
if event.button == 1: if event.button == 1:
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: " # self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0)) # "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (0, 0))
# Selection with left mouse button # Selection with left mouse button
if self.active_tool is not None: if self.active_tool is not None:
@@ -4550,8 +4536,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.defaults["global_point_clipboard_format"] % self.app.defaults["global_point_clipboard_format"] %
(self.decimals, self.pos[0], self.decimals, self.pos[1]) (self.decimals, self.pos[0], self.decimals, self.pos[1])
) )
self.app.inform.emit('[success] %s' % self.app.inform.emit('[success] %s' % _("Coordinates copied to clipboard."))
_("Coordinates copied to clipboard."))
return return
# Dispatch event to active_tool # Dispatch event to active_tool
@@ -4562,6 +4547,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
if self.current_storage is not None: if self.current_storage is not None:
self.on_grb_shape_complete(self.current_storage) self.on_grb_shape_complete(self.current_storage)
self.build_ui() self.build_ui()
# MS: always return to the Select Tool if modifier key is not pressed # MS: always return to the Select Tool if modifier key is not pressed
# else return to the current tool # else return to the current tool
key_modifier = QtWidgets.QApplication.keyboardModifiers() key_modifier = QtWidgets.QApplication.keyboardModifiers()
@@ -4569,6 +4555,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
modifier_to_use = Qt.ControlModifier modifier_to_use = Qt.ControlModifier
else: else:
modifier_to_use = Qt.ShiftModifier modifier_to_use = Qt.ShiftModifier
# if modifier key is pressed then we add to the selected list the current shape but if it's already # if modifier key is pressed then we add to the selected list the current shape but if it's already
# in the selected list, we removed it. Therefore first click selects, second deselects. # in the selected list, we removed it. Therefore first click selects, second deselects.
if key_modifier == modifier_to_use: if key_modifier == modifier_to_use:
@@ -4629,12 +4616,14 @@ class FlatCAMGrbEditor(QtCore.QObject):
# if right click on canvas and the active tool need to be finished (like Path or Polygon) # if right click on canvas and the active tool need to be finished (like Path or Polygon)
# right mouse click will finish the action # right mouse click will finish the action
if isinstance(self.active_tool, FCShapeTool): if isinstance(self.active_tool, FCShapeTool):
self.active_tool.click(self.app.geo_editor.snap(self.x, self.y)) if isinstance(self.active_tool, FCTrack):
self.active_tool.make() self.active_tool.make()
else:
self.active_tool.click(self.app.geo_editor.snap(self.x, self.y))
self.active_tool.make()
if self.active_tool.complete: if self.active_tool.complete:
self.on_grb_shape_complete() self.on_grb_shape_complete()
self.app.inform.emit('[success] %s' % self.app.inform.emit('[success] %s' % _("Done."))
_("Done."))
# MS: always return to the Select Tool if modifier key is not pressed # MS: always return to the Select Tool if modifier key is not pressed
# else return to the current tool but not for FCTrack # else return to the current tool but not for FCTrack
@@ -4774,18 +4763,23 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.mouse = [x, y] self.app.mouse = [x, y]
# update the position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"<b>Y</b>: %.4f" % (x, y))
if self.pos is None: if self.pos is None:
self.pos = (0, 0) self.pos = (0, 0)
self.app.dx = x - self.pos[0] self.app.dx = x - self.pos[0]
self.app.dy = y - self.pos[1] self.app.dy = y - self.pos[1]
# update the reference position label in the infobar since the APP mouse event handlers are disconnected # # update the position label in the infobar since the APP mouse event handlers are disconnected
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: " self.app.ui.position_label.setText("&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "
"%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (self.app.dx, self.app.dy)) "<b>Y</b>: %.4f&nbsp;" % (x, y))
#
# # update the reference position label in the infobar since the APP mouse event handlers are disconnected
# self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f&nbsp;&nbsp; <b>Dy</b>: "
# "%.4f&nbsp;&nbsp;&nbsp;&nbsp;" % (self.app.dx, self.app.dy))
units = self.app.defaults["units"].lower()
self.app.plotcanvas.text_hud.text = \
'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\n\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format(
self.app.dx, units, self.app.dy, units, x, units, y, units)
self.update_utility_geometry(data=(x, y)) self.update_utility_geometry(data=(x, y))
@@ -5032,7 +5026,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
def select_tool(self, toolname): def select_tool(self, toolname):
""" """
Selects a drawing tool. Impacts the object and GUI. Selects a drawing tool. Impacts the object and AppGUI.
:param toolname: Name of the tool. :param toolname: Name of the tool.
:return: None :return: None
@@ -5298,7 +5292,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab) self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
class TransformEditorTool(FlatCAMTool): class TransformEditorTool(AppTool):
""" """
Inputs to specify how to paint the selected polygons. Inputs to specify how to paint the selected polygons.
""" """
@@ -5311,7 +5305,7 @@ class TransformEditorTool(FlatCAMTool):
offsetName = _("Offset") offsetName = _("Offset")
def __init__(self, app, draw_app): def __init__(self, app, draw_app):
FlatCAMTool.__init__(self, app) AppTool.__init__(self, app)
self.app = app self.app = app
self.draw_app = draw_app self.draw_app = draw_app
@@ -5697,13 +5691,13 @@ class TransformEditorTool(FlatCAMTool):
except AttributeError: except AttributeError:
pass pass
FlatCAMTool.run(self) AppTool.run(self)
self.set_tool_ui() self.set_tool_ui()
self.app.ui.notebook.setTabText(2, _("Transform Tool")) self.app.ui.notebook.setTabText(2, _("Transform Tool"))
def install(self, icon=None, separator=None, **kwargs): def install(self, icon=None, separator=None, **kwargs):
FlatCAMTool.install(self, icon, separator, shortcut='Alt+T', **kwargs) AppTool.install(self, icon, separator, shortcut='Alt+T', **kwargs)
def set_tool_ui(self): def set_tool_ui(self):
# Initialize form # Initialize form

View File

@@ -5,7 +5,7 @@
# MIT Licence # # MIT Licence #
# ########################################################## # ##########################################################
from flatcamGUI.GUIElements import FCFileSaveDialog, FCEntry, FCTextAreaExtended, FCTextAreaLineNumber from AppGUI.GUIElements import FCFileSaveDialog, FCEntry, FCTextAreaExtended, FCTextAreaLineNumber
from PyQt5 import QtPrintSupport, QtWidgets, QtCore, QtGui from PyQt5 import QtPrintSupport, QtWidgets, QtCore, QtGui
from reportlab.platypus import SimpleDocTemplate, Paragraph from reportlab.platypus import SimpleDocTemplate, Paragraph
@@ -15,7 +15,7 @@ from reportlab.lib.units import inch, mm
# from io import StringIO # from io import StringIO
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -214,10 +214,10 @@ class TextEditor(QtWidgets.QWidget):
filename = str(FCFileSaveDialog.get_saved_filename( filename = str(FCFileSaveDialog.get_saved_filename(
caption=_("Export Code ..."), caption=_("Export Code ..."),
directory=self.app.defaults["global_last_folder"] + '/' + str(obj_name), directory=self.app.defaults["global_last_folder"] + '/' + str(obj_name),
filter=_filter_ ext_filter=_filter_
)[0]) )[0])
except TypeError: except TypeError:
filename = str(FCFileSaveDialog.get_saved_filename(caption=_("Export Code ..."), filter=_filter_)[0]) filename = str(FCFileSaveDialog.get_saved_filename(caption=_("Export Code ..."), ext_filter=_filter_)[0])
if filename == "": if filename == "":
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled.")) self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))

View File

@@ -0,0 +1,181 @@
# ##########################################################
# FlatCAM: 2D Post-processing for Manufacturing #
# File by: David Robertson (c) #
# Date: 5/2020 #
# License: MIT Licence #
# ##########################################################
import sys
from PyQt5.QtCore import QPoint, QRect, QSize, Qt
from PyQt5.QtWidgets import QLayout, QSizePolicy
import math
class ColumnarFlowLayout(QLayout):
def __init__(self, parent=None, margin=0, spacing=-1):
super().__init__(parent)
if parent is not None:
self.setContentsMargins(margin, margin, margin, margin)
self.setSpacing(spacing)
self.itemList = []
def __del__(self):
del_item = self.takeAt(0)
while del_item:
del_item = self.takeAt(0)
def addItem(self, item):
self.itemList.append(item)
def count(self):
return len(self.itemList)
def itemAt(self, index):
if 0 <= index < len(self.itemList):
return self.itemList[index]
return None
def takeAt(self, index):
if 0 <= index < len(self.itemList):
return self.itemList.pop(index)
return None
def expandingDirections(self):
return Qt.Orientations(Qt.Orientation(0))
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
height = self.doLayout(QRect(0, 0, width, 0), True)
return height
def setGeometry(self, rect):
super().setGeometry(rect)
self.doLayout(rect, False)
def sizeHint(self):
return self.minimumSize()
def minimumSize(self):
size = QSize()
for item in self.itemList:
size = size.expandedTo(item.minimumSize())
margin, _, _, _ = self.getContentsMargins()
size += QSize(2 * margin, 2 * margin)
return size
def doLayout(self, rect: QRect, testOnly: bool) -> int:
spacing = self.spacing()
x = rect.x()
y = rect.y()
# Determine width of widest item
widest = 0
for item in self.itemList:
widest = max(widest, item.sizeHint().width())
# Determine how many equal-width columns we can get, and how wide each one should be
column_count = math.floor(rect.width() / (widest + spacing))
column_count = min(column_count, len(self.itemList))
column_count = max(1, column_count)
column_width = math.floor((rect.width() - (column_count-1)*spacing - 1) / column_count)
# Get the heights for all of our items
item_heights = {}
for item in self.itemList:
height = item.heightForWidth(column_width) if item.hasHeightForWidth() else item.sizeHint().height()
item_heights[item] = height
# Prepare our column representation
column_contents = []
column_heights = []
for column_index in range(column_count):
column_contents.append([])
column_heights.append(0)
def add_to_column(column: int, item):
column_contents[column].append(item)
column_heights[column] += (item_heights[item] + spacing)
def shove_one(from_column: int) -> bool:
if len(column_contents[from_column]) >= 1:
item = column_contents[from_column].pop(0)
column_heights[from_column] -= (item_heights[item] + spacing)
add_to_column(from_column-1, item)
return True
return False
def shove_cascade_consider(from_column: int) -> bool:
changed_item = False
if len(column_contents[from_column]) > 1:
item = column_contents[from_column][0]
item_height = item_heights[item]
if column_heights[from_column-1] + item_height < max(column_heights):
changed_item = shove_one(from_column) or changed_item
if from_column+1 < column_count:
changed_item = shove_cascade_consider(from_column+1) or changed_item
return changed_item
def shove_cascade() -> bool:
if column_count < 2:
return False
changed_item = True
while changed_item:
changed_item = shove_cascade_consider(1)
return changed_item
def pick_best_shoving_position() -> int:
best_pos = 1
best_height = sys.maxsize
for column_idx in range(1, column_count):
if len(column_contents[column_idx]) == 0:
continue
item = column_contents[column_idx][0]
height_after_shove = column_heights[column_idx-1] + item_heights[item]
if height_after_shove < best_height:
best_height = height_after_shove
best_pos = column_idx
return best_pos
# Calculate the best layout
column_index = 0
for item in self.itemList:
item_height = item_heights[item]
if column_heights[column_index] != 0 and (column_heights[column_index] + item_height) > max(column_heights):
column_index += 1
if column_index >= column_count:
# Run out of room, need to shove more stuff in each column
if column_count >= 2:
changed = shove_cascade()
if not changed:
shoving_pos = pick_best_shoving_position()
shove_one(shoving_pos)
shove_cascade()
column_index = column_count-1
add_to_column(column_index, item)
shove_cascade()
# Set geometry according to the layout we have calculated
if not testOnly:
for column_index, items in enumerate(column_contents):
x = column_index * (column_width + spacing)
y = 0
for item in items:
height = item_heights[item]
item.setGeometry(QRect(x, y, column_width, height))
y += (height + spacing)
# Return the overall height
return max(column_heights)

View File

@@ -23,7 +23,7 @@ import html
import sys import sys
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
log = logging.getLogger('base') log = logging.getLogger('base')
@@ -570,9 +570,13 @@ class FCEntry3(FCEntry):
class EvalEntry(QtWidgets.QLineEdit): class EvalEntry(QtWidgets.QLineEdit):
def __init__(self, parent=None): def __init__(self, border_color=None, parent=None):
super(EvalEntry, self).__init__(parent) super(EvalEntry, self).__init__(parent)
self.readyToEdit = True self.readyToEdit = True
if border_color:
self.setStyleSheet("QLineEdit {border: 1px solid %s;}" % border_color)
self.editingFinished.connect(self.on_edit_finished) self.editingFinished.connect(self.on_edit_finished)
def on_edit_finished(self): def on_edit_finished(self):
@@ -599,7 +603,6 @@ class EvalEntry(QtWidgets.QLineEdit):
def get_value(self): def get_value(self):
raw = str(self.text()).strip(' ') raw = str(self.text()).strip(' ')
evaled = 0.0
try: try:
evaled = eval(raw) evaled = eval(raw)
except Exception as e: except Exception as e:
@@ -639,7 +642,7 @@ class EvalEntry2(QtWidgets.QLineEdit):
def get_value(self): def get_value(self):
raw = str(self.text()).strip(' ') raw = str(self.text()).strip(' ')
evaled = 0.0
try: try:
evaled = eval(raw) evaled = eval(raw)
except Exception as e: except Exception as e:
@@ -656,6 +659,132 @@ class EvalEntry2(QtWidgets.QLineEdit):
return QtCore.QSize(EDIT_SIZE_HINT, default_hint_size.height()) return QtCore.QSize(EDIT_SIZE_HINT, default_hint_size.height())
class NumericalEvalEntry(EvalEntry):
"""
Will evaluate the input and return a value. Accepts only float numbers and formulas using the operators: /,*,+,-,%
"""
def __init__(self, border_color=None):
super().__init__(border_color=border_color)
regex = QtCore.QRegExp("[0-9\/\*\+\-\%\.\s]*")
validator = QtGui.QRegExpValidator(regex, self)
self.setValidator(validator)
class NumericalEvalTupleEntry(FCEntry):
"""
Will evaluate the input and return a value. Accepts only float numbers and formulas using the operators: /,*,+,-,%
"""
def __init__(self, border_color=None):
super().__init__(border_color=border_color)
regex = QtCore.QRegExp("[0-9\/\*\+\-\%\.\s\,]*")
validator = QtGui.QRegExpValidator(regex, self)
self.setValidator(validator)
class FCColorEntry(QtWidgets.QFrame):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.entry = FCEntry()
regex = QtCore.QRegExp("[#A-Fa-f0-9]*")
validator = QtGui.QRegExpValidator(regex, self.entry)
self.entry.setValidator(validator)
self.button = QtWidgets.QPushButton()
self.button.setFixedSize(15, 15)
self.button.setStyleSheet("border-color: dimgray;")
self.layout = QtWidgets.QHBoxLayout()
self.layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.addWidget(self.entry)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.entry.editingFinished.connect(self._sync_button_color)
self.button.clicked.connect(self._on_button_clicked)
self.editingFinished = self.entry.editingFinished
def get_value(self) -> str:
return self.entry.get_value()
def set_value(self, value: str):
self.entry.set_value(value)
self._sync_button_color()
def _sync_button_color(self):
value = self.get_value()
self.button.setStyleSheet("background-color:%s;" % self._extract_color(value))
def _on_button_clicked(self):
value = self.entry.get_value()
current_color = QtGui.QColor(self._extract_color(value))
color_dialog = QtWidgets.QColorDialog()
selected_color = color_dialog.getColor(initial=current_color, options=QtWidgets.QColorDialog.ShowAlphaChannel)
if selected_color.isValid() is False:
return
new_value = str(selected_color.name()) + self._extract_alpha(value)
self.set_value(new_value)
def _extract_color(self, value: str) -> str:
return value[:7]
def _extract_alpha(self, value: str) -> str:
return value[7:9]
class FCSliderWithSpinner(QtWidgets.QFrame):
def __init__(self, min=0, max=100, step=1, **kwargs):
super().__init__(**kwargs)
self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.slider.setMinimum(min)
self.slider.setMaximum(max)
self.slider.setSingleStep(step)
self.spinner = FCSpinner()
self.spinner.set_range(min, max)
self.spinner.set_step(step)
self.spinner.setMinimumWidth(70)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
self.spinner.setSizePolicy(sizePolicy)
self.layout = QtWidgets.QHBoxLayout()
self.layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.addWidget(self.slider)
self.layout.addWidget(self.spinner)
self.setLayout(self.layout)
self.slider.valueChanged.connect(self._on_slider)
self.spinner.valueChanged.connect(self._on_spinner)
self.valueChanged = self.spinner.valueChanged
def get_value(self) -> int:
return self.spinner.get_value()
def set_value(self, value: int):
self.spinner.set_value(value)
def _on_spinner(self):
spinner_value = self.spinner.value()
self.slider.setValue(spinner_value)
def _on_slider(self):
slider_value = self.slider.value()
self.spinner.set_value(slider_value)
class FCSpinner(QtWidgets.QSpinBox): class FCSpinner(QtWidgets.QSpinBox):
returnPressed = QtCore.pyqtSignal() returnPressed = QtCore.pyqtSignal()
@@ -684,6 +813,8 @@ class FCSpinner(QtWidgets.QSpinBox):
self.setAlignment(align_val) self.setAlignment(align_val)
self.prev_readyToEdit = True self.prev_readyToEdit = True
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Preferred)
self.setSizePolicy(sizePolicy)
def eventFilter(self, object, event): def eventFilter(self, object, event):
if event.type() == QtCore.QEvent.MouseButtonPress and self.prev_readyToEdit is True: if event.type() == QtCore.QEvent.MouseButtonPress and self.prev_readyToEdit is True:
@@ -816,6 +947,8 @@ class FCDoubleSpinner(QtWidgets.QDoubleSpinBox):
self.setAlignment(align_val) self.setAlignment(align_val)
self.prev_readyToEdit = True self.prev_readyToEdit = True
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Preferred)
self.setSizePolicy(sizePolicy)
def on_edit_finished(self): def on_edit_finished(self):
self.clearFocus() self.clearFocus()
@@ -2098,6 +2231,24 @@ class FCDetachableTab2(FCDetachableTab):
def __init__(self, protect=None, protect_by_name=None, parent=None): def __init__(self, protect=None, protect_by_name=None, parent=None):
super(FCDetachableTab2, self).__init__(protect=protect, protect_by_name=protect_by_name, parent=parent) super(FCDetachableTab2, self).__init__(protect=protect, protect_by_name=protect_by_name, parent=parent)
try:
self.tabBar.onCloseTabSignal.disconnect()
except TypeError:
pass
self.tabBar.onCloseTabSignal.connect(self.on_closetab_middle_button)
def on_closetab_middle_button(self, current_index):
"""
:param current_index:
:return:
"""
# if tab is protected don't delete it
if self.tabBar.tabButton(current_index, QtWidgets.QTabBar.RightSide) is not None:
self.closeTab(current_index)
def closeTab(self, currentIndex): def closeTab(self, currentIndex):
""" """
Slot connected to the tabCloseRequested signal Slot connected to the tabCloseRequested signal
@@ -2196,11 +2347,14 @@ class OptionalHideInputSection:
""" """
Associates the a checkbox with a set of inputs. Associates the a checkbox with a set of inputs.
:param cb: Checkbox that enables the optional inputs. :param cb: Checkbox that enables the optional inputs.
:param optinputs: List of widgets that are optional. :type cb: QtWidgets.QCheckBox
:param logic: When True the logic is normal, when False the logic is in reverse :param optinputs: List of widgets that are optional.
It means that for logic=True, when the checkbox is checked the widgets are Enabled, and :type optinputs: list
for logic=False, when the checkbox is checked the widgets are Disabled :param logic: When True the logic is normal, when False the logic is in reverse
It means that for logic=True, when the checkbox is checked the widgets are Enabled, and
for logic=False, when the checkbox is checked the widgets are Disabled
:type logic: bool
:return: :return:
""" """
assert isinstance(cb, FCCheckBox), \ assert isinstance(cb, FCCheckBox), \
@@ -2471,7 +2625,8 @@ class SpinBoxDelegate(QtWidgets.QItemDelegate):
def updateEditorGeometry(self, editor, option, index): def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect) editor.setGeometry(option.rect)
def setDecimals(self, spinbox, digits): @staticmethod
def setDecimals(spinbox, digits):
spinbox.setDecimals(digits) spinbox.setDecimals(digits)
@@ -2519,7 +2674,7 @@ class DialogBoxRadio(QtWidgets.QDialog):
:param title: string with the window title :param title: string with the window title
:param label: string with the message inside the dialog box :param label: string with the message inside the dialog box
""" """
super(DialogBoxRadio, self).__init__() super(DialogBoxRadio, self).__init__(parent=parent)
if initial_text is None: if initial_text is None:
self.location = str((0, 0)) self.location = str((0, 0))
else: else:
@@ -2762,9 +2917,12 @@ class MyCompleter(QCompleter):
insertText = QtCore.pyqtSignal(str) insertText = QtCore.pyqtSignal(str)
def __init__(self, parent=None): def __init__(self, parent=None):
QCompleter.__init__(self) QCompleter.__init__(self, parent=parent)
self.setCompletionMode(QCompleter.PopupCompletion) self.setCompletionMode(QCompleter.PopupCompletion)
self.highlighted.connect(self.setHighlighted) self.highlighted.connect(self.setHighlighted)
self.lastSelected = ''
# self.popup().installEventFilter(self) # self.popup().installEventFilter(self)
# def eventFilter(self, obj, event): # def eventFilter(self, obj, event):
@@ -2920,9 +3078,9 @@ class FCFileSaveDialog(QtWidgets.QFileDialog):
super(FCFileSaveDialog, self).__init__(*args) super(FCFileSaveDialog, self).__init__(*args)
@staticmethod @staticmethod
def get_saved_filename(parent=None, caption='', directory='', filter='', initialFilter=''): def get_saved_filename(parent=None, caption='', directory='', ext_filter='', initialFilter=''):
filename, _filter = QtWidgets.QFileDialog.getSaveFileName(parent=parent, caption=caption, filename, _filter = QtWidgets.QFileDialog.getSaveFileName(parent=parent, caption=caption,
directory=directory, filter=filter, directory=directory, filter=ext_filter,
initialFilter=initialFilter) initialFilter=initialFilter)
filename = str(filename) filename = str(filename)
@@ -2938,6 +3096,225 @@ class FCFileSaveDialog(QtWidgets.QFileDialog):
return filename, _filter return filename, _filter
class FCDock(QtWidgets.QDockWidget):
def __init__(self, *args, **kwargs):
super(FCDock, self).__init__(*args)
self.close_callback = kwargs["close_callback"] if "close_callback" in kwargs else None
def closeEvent(self, event: QtGui.QCloseEvent) -> None:
self.close_callback()
super().closeEvent(event)
def show(self) -> None:
if self.isFloating():
self.setFloating(False)
super().show()
class FlatCAMActivityView(QtWidgets.QWidget):
"""
This class create and control the activity icon displayed in the App status bar
"""
def __init__(self, app, parent=None):
super().__init__(parent=parent)
self.app = app
if self.app.defaults["global_activity_icon"] == "Ball green":
icon = self.app.resource_location + '/active_2_static.png'
movie = self.app.resource_location + "/active_2.gif"
elif self.app.defaults["global_activity_icon"] == "Ball black":
icon = self.app.resource_location + '/active_static.png'
movie = self.app.resource_location + "/active.gif"
elif self.app.defaults["global_activity_icon"] == "Arrow green":
icon = self.app.resource_location + '/active_3_static.png'
movie = self.app.resource_location + "/active_3.gif"
elif self.app.defaults["global_activity_icon"] == "Eclipse green":
icon = self.app.resource_location + '/active_4_static.png'
movie = self.app.resource_location + "/active_4.gif"
else:
icon = self.app.resource_location + '/active_static.png'
movie = self.app.resource_location + "/active.gif"
self.setMinimumWidth(200)
self.movie_path = movie
self.icon_path = icon
self.icon = FCLabel(self)
self.icon.setGeometry(0, 0, 16, 12)
self.movie = QtGui.QMovie(self.movie_path)
self.icon.setMovie(self.movie)
# self.movie.start()
layout = QtWidgets.QHBoxLayout()
layout.setContentsMargins(5, 0, 5, 0)
layout.setAlignment(QtCore.Qt.AlignLeft)
self.setLayout(layout)
layout.addWidget(self.icon)
self.text = QtWidgets.QLabel(self)
self.text.setText(_("Idle."))
self.icon.setPixmap(QtGui.QPixmap(self.icon_path))
layout.addWidget(self.text)
self.icon.clicked.connect(self.app.on_toolbar_replot)
def set_idle(self):
self.movie.stop()
self.text.setText(_("Idle."))
def set_busy(self, msg, no_movie=None):
if no_movie is not True:
self.icon.setMovie(self.movie)
self.movie.start()
self.text.setText(msg)
class FlatCAMInfoBar(QtWidgets.QWidget):
"""
This class create a place to display the App messages in the Status Bar
"""
def __init__(self, parent=None, app=None):
super(FlatCAMInfoBar, self).__init__(parent=parent)
self.app = app
self.icon = QtWidgets.QLabel(self)
self.icon.setGeometry(0, 0, 12, 12)
self.pmap = QtGui.QPixmap(self.app.resource_location + '/graylight12.png')
self.icon.setPixmap(self.pmap)
self.lock_pmaps = False
layout = QtWidgets.QHBoxLayout()
layout.setContentsMargins(5, 0, 5, 0)
self.setLayout(layout)
layout.addWidget(self.icon)
self.text = QtWidgets.QLabel(self)
self.text.setText(_("Application started ..."))
self.text.setToolTip(_("Hello!"))
layout.addWidget(self.text)
layout.addStretch()
def set_text_(self, text, color=None):
self.text.setText(text)
self.text.setToolTip(text)
if color:
self.text.setStyleSheet('color: %s' % str(color))
def set_status(self, text, level="info"):
level = str(level)
if self.lock_pmaps is not True:
self.pmap.fill()
if level == "ERROR" or level == "ERROR_NOTCL":
self.pmap = QtGui.QPixmap(self.app.resource_location + '/redlight12.png')
elif level.lower() == "success":
self.pmap = QtGui.QPixmap(self.app.resource_location + '/greenlight12.png')
elif level == "WARNING" or level == "WARNING_NOTCL":
self.pmap = QtGui.QPixmap(self.app.resource_location + '/yellowlight12.png')
elif level.lower() == "selected":
self.pmap = QtGui.QPixmap(self.app.resource_location + '/bluelight12.png')
else:
self.pmap = QtGui.QPixmap(self.app.resource_location + '/graylight12.png')
try:
self.set_text_(text)
self.icon.setPixmap(self.pmap)
except Exception as e:
log.debug("FlatCAMInfoBar.set_status() --> %s" % str(e))
class FlatCAMSystemTray(QtWidgets.QSystemTrayIcon):
"""
This class create the Sys Tray icon for the app
"""
def __init__(self, app, icon, headless=None, parent=None):
# QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
super().__init__(icon, parent=parent)
self.app = app
menu = QtWidgets.QMenu(parent)
menu_runscript = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/script14.png'),
'%s' % _('Run Script ...'), self)
menu_runscript.setToolTip(
_("Will run the opened Tcl Script thus\n"
"enabling the automation of certain\n"
"functions of FlatCAM.")
)
menu.addAction(menu_runscript)
menu.addSeparator()
if headless is None:
self.menu_open = menu.addMenu(QtGui.QIcon(self.app.resource_location + '/folder32_bis.png'), _('Open'))
# Open Project ...
menu_openproject = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/folder16.png'),
_('Open Project ...'), self)
self.menu_open.addAction(menu_openproject)
self.menu_open.addSeparator()
# Open Gerber ...
menu_opengerber = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/flatcam_icon24.png'),
_('Open &Gerber ...\tCtrl+G'), self)
self.menu_open.addAction(menu_opengerber)
# Open Excellon ...
menu_openexcellon = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/open_excellon32.png'),
_('Open &Excellon ...\tCtrl+E'), self)
self.menu_open.addAction(menu_openexcellon)
# Open G-Code ...
menu_opengcode = QtWidgets.QAction(QtGui.QIcon(self.app.resource_location + '/code.png'),
_('Open G-&Code ...'), self)
self.menu_open.addAction(menu_opengcode)
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)
exitAction = menu.addAction(_("Exit"))
exitAction.setIcon(QtGui.QIcon(self.app.resource_location + '/power16.png'))
self.setContextMenu(menu)
menu_runscript.triggered.connect(lambda: self.app.on_filerunscript(
silent=True if self.app.cmd_line_headless == 1 else False))
exitAction.triggered.connect(self.app.final_save)
def message_dialog(title, message, kind="info", parent=None):
"""
Builds and show a custom QMessageBox to be used in FlatCAM.
:param title: title of the QMessageBox
:param message: message to be displayed
:param kind: type of QMessageBox; will display a specific icon.
:param parent: parent
:return: None
"""
icon = {"info": QtWidgets.QMessageBox.Information,
"warning": QtWidgets.QMessageBox.Warning,
"error": QtWidgets.QMessageBox.Critical}[str(kind)]
dlg = QtWidgets.QMessageBox(icon, title, message, parent=parent)
dlg.setText(message)
dlg.exec_()
def rreplace(s, old, new, occurrence): def rreplace(s, old, new, occurrence):
""" """
Credits go here: Credits go here:

File diff suppressed because it is too large Load Diff

View File

@@ -11,11 +11,11 @@
# Date: 3/10/2019 # # Date: 3/10/2019 #
# ########################################################## # ##########################################################
from flatcamGUI.GUIElements import * from AppGUI.GUIElements import *
import sys import sys
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -35,7 +35,7 @@ class ObjectUI(QtWidgets.QWidget):
put UI elements in ObjectUI.custom_box (QtWidgets.QLayout). put UI elements in ObjectUI.custom_box (QtWidgets.QLayout).
""" """
def __init__(self, app, icon_file='assets/resources/flatcam_icon32.png', title=_('FlatCAM Object'), def __init__(self, app, icon_file='assets/resources/flatcam_icon32.png', title=_('App Object'),
parent=None, common=True): parent=None, common=True):
QtWidgets.QWidget.__init__(self, parent=parent) QtWidgets.QWidget.__init__(self, parent=parent)
@@ -114,7 +114,7 @@ class ObjectUI(QtWidgets.QWidget):
self.common_grid.addWidget(self.transform_label, 2, 0, 1, 2) self.common_grid.addWidget(self.transform_label, 2, 0, 1, 2)
# ### Scale #### # ### Scale ####
self.scale_entry = FCEntry() self.scale_entry = NumericalEvalEntry(border_color='#0069A9')
self.scale_entry.set_value(1.0) self.scale_entry.set_value(1.0)
self.scale_entry.setToolTip( self.scale_entry.setToolTip(
_("Factor by which to multiply\n" _("Factor by which to multiply\n"
@@ -132,7 +132,7 @@ class ObjectUI(QtWidgets.QWidget):
self.common_grid.addWidget(self.scale_button, 3, 1) self.common_grid.addWidget(self.scale_button, 3, 1)
# ### Offset #### # ### Offset ####
self.offsetvector_entry = EvalEntry2() self.offsetvector_entry = NumericalEvalTupleEntry(border_color='#0069A9')
self.offsetvector_entry.setText("(0.0, 0.0)") self.offsetvector_entry.setText("(0.0, 0.0)")
self.offsetvector_entry.setToolTip( self.offsetvector_entry.setToolTip(
_("Amount by which to move the object\n" _("Amount by which to move the object\n"
@@ -149,21 +149,30 @@ class ObjectUI(QtWidgets.QWidget):
self.common_grid.addWidget(self.offsetvector_entry, 4, 0) self.common_grid.addWidget(self.offsetvector_entry, 4, 0)
self.common_grid.addWidget(self.offset_button, 4, 1) self.common_grid.addWidget(self.offset_button, 4, 1)
self.transformations_button = QtWidgets.QPushButton(_('Transformations'))
self.transformations_button.setToolTip(
_("Geometrical transformations of the current object.")
)
self.common_grid.addWidget(self.transformations_button, 5, 0, 1, 2)
layout.addStretch() layout.addStretch()
def confirmation_message(self, accepted, minval, maxval): def confirmation_message(self, accepted, minval, maxval):
if accepted is False: if accepted is False:
self.app.inform.emit('[WARNING_NOTCL] %s: [%.*f, %.*f]' % self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%.*f, %.*f]' % (_("Edited value is out of range"),
(_("Edited value is out of range"), self.decimals, minval, self.decimals, maxval)) self.decimals,
minval,
self.decimals,
maxval), False)
else: else:
self.app.inform.emit('[success] %s' % _("Edited value is within limits.")) self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)
def confirmation_message_int(self, accepted, minval, maxval): def confirmation_message_int(self, accepted, minval, maxval):
if accepted is False: if accepted is False:
self.app.inform.emit('[WARNING_NOTCL] %s: [%d, %d]' % self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%d, %d]' %
(_("Edited value is out of range"), minval, maxval)) (_("Edited value is out of range"), minval, maxval), False)
else: else:
self.app.inform.emit('[success] %s' % _("Edited value is within limits.")) self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)
class GerberObjectUI(ObjectUI): class GerberObjectUI(ObjectUI):
@@ -205,27 +214,37 @@ class GerberObjectUI(ObjectUI):
self.multicolored_cb.setMinimumWidth(55) self.multicolored_cb.setMinimumWidth(55)
grid0.addWidget(self.multicolored_cb, 0, 2) grid0.addWidget(self.multicolored_cb, 0, 2)
# Plot CB
self.plot_cb = FCCheckBox('%s' % _("Plot"))
# self.plot_cb.setLayoutDirection(QtCore.Qt.RightToLeft)
self.plot_cb.setToolTip(_("Plot (show) this object."))
grid0.addWidget(self.plot_cb, 1, 0, 1, 2)
# ## Object name # ## Object name
self.name_hlay = QtWidgets.QHBoxLayout() self.name_hlay = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(self.name_hlay) grid0.addLayout(self.name_hlay, 1, 0, 1, 3)
name_label = QtWidgets.QLabel("<b>%s:</b>" % _("Name")) name_label = QtWidgets.QLabel("<b>%s:</b>" % _("Name"))
self.name_entry = FCEntry() self.name_entry = FCEntry()
self.name_entry.setFocusPolicy(QtCore.Qt.StrongFocus) self.name_entry.setFocusPolicy(QtCore.Qt.StrongFocus)
self.name_hlay.addWidget(name_label) self.name_hlay.addWidget(name_label)
self.name_hlay.addWidget(self.name_entry) self.name_hlay.addWidget(self.name_entry)
# Plot CB
self.plot_lbl = FCLabel('%s:' % _("Plot"))
self.plot_lbl.setToolTip(_("Plot (show) this object."))
self.plot_cb = FCCheckBox()
grid0.addWidget(self.plot_lbl, 2, 0)
grid0.addWidget(self.plot_cb, 2, 1)
# generate follow
self.follow_cb = FCCheckBox('%s' % _("Follow"))
self.follow_cb.setToolTip(_("Generate a 'Follow' geometry.\n"
"This means that it will cut through\n"
"the middle of the trace."))
self.follow_cb.setMinimumWidth(55)
grid0.addWidget(self.follow_cb, 2, 2)
hlay_plot = QtWidgets.QHBoxLayout() hlay_plot = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(hlay_plot) self.custom_box.addLayout(hlay_plot)
# ### Gerber Apertures #### # ### Gerber Apertures ####
self.apertures_table_label = QtWidgets.QLabel('<b>%s:</b>' % _('Apertures')) self.apertures_table_label = QtWidgets.QLabel('%s:' % _('Apertures'))
self.apertures_table_label.setToolTip( self.apertures_table_label.setToolTip(
_("Apertures Table for the Gerber Object.") _("Apertures Table for the Gerber Object.")
) )
@@ -282,254 +301,7 @@ class GerberObjectUI(ObjectUI):
# start with apertures table hidden # start with apertures table hidden
self.apertures_table.setVisible(False) self.apertures_table.setVisible(False)
separator_line = QtWidgets.QFrame() # Buffer Geometry
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.custom_box.addWidget(separator_line)
# Isolation Routing
self.isolation_routing_label = QtWidgets.QLabel("<b>%s</b>" % _("Isolation Routing"))
self.isolation_routing_label.setToolTip(
_("Create a Geometry object with\n"
"toolpaths to cut outside polygons.")
)
self.custom_box.addWidget(self.isolation_routing_label)
# ###########################################
# ########## NEW GRID #######################
# ###########################################
grid1 = QtWidgets.QGridLayout()
self.custom_box.addLayout(grid1)
grid1.setColumnStretch(0, 0)
grid1.setColumnStretch(1, 1)
grid1.setColumnStretch(2, 1)
# Tool Type
self.tool_type_label = QtWidgets.QLabel('%s:' % _('Tool Type'))
self.tool_type_label.setToolTip(
_("Choose which tool to use for Gerber isolation:\n"
"'Circular' or 'V-shape'.\n"
"When the 'V-shape' is selected then the tool\n"
"diameter will depend on the chosen cut depth.")
)
self.tool_type_radio = RadioSet([{'label': _('Circular'), 'value': 'circular'},
{'label': _('V-Shape'), 'value': 'v'}])
grid1.addWidget(self.tool_type_label, 0, 0)
grid1.addWidget(self.tool_type_radio, 0, 1, 1, 2)
# Tip Dia
self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia'))
self.tipdialabel.setToolTip(
_("The tip diameter for V-Shape Tool")
)
self.tipdia_spinner = FCDoubleSpinner(callback=self.confirmation_message)
self.tipdia_spinner.set_range(-99.9999, 99.9999)
self.tipdia_spinner.set_precision(self.decimals)
self.tipdia_spinner.setSingleStep(0.1)
self.tipdia_spinner.setWrapping(True)
grid1.addWidget(self.tipdialabel, 1, 0)
grid1.addWidget(self.tipdia_spinner, 1, 1, 1, 2)
# Tip Angle
self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle'))
self.tipanglelabel.setToolTip(
_("The tip angle for V-Shape Tool.\n"
"In degree.")
)
self.tipangle_spinner = FCDoubleSpinner(callback=self.confirmation_message)
self.tipangle_spinner.set_range(1, 180)
self.tipangle_spinner.set_precision(self.decimals)
self.tipangle_spinner.setSingleStep(5)
self.tipangle_spinner.setWrapping(True)
grid1.addWidget(self.tipanglelabel, 2, 0)
grid1.addWidget(self.tipangle_spinner, 2, 1, 1, 2)
# Cut Z
self.cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
self.cutzlabel.setToolTip(
_("Cutting depth (negative)\n"
"below the copper surface.")
)
self.cutz_spinner = FCDoubleSpinner(callback=self.confirmation_message)
self.cutz_spinner.set_range(-9999.9999, 0.0000)
self.cutz_spinner.set_precision(self.decimals)
self.cutz_spinner.setSingleStep(0.1)
self.cutz_spinner.setWrapping(True)
grid1.addWidget(self.cutzlabel, 3, 0)
grid1.addWidget(self.cutz_spinner, 3, 1, 1, 2)
# Tool diameter
tdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
tdlabel.setToolTip(
_("Diameter of the cutting tool.\n"
"If you want to have an isolation path\n"
"inside the actual shape of the Gerber\n"
"feature, use a negative value for\n"
"this parameter.")
)
tdlabel.setMinimumWidth(90)
self.iso_tool_dia_entry = FCDoubleSpinner(callback=self.confirmation_message)
self.iso_tool_dia_entry.set_range(-9999.9999, 9999.9999)
self.iso_tool_dia_entry.set_precision(self.decimals)
self.iso_tool_dia_entry.setSingleStep(0.1)
grid1.addWidget(tdlabel, 4, 0)
grid1.addWidget(self.iso_tool_dia_entry, 4, 1, 1, 2)
# Number of Passes
passlabel = QtWidgets.QLabel('%s:' % _('# Passes'))
passlabel.setToolTip(
_("Width of the isolation gap in\n"
"number (integer) of tool widths.")
)
passlabel.setMinimumWidth(90)
self.iso_width_entry = FCSpinner(callback=self.confirmation_message_int)
self.iso_width_entry.set_range(1, 999)
grid1.addWidget(passlabel, 5, 0)
grid1.addWidget(self.iso_width_entry, 5, 1, 1, 2)
# Pass overlap
overlabel = QtWidgets.QLabel('%s:' % _('Pass overlap'))
overlabel.setToolTip(
_("How much (percentage) of the tool width to overlap each tool pass.")
)
overlabel.setMinimumWidth(90)
self.iso_overlap_entry = FCDoubleSpinner(suffix='%', callback=self.confirmation_message)
self.iso_overlap_entry.set_precision(self.decimals)
self.iso_overlap_entry.setWrapping(True)
self.iso_overlap_entry.set_range(0.0000, 99.9999)
self.iso_overlap_entry.setSingleStep(0.1)
grid1.addWidget(overlabel, 6, 0)
grid1.addWidget(self.iso_overlap_entry, 6, 1, 1, 2)
# Milling Type Radio Button
self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
self.milling_type_label.setToolTip(
_("Milling type:\n"
"- climb / best for precision milling and to reduce tool usage\n"
"- conventional / useful when there is no backlash compensation")
)
self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
{'label': _('Conventional'), 'value': 'cv'}])
grid1.addWidget(self.milling_type_label, 7, 0)
grid1.addWidget(self.milling_type_radio, 7, 1, 1, 2)
# combine all passes CB
self.combine_passes_cb = FCCheckBox(label=_('Combine'))
self.combine_passes_cb.setToolTip(
_("Combine all passes into one object")
)
# generate follow
self.follow_cb = FCCheckBox(label=_('"Follow"'))
self.follow_cb.setToolTip(_("Generate a 'Follow' geometry.\n"
"This means that it will cut through\n"
"the middle of the trace."))
grid1.addWidget(self.combine_passes_cb, 8, 0)
# avoid an area from isolation
self.except_cb = FCCheckBox(label=_('Except'))
grid1.addWidget(self.follow_cb, 8, 1)
self.except_cb.setToolTip(_("When the isolation geometry is generated,\n"
"by checking this, the area of the object below\n"
"will be subtracted from the isolation geometry."))
grid1.addWidget(self.except_cb, 8, 2)
# ## Form Layout
form_layout = QtWidgets.QFormLayout()
grid1.addLayout(form_layout, 9, 0, 1, 3)
# ################################################
# ##### Type of object to be excepted ############
# ################################################
self.type_obj_combo = FCComboBox()
self.type_obj_combo.addItems([_("Gerber"), _("Geometry")])
# we get rid of item1 ("Excellon") as it is not suitable
# self.type_obj_combo.view().setRowHidden(1, True)
self.type_obj_combo.setItemIcon(0, QtGui.QIcon(self.resource_loc + "/flatcam_icon16.png"))
self.type_obj_combo.setItemIcon(1, QtGui.QIcon(self.resource_loc + "/geometry16.png"))
self.type_obj_combo_label = QtWidgets.QLabel('%s:' % _("Obj Type"))
self.type_obj_combo_label.setToolTip(
_("Specify the type of object to be excepted from isolation.\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.")
)
# self.type_obj_combo_label.setMinimumWidth(60)
form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo)
# ################################################
# ##### The object to be excepted ################
# ################################################
self.obj_combo = FCComboBox()
self.obj_label = QtWidgets.QLabel('%s:' % _("Object"))
self.obj_label.setToolTip(_("Object whose area will be removed from isolation geometry."))
form_layout.addRow(self.obj_label, self.obj_combo)
# ---------------------------------------------- #
# --------- Isolation scope -------------------- #
# ---------------------------------------------- #
self.iso_scope_label = QtWidgets.QLabel('<b>%s:</b>' % _('Scope'))
self.iso_scope_label.setToolTip(
_("Isolation scope. Choose what to isolate:\n"
"- 'All' -> Isolate all the polygons in the object\n"
"- 'Selection' -> Isolate a selection of polygons.")
)
self.iso_scope_radio = RadioSet([{'label': _('All'), 'value': 'all'},
{'label': _('Selection'), 'value': 'single'}])
grid1.addWidget(self.iso_scope_label, 10, 0)
grid1.addWidget(self.iso_scope_radio, 10, 1, 1, 2)
# ---------------------------------------------- #
# --------- Isolation type -------------------- #
# ---------------------------------------------- #
self.iso_type_label = QtWidgets.QLabel('<b>%s:</b>' % _('Isolation Type'))
self.iso_type_label.setToolTip(
_("Choose how the isolation will be executed:\n"
"- 'Full' -> complete isolation of polygons\n"
"- 'Ext' -> will isolate only on the outside\n"
"- 'Int' -> will isolate only on the inside\n"
"'Exterior' isolation is almost always possible\n"
"(with the right tool) but 'Interior'\n"
"isolation can be done only when there is an opening\n"
"inside of the polygon (e.g polygon is a 'doughnut' shape).")
)
self.iso_type_radio = RadioSet([{'label': _('Full'), 'value': 'full'},
{'label': _('Ext'), 'value': 'ext'},
{'label': _('Int'), 'value': 'int'}])
grid1.addWidget(self.iso_type_label, 11, 0)
grid1.addWidget(self.iso_type_radio, 11, 1, 1, 2)
self.generate_iso_button = QtWidgets.QPushButton("%s" % _("Generate Isolation Geometry"))
self.generate_iso_button.setStyleSheet("""
QPushButton
{
font-weight: bold;
}
""")
self.generate_iso_button.setToolTip(
_("Create a Geometry object with toolpaths to cut \n"
"isolation outside, inside or on both sides of the\n"
"object. For a Gerber object outside means outside\n"
"of the Gerber feature and inside means inside of\n"
"the Gerber feature, if possible at all. This means\n"
"that only if the Gerber feature has openings inside, they\n"
"will be isolated. If what is wanted is to cut isolation\n"
"inside the actual Gerber feature, use a negative tool\n"
"diameter above.")
)
grid1.addWidget(self.generate_iso_button, 12, 0, 1, 3)
self.create_buffer_button = QtWidgets.QPushButton(_('Buffer Solid Geometry')) self.create_buffer_button = QtWidgets.QPushButton(_('Buffer Solid Geometry'))
self.create_buffer_button.setToolTip( self.create_buffer_button.setToolTip(
_("This button is shown only when the Gerber file\n" _("This button is shown only when the Gerber file\n"
@@ -537,19 +309,12 @@ class GerberObjectUI(ObjectUI):
"Clicking this will create the buffered geometry\n" "Clicking this will create the buffered geometry\n"
"required for isolation.") "required for isolation.")
) )
grid1.addWidget(self.create_buffer_button, 13, 0, 1, 3) self.custom_box.addWidget(self.create_buffer_button)
self.ohis_iso = OptionalHideInputSection( separator_line = QtWidgets.QFrame()
self.except_cb, separator_line.setFrameShape(QtWidgets.QFrame.HLine)
[self.type_obj_combo, self.type_obj_combo_label, self.obj_combo, self.obj_label], separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
logic=True self.custom_box.addWidget(separator_line)
)
separator_line2 = QtWidgets.QFrame()
separator_line2.setFrameShape(QtWidgets.QFrame.HLine)
separator_line2.setFrameShadow(QtWidgets.QFrame.Sunken)
grid1.addWidget(separator_line2, 14, 0, 1, 3)
# grid1.addWidget(QtWidgets.QLabel(''), 15, 0)
# ########################################### # ###########################################
# ########## NEW GRID ####################### # ########## NEW GRID #######################
@@ -563,14 +328,21 @@ class GerberObjectUI(ObjectUI):
self.tool_lbl = QtWidgets.QLabel('<b>%s</b>' % _("TOOLS")) self.tool_lbl = QtWidgets.QLabel('<b>%s</b>' % _("TOOLS"))
grid2.addWidget(self.tool_lbl, 0, 0, 1, 2) grid2.addWidget(self.tool_lbl, 0, 0, 1, 2)
# ## Clear non-copper regions # Isolation Tool - will create isolation paths around the copper features
self.clearcopper_label = QtWidgets.QLabel("%s" % _("Clear N-copper")) self.iso_button = QtWidgets.QPushButton(_('Isolation Routing'))
self.clearcopper_label.setToolTip( self.iso_button.setToolTip(
_("Create a Geometry object with\n" _("Create a Geometry object with\n"
"toolpaths to cut all non-copper regions.") "toolpaths to cut around polygons.")
) )
self.clearcopper_label.setMinimumWidth(90) self.iso_button.setStyleSheet("""
QPushButton
{
font-weight: bold;
}
""")
grid2.addWidget(self.iso_button, 1, 0, 1, 2)
# ## Clear non-copper regions
self.generate_ncc_button = QtWidgets.QPushButton(_('NCC Tool')) self.generate_ncc_button = QtWidgets.QPushButton(_('NCC Tool'))
self.generate_ncc_button.setToolTip( self.generate_ncc_button.setToolTip(
_("Create the Geometry Object\n" _("Create the Geometry Object\n"
@@ -582,17 +354,9 @@ class GerberObjectUI(ObjectUI):
font-weight: bold; font-weight: bold;
} }
""") """)
grid2.addWidget(self.clearcopper_label, 1, 0) grid2.addWidget(self.generate_ncc_button, 2, 0, 1, 2)
grid2.addWidget(self.generate_ncc_button, 1, 1)
# ## Board cutout # ## Board cutout
self.board_cutout_label = QtWidgets.QLabel("%s" % _("Board cutout"))
self.board_cutout_label.setToolTip(
_("Create toolpaths to cut around\n"
"the PCB and separate it from\n"
"the original board.")
)
self.generate_cutout_button = QtWidgets.QPushButton(_('Cutout Tool')) self.generate_cutout_button = QtWidgets.QPushButton(_('Cutout Tool'))
self.generate_cutout_button.setToolTip( self.generate_cutout_button.setToolTip(
_("Generate the geometry for\n" _("Generate the geometry for\n"
@@ -604,13 +368,12 @@ class GerberObjectUI(ObjectUI):
font-weight: bold; font-weight: bold;
} }
""") """)
grid2.addWidget(self.board_cutout_label, 2, 0) grid2.addWidget(self.generate_cutout_button, 3, 0, 1, 2)
grid2.addWidget(self.generate_cutout_button, 2, 1)
separator_line = QtWidgets.QFrame() separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid2.addWidget(separator_line, 3, 0, 1, 2) grid2.addWidget(separator_line, 4, 0, 1, 2)
# ## Non-copper regions # ## Non-copper regions
self.noncopper_label = QtWidgets.QLabel("<b>%s</b>" % _("Non-copper regions")) self.noncopper_label = QtWidgets.QLabel("<b>%s</b>" % _("Non-copper regions"))
@@ -622,7 +385,7 @@ class GerberObjectUI(ObjectUI):
"copper from a specified region.") "copper from a specified region.")
) )
grid2.addWidget(self.noncopper_label, 4, 0, 1, 2) grid2.addWidget(self.noncopper_label, 5, 0, 1, 2)
# Margin # Margin
bmlabel = QtWidgets.QLabel('%s:' % _('Boundary Margin')) bmlabel = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
@@ -638,8 +401,8 @@ class GerberObjectUI(ObjectUI):
self.noncopper_margin_entry.set_precision(self.decimals) self.noncopper_margin_entry.set_precision(self.decimals)
self.noncopper_margin_entry.setSingleStep(0.1) self.noncopper_margin_entry.setSingleStep(0.1)
grid2.addWidget(bmlabel, 5, 0) grid2.addWidget(bmlabel, 6, 0)
grid2.addWidget(self.noncopper_margin_entry, 5, 1) grid2.addWidget(self.noncopper_margin_entry, 6, 1)
# Rounded corners # Rounded corners
self.noncopper_rounded_cb = FCCheckBox(label=_("Rounded Geo")) self.noncopper_rounded_cb = FCCheckBox(label=_("Rounded Geo"))
@@ -649,13 +412,13 @@ class GerberObjectUI(ObjectUI):
self.noncopper_rounded_cb.setMinimumWidth(90) self.noncopper_rounded_cb.setMinimumWidth(90)
self.generate_noncopper_button = QtWidgets.QPushButton(_('Generate Geo')) self.generate_noncopper_button = QtWidgets.QPushButton(_('Generate Geo'))
grid2.addWidget(self.noncopper_rounded_cb, 6, 0) grid2.addWidget(self.noncopper_rounded_cb, 7, 0)
grid2.addWidget(self.generate_noncopper_button, 6, 1) grid2.addWidget(self.generate_noncopper_button, 7, 1)
separator_line1 = QtWidgets.QFrame() separator_line1 = QtWidgets.QFrame()
separator_line1.setFrameShape(QtWidgets.QFrame.HLine) separator_line1.setFrameShape(QtWidgets.QFrame.HLine)
separator_line1.setFrameShadow(QtWidgets.QFrame.Sunken) separator_line1.setFrameShadow(QtWidgets.QFrame.Sunken)
grid2.addWidget(separator_line1, 7, 0, 1, 2) grid2.addWidget(separator_line1, 8, 0, 1, 2)
# ## Bounding box # ## Bounding box
self.boundingbox_label = QtWidgets.QLabel('<b>%s</b>' % _('Bounding Box')) self.boundingbox_label = QtWidgets.QLabel('<b>%s</b>' % _('Bounding Box'))
@@ -664,7 +427,7 @@ class GerberObjectUI(ObjectUI):
"Square shape.") "Square shape.")
) )
grid2.addWidget(self.boundingbox_label, 8, 0, 1, 2) grid2.addWidget(self.boundingbox_label, 9, 0, 1, 2)
bbmargin = QtWidgets.QLabel('%s:' % _('Boundary Margin')) bbmargin = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
bbmargin.setToolTip( bbmargin.setToolTip(
@@ -677,8 +440,8 @@ class GerberObjectUI(ObjectUI):
self.bbmargin_entry.set_precision(self.decimals) self.bbmargin_entry.set_precision(self.decimals)
self.bbmargin_entry.setSingleStep(0.1) self.bbmargin_entry.setSingleStep(0.1)
grid2.addWidget(bbmargin, 9, 0) grid2.addWidget(bbmargin, 10, 0)
grid2.addWidget(self.bbmargin_entry, 9, 1) grid2.addWidget(self.bbmargin_entry, 10, 1)
self.bbrounded_cb = FCCheckBox(label=_("Rounded Geo")) self.bbrounded_cb = FCCheckBox(label=_("Rounded Geo"))
self.bbrounded_cb.setToolTip( self.bbrounded_cb.setToolTip(
@@ -693,8 +456,8 @@ class GerberObjectUI(ObjectUI):
self.generate_bb_button.setToolTip( self.generate_bb_button.setToolTip(
_("Generate the Geometry object.") _("Generate the Geometry object.")
) )
grid2.addWidget(self.bbrounded_cb, 10, 0) grid2.addWidget(self.bbrounded_cb, 11, 0)
grid2.addWidget(self.generate_bb_button, 10, 1) grid2.addWidget(self.generate_bb_button, 11, 1)
class ExcellonObjectUI(ObjectUI): class ExcellonObjectUI(ObjectUI):
@@ -723,22 +486,38 @@ class ExcellonObjectUI(ObjectUI):
parent=parent, parent=parent,
app=self.app) app=self.app)
# ### Plot options #### # Plot options
hlay_plot = QtWidgets.QHBoxLayout() grid_h = QtWidgets.QGridLayout()
self.custom_box.addLayout(hlay_plot) grid_h.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.custom_box.addLayout(grid_h)
grid_h.setColumnStretch(0, 0)
grid_h.setColumnStretch(1, 1)
self.plot_options_label = QtWidgets.QLabel("<b>%s:</b>" % _("Plot Options")) self.plot_options_label = QtWidgets.QLabel("<b>%s:</b>" % _("Plot Options"))
self.plot_options_label.setMinimumWidth(90)
grid_h.addWidget(self.plot_options_label, 0, 0)
# Solid CB
self.solid_cb = FCCheckBox(label=_('Solid')) self.solid_cb = FCCheckBox(label=_('Solid'))
self.solid_cb.setToolTip( self.solid_cb.setToolTip(
_("Solid circles.") _("Solid circles.")
) )
hlay_plot.addWidget(self.plot_options_label) self.solid_cb.setMinimumWidth(50)
hlay_plot.addStretch() grid_h.addWidget(self.solid_cb, 0, 1)
hlay_plot.addWidget(self.solid_cb)
# Multicolored CB
self.multicolored_cb = FCCheckBox(label=_('Multi-Color'))
self.multicolored_cb.setToolTip(
_("Draw polygons in different colors.")
)
self.multicolored_cb.setMinimumWidth(55)
grid_h.addWidget(self.multicolored_cb, 0, 2)
# ## Object name # ## Object name
self.name_hlay = QtWidgets.QHBoxLayout() self.name_hlay = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(self.name_hlay) grid_h.addLayout(self.name_hlay, 1, 0, 1, 3)
name_label = QtWidgets.QLabel("<b>%s:</b>" % _("Name")) name_label = QtWidgets.QLabel("<b>%s:</b>" % _("Name"))
self.name_entry = FCEntry() self.name_entry = FCEntry()
self.name_entry.setFocusPolicy(QtCore.Qt.StrongFocus) self.name_entry.setFocusPolicy(QtCore.Qt.StrongFocus)
@@ -1525,12 +1304,28 @@ class GeometryObjectUI(ObjectUI):
) )
# Plot options # Plot options
grid_header = QtWidgets.QGridLayout()
grid_header.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.custom_box.addLayout(grid_header)
grid_header.setColumnStretch(0, 0)
grid_header.setColumnStretch(1, 1)
self.plot_options_label = QtWidgets.QLabel("<b>%s:</b>" % _("Plot Options")) self.plot_options_label = QtWidgets.QLabel("<b>%s:</b>" % _("Plot Options"))
self.custom_box.addWidget(self.plot_options_label) self.plot_options_label.setMinimumWidth(90)
grid_header.addWidget(self.plot_options_label, 0, 0)
# Multicolored CB
self.multicolored_cb = FCCheckBox(label=_('Multi-Color'))
self.multicolored_cb.setToolTip(
_("Draw polygons in different colors.")
)
self.multicolored_cb.setMinimumWidth(55)
grid_header.addWidget(self.multicolored_cb, 0, 2)
# ## Object name # ## Object name
self.name_hlay = QtWidgets.QHBoxLayout() self.name_hlay = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(self.name_hlay) grid_header.addLayout(self.name_hlay, 1, 0, 1, 3)
name_label = QtWidgets.QLabel("<b>%s:</b>" % _("Name")) name_label = QtWidgets.QLabel("<b>%s:</b>" % _("Name"))
self.name_entry = FCEntry() self.name_entry = FCEntry()
@@ -1694,19 +1489,24 @@ class GeometryObjectUI(ObjectUI):
grid1.addWidget(self.addtool_entry_lbl, 3, 0) grid1.addWidget(self.addtool_entry_lbl, 3, 0)
grid1.addWidget(self.addtool_entry, 3, 1) grid1.addWidget(self.addtool_entry, 3, 1)
bhlay = QtWidgets.QHBoxLayout()
self.addtool_btn = QtWidgets.QPushButton(_('Add')) self.addtool_btn = QtWidgets.QPushButton(_('Add'))
self.addtool_btn.setToolTip( self.addtool_btn.setToolTip(
_("Add a new tool to the Tool Table\n" _("Add a new tool to the Tool Table\n"
"with the specified diameter.") "with the diameter specified above.")
) )
grid1.addWidget(self.addtool_btn, 4, 0, 1, 2)
self.addtool_from_db_btn = QtWidgets.QPushButton(_('Add from DB')) self.addtool_from_db_btn = QtWidgets.QPushButton(_('Add from DB'))
self.addtool_from_db_btn.setToolTip( self.addtool_from_db_btn.setToolTip(
_("Add a new tool to the Tool Table\n" _("Add a new tool to the Tool Table\n"
"from the Tool DataBase.") "from the Tool DataBase.")
) )
grid1.addWidget(self.addtool_from_db_btn, 7, 0, 1, 2)
bhlay.addWidget(self.addtool_btn)
bhlay.addWidget(self.addtool_from_db_btn)
grid1.addLayout(bhlay, 5, 0, 1, 2)
separator_line = QtWidgets.QFrame() separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShape(QtWidgets.QFrame.HLine)
@@ -1754,10 +1554,10 @@ class GeometryObjectUI(ObjectUI):
# ################# GRID LAYOUT 3 ############################### # ################# GRID LAYOUT 3 ###############################
# ################################################################# # #################################################################
grid3 = QtWidgets.QGridLayout() self.grid3 = QtWidgets.QGridLayout()
grid3.setColumnStretch(0, 0) self.grid3.setColumnStretch(0, 0)
grid3.setColumnStretch(1, 1) self.grid3.setColumnStretch(1, 1)
self.geo_param_box.addLayout(grid3) self.geo_param_box.addLayout(self.grid3)
# ### Tools Data ## ## # ### Tools Data ## ##
self.tool_data_label = QtWidgets.QLabel( self.tool_data_label = QtWidgets.QLabel(
@@ -1768,7 +1568,7 @@ class GeometryObjectUI(ObjectUI):
"Each tool store it's own set of such data." "Each tool store it's own set of such data."
) )
) )
grid3.addWidget(self.tool_data_label, 0, 0, 1, 2) self.grid3.addWidget(self.tool_data_label, 0, 0, 1, 2)
# Tip Dia # Tip Dia
self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia')) self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia'))
@@ -1782,8 +1582,8 @@ class GeometryObjectUI(ObjectUI):
self.tipdia_entry.set_range(0.00001, 9999.9999) self.tipdia_entry.set_range(0.00001, 9999.9999)
self.tipdia_entry.setSingleStep(0.1) self.tipdia_entry.setSingleStep(0.1)
grid3.addWidget(self.tipdialabel, 1, 0) self.grid3.addWidget(self.tipdialabel, 1, 0)
grid3.addWidget(self.tipdia_entry, 1, 1) self.grid3.addWidget(self.tipdia_entry, 1, 1)
# Tip Angle # Tip Angle
self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle')) self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle'))
@@ -1798,8 +1598,8 @@ class GeometryObjectUI(ObjectUI):
self.tipangle_entry.set_range(1.0, 180.0) self.tipangle_entry.set_range(1.0, 180.0)
self.tipangle_entry.setSingleStep(1) self.tipangle_entry.setSingleStep(1)
grid3.addWidget(self.tipanglelabel, 2, 0) self.grid3.addWidget(self.tipanglelabel, 2, 0)
grid3.addWidget(self.tipangle_entry, 2, 1) self.grid3.addWidget(self.tipangle_entry, 2, 1)
# Cut Z # Cut Z
self.cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z')) self.cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
@@ -1819,8 +1619,8 @@ class GeometryObjectUI(ObjectUI):
self.cutz_entry.setSingleStep(0.1) self.cutz_entry.setSingleStep(0.1)
grid3.addWidget(self.cutzlabel, 3, 0) self.grid3.addWidget(self.cutzlabel, 3, 0)
grid3.addWidget(self.cutz_entry, 3, 1) self.grid3.addWidget(self.cutz_entry, 3, 1)
# Multi-pass # Multi-pass
self.mpass_cb = FCCheckBox('%s:' % _("Multi-Depth")) self.mpass_cb = FCCheckBox('%s:' % _("Multi-Depth"))
@@ -1845,8 +1645,8 @@ class GeometryObjectUI(ObjectUI):
) )
self.ois_mpass_geo = OptionalInputSection(self.mpass_cb, [self.maxdepth_entry]) self.ois_mpass_geo = OptionalInputSection(self.mpass_cb, [self.maxdepth_entry])
grid3.addWidget(self.mpass_cb, 4, 0) self.grid3.addWidget(self.mpass_cb, 4, 0)
grid3.addWidget(self.maxdepth_entry, 4, 1) self.grid3.addWidget(self.maxdepth_entry, 4, 1)
# Travel Z # Travel Z
self.travelzlabel = QtWidgets.QLabel('%s:' % _('Travel Z')) self.travelzlabel = QtWidgets.QLabel('%s:' % _('Travel Z'))
@@ -1864,8 +1664,8 @@ class GeometryObjectUI(ObjectUI):
self.travelz_entry.setSingleStep(0.1) self.travelz_entry.setSingleStep(0.1)
grid3.addWidget(self.travelzlabel, 5, 0) self.grid3.addWidget(self.travelzlabel, 5, 0)
grid3.addWidget(self.travelz_entry, 5, 1) self.grid3.addWidget(self.travelz_entry, 5, 1)
# Feedrate X-Y # Feedrate X-Y
self.frlabel = QtWidgets.QLabel('%s:' % _('Feedrate X-Y')) self.frlabel = QtWidgets.QLabel('%s:' % _('Feedrate X-Y'))
@@ -1878,8 +1678,8 @@ class GeometryObjectUI(ObjectUI):
self.cncfeedrate_entry.set_range(0, 99999.9999) self.cncfeedrate_entry.set_range(0, 99999.9999)
self.cncfeedrate_entry.setSingleStep(0.1) self.cncfeedrate_entry.setSingleStep(0.1)
grid3.addWidget(self.frlabel, 10, 0) self.grid3.addWidget(self.frlabel, 10, 0)
grid3.addWidget(self.cncfeedrate_entry, 10, 1) self.grid3.addWidget(self.cncfeedrate_entry, 10, 1)
# Feedrate Z (Plunge) # Feedrate Z (Plunge)
self.frzlabel = QtWidgets.QLabel('%s:' % _('Feedrate Z')) self.frzlabel = QtWidgets.QLabel('%s:' % _('Feedrate Z'))
@@ -1893,8 +1693,8 @@ class GeometryObjectUI(ObjectUI):
self.feedrate_z_entry.set_range(0, 99999.9999) self.feedrate_z_entry.set_range(0, 99999.9999)
self.feedrate_z_entry.setSingleStep(0.1) self.feedrate_z_entry.setSingleStep(0.1)
grid3.addWidget(self.frzlabel, 11, 0) self.grid3.addWidget(self.frzlabel, 11, 0)
grid3.addWidget(self.feedrate_z_entry, 11, 1) self.grid3.addWidget(self.feedrate_z_entry, 11, 1)
# Feedrate rapids # Feedrate rapids
self.fr_rapidlabel = QtWidgets.QLabel('%s:' % _('Feedrate Rapids')) self.fr_rapidlabel = QtWidgets.QLabel('%s:' % _('Feedrate Rapids'))
@@ -1910,8 +1710,8 @@ class GeometryObjectUI(ObjectUI):
self.feedrate_rapid_entry.set_range(0, 99999.9999) self.feedrate_rapid_entry.set_range(0, 99999.9999)
self.feedrate_rapid_entry.setSingleStep(0.1) self.feedrate_rapid_entry.setSingleStep(0.1)
grid3.addWidget(self.fr_rapidlabel, 12, 0) self.grid3.addWidget(self.fr_rapidlabel, 12, 0)
grid3.addWidget(self.feedrate_rapid_entry, 12, 1) self.grid3.addWidget(self.feedrate_rapid_entry, 12, 1)
# default values is to hide # default values is to hide
self.fr_rapidlabel.hide() self.fr_rapidlabel.hide()
self.feedrate_rapid_entry.hide() self.feedrate_rapid_entry.hide()
@@ -1936,8 +1736,8 @@ class GeometryObjectUI(ObjectUI):
"meet with last cut, we generate an\n" "meet with last cut, we generate an\n"
"extended cut over the first cut section.") "extended cut over the first cut section.")
) )
grid3.addWidget(self.extracut_cb, 13, 0) self.grid3.addWidget(self.extracut_cb, 13, 0)
grid3.addWidget(self.e_cut_entry, 13, 1) self.grid3.addWidget(self.e_cut_entry, 13, 1)
# Spindlespeed # Spindlespeed
self.spindle_label = QtWidgets.QLabel('%s:' % _('Spindle speed')) self.spindle_label = QtWidgets.QLabel('%s:' % _('Spindle speed'))
@@ -1952,8 +1752,8 @@ class GeometryObjectUI(ObjectUI):
self.cncspindlespeed_entry.set_range(0, 1000000) self.cncspindlespeed_entry.set_range(0, 1000000)
self.cncspindlespeed_entry.set_step(100) self.cncspindlespeed_entry.set_step(100)
grid3.addWidget(self.spindle_label, 14, 0) self.grid3.addWidget(self.spindle_label, 14, 0)
grid3.addWidget(self.cncspindlespeed_entry, 14, 1) self.grid3.addWidget(self.cncspindlespeed_entry, 14, 1)
# Dwell # Dwell
self.dwell_cb = FCCheckBox('%s:' % _('Dwell')) self.dwell_cb = FCCheckBox('%s:' % _('Dwell'))
@@ -1973,8 +1773,8 @@ class GeometryObjectUI(ObjectUI):
) )
self.ois_dwell_geo = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry]) self.ois_dwell_geo = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry])
grid3.addWidget(self.dwell_cb, 15, 0) self.grid3.addWidget(self.dwell_cb, 15, 0)
grid3.addWidget(self.dwelltime_entry, 15, 1) self.grid3.addWidget(self.dwelltime_entry, 15, 1)
# Probe depth # Probe depth
self.pdepth_label = QtWidgets.QLabel('%s:' % _("Probe Z depth")) self.pdepth_label = QtWidgets.QLabel('%s:' % _("Probe Z depth"))
@@ -1987,8 +1787,8 @@ class GeometryObjectUI(ObjectUI):
self.pdepth_entry.set_range(-9999.9999, 9999.9999) self.pdepth_entry.set_range(-9999.9999, 9999.9999)
self.pdepth_entry.setSingleStep(0.1) self.pdepth_entry.setSingleStep(0.1)
grid3.addWidget(self.pdepth_label, 17, 0) self.grid3.addWidget(self.pdepth_label, 17, 0)
grid3.addWidget(self.pdepth_entry, 17, 1) self.grid3.addWidget(self.pdepth_entry, 17, 1)
self.pdepth_label.hide() self.pdepth_label.hide()
self.pdepth_entry.setVisible(False) self.pdepth_entry.setVisible(False)
@@ -2003,8 +1803,8 @@ class GeometryObjectUI(ObjectUI):
self.feedrate_probe_entry.set_range(0.0, 9999.9999) self.feedrate_probe_entry.set_range(0.0, 9999.9999)
self.feedrate_probe_entry.setSingleStep(0.1) self.feedrate_probe_entry.setSingleStep(0.1)
grid3.addWidget(self.feedrate_probe_label, 18, 0) self.grid3.addWidget(self.feedrate_probe_label, 18, 0)
grid3.addWidget(self.feedrate_probe_entry, 18, 1) self.grid3.addWidget(self.feedrate_probe_entry, 18, 1)
self.feedrate_probe_label.hide() self.feedrate_probe_label.hide()
self.feedrate_probe_entry.setVisible(False) self.feedrate_probe_entry.setVisible(False)

View File

@@ -8,13 +8,21 @@
from PyQt5 import QtCore from PyQt5 import QtCore
import logging import logging
from flatcamGUI.VisPyCanvas import VisPyCanvas, Color from AppGUI.VisPyCanvas import VisPyCanvas, Color
from flatcamGUI.VisPyVisuals import ShapeGroup, ShapeCollection, TextCollection, TextGroup, Cursor from AppGUI.VisPyVisuals import ShapeGroup, ShapeCollection, TextCollection, TextGroup, Cursor
from vispy.scene.visuals import InfiniteLine, Line from vispy.scene.visuals import InfiniteLine, Line, Rectangle, Text
import gettext
import AppTranslation as fcTranslate
import builtins
import numpy as np import numpy as np
from vispy.geometry import Rect from vispy.geometry import Rect
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base') log = logging.getLogger('base')
@@ -54,8 +62,12 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
if theme == 'white': if theme == 'white':
self.line_color = (0.3, 0.0, 0.0, 1.0) self.line_color = (0.3, 0.0, 0.0, 1.0)
self.rect_hud_color = Color('#0000FF10')
self.text_hud_color = 'black'
else: else:
self.line_color = (0.4, 0.4, 0.4, 1.0) self.line_color = (0.4, 0.4, 0.4, 1.0)
self.rect_hud_color = Color('#80808040')
self.text_hud_color = 'white'
# workspace lines; I didn't use the rectangle because I didn't want to add another VisPy Node, # workspace lines; I didn't use the rectangle because I didn't want to add another VisPy Node,
# which might decrease performance # which might decrease performance
@@ -129,11 +141,6 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
self.h_line = InfiniteLine(pos=0, color=(0.70, 0.3, 0.3, 0.8), vertical=False, self.h_line = InfiniteLine(pos=0, color=(0.70, 0.3, 0.3, 0.8), vertical=False,
parent=self.view.scene) parent=self.view.scene)
# draw a rectangle made out of 4 lines on the canvas to serve as a hint for the work area
# all CNC have a limited workspace
if self.fcapp.defaults['global_workspace'] is True:
self.draw_workspace(workspace_size=self.fcapp.defaults["global_workspaceT"])
self.line_parent = None self.line_parent = None
if self.fcapp.defaults["global_cursor_color_enabled"]: if self.fcapp.defaults["global_cursor_color_enabled"]:
c_color = Color(self.fcapp.defaults["global_cursor_color"]).rgba c_color = Color(self.fcapp.defaults["global_cursor_color"]).rgba
@@ -146,13 +153,61 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
self.cursor_h_line = InfiniteLine(pos=None, color=c_color, vertical=False, self.cursor_h_line = InfiniteLine(pos=None, color=c_color, vertical=False,
parent=self.line_parent) parent=self.line_parent)
# font size
qsettings = QtCore.QSettings("Open Source", "FlatCAM")
if qsettings.contains("hud_font_size"):
fsize = qsettings.value('hud_font_size', type=int)
else:
fsize = 8
# units
units = self.fcapp.defaults["units"].lower()
# coordinates and anchors
height = fsize * 11 # 90. Constant 11 is something that works
width = height * 2 # width is double the height = it is something that works
center_x = (width / 2) + 5
center_y = (height / 2) + 5
# text
self.text_hud = Text('', color=self.text_hud_color, pos=(10, center_y), method='gpu', anchor_x='left',
parent=None)
self.text_hud.font_size = fsize
self.text_hud.text = 'Dx:\t%s [%s]\nDy:\t%s [%s]\n\nX: \t%s [%s]\nY: \t%s [%s]' % \
('0.0000', units, '0.0000', units, '0.0000', units, '0.0000', units)
# rectangle
self.rect_hud = Rectangle(center=(center_x, center_y), width=width, height=height, radius=[5, 5, 5, 5],
border_color=self.rect_hud_color, color=self.rect_hud_color, parent=None)
self.rect_hud.set_gl_state(depth_test=False)
# draw a rectangle made out of 4 lines on the canvas to serve as a hint for the work area
# all CNC have a limited workspace
if self.fcapp.defaults['global_workspace'] is True:
self.draw_workspace(workspace_size=self.fcapp.defaults["global_workspaceT"])
# HUD Display
self.hud_enabled = False
# enable the HUD if it is activated in FlatCAM Preferences
if self.fcapp.defaults['global_hud'] is True:
self.on_toggle_hud(state=True)
# Axis Display
self.axis_enabled = True
# enable Axis
self.on_toggle_axis(state=True)
# enable Grid lines
self.grid_lines_enabled = True
self.shape_collections = [] self.shape_collections = []
self.shape_collection = self.new_shape_collection() self.shape_collection = self.new_shape_collection()
self.fcapp.pool_recreated.connect(self.on_pool_recreated) self.fcapp.pool_recreated.connect(self.on_pool_recreated)
self.text_collection = self.new_text_collection() self.text_collection = self.new_text_collection()
# TODO: Should be setting to show/hide CNC job annotations (global or per object)
self.text_collection.enabled = True self.text_collection.enabled = True
self.c = None self.c = None
@@ -163,6 +218,76 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
self.graph_event_connect('mouse_wheel', self.on_mouse_scroll) self.graph_event_connect('mouse_wheel', self.on_mouse_scroll)
def on_toggle_axis(self, signal=None, state=None):
if state is None:
state = not self.axis_enabled
if state:
self.axis_enabled = True
self.v_line.parent = self.view.scene
self.h_line.parent = self.view.scene
self.fcapp.ui.axis_status_label.setStyleSheet("""
QLabel
{
color: black;
background-color: orange;
}
""")
self.fcapp.inform[str, bool].emit(_("Axis enabled."), False)
else:
self.axis_enabled = False
self.v_line.parent = None
self.h_line.parent = None
self.fcapp.ui.axis_status_label.setStyleSheet("")
self.fcapp.inform[str, bool].emit(_("Axis disabled."), False)
def on_toggle_hud(self, signal=None, state=None):
if state is None:
state = not self.hud_enabled
if state:
self.hud_enabled = True
self.rect_hud.parent = self.view
self.text_hud.parent = self.view
self.fcapp.defaults['global_hud'] = True
self.fcapp.ui.hud_label.setStyleSheet("""
QLabel
{
color: black;
background-color: mediumpurple;
}
""")
self.fcapp.inform[str, bool].emit(_("HUD enabled."), False)
else:
self.hud_enabled = False
self.rect_hud.parent = None
self.text_hud.parent = None
self.fcapp.defaults['global_hud'] = False
self.fcapp.ui.hud_label.setStyleSheet("")
self.fcapp.inform[str, bool].emit(_("HUD disabled."), False)
def on_toggle_grid_lines(self):
state = not self.grid_lines_enabled
if state:
self.grid_lines_enabled = True
self.grid.parent = self.view.scene
self.fcapp.inform[str, bool].emit(_("Grid enabled."), False)
else:
self.grid_lines_enabled = False
self.grid.parent = None
self.fcapp.inform[str, bool].emit(_("Grid disabled."), False)
# HACK: enabling/disabling the cursor seams to somehow update the shapes on screen
# - perhaps is a bug in VisPy implementation
if self.fcapp.grid_status():
self.fcapp.app_cursor.enabled = False
self.fcapp.app_cursor.enabled = True
else:
self.fcapp.app_cursor.enabled = True
self.fcapp.app_cursor.enabled = False
def draw_workspace(self, workspace_size): def draw_workspace(self, workspace_size):
""" """
Draw a rectangular shape on canvas to specify our valid workspace. Draw a rectangular shape on canvas to specify our valid workspace.
@@ -183,17 +308,30 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
a = np.array([(0, 0), (dims[0], 0), (dims[0], dims[1]), (0, dims[1])]) a = np.array([(0, 0), (dims[0], 0), (dims[0], dims[1]), (0, dims[1])])
if not self.workspace_line: # if not self.workspace_line:
self.workspace_line = Line(pos=np.array((a[0], a[1], a[2], a[3], a[0])), color=(0.70, 0.3, 0.3, 0.7), # self.workspace_line = Line(pos=np.array((a[0], a[1], a[2], a[3], a[0])), color=(0.70, 0.3, 0.3, 0.7),
antialias=True, method='agg', parent=self.view.scene) # antialias=True, method='agg', parent=self.view.scene)
else: # else:
self.workspace_line.parent = self.view.scene # self.workspace_line.parent = self.view.scene
self.workspace_line = Line(pos=np.array((a[0], a[1], a[2], a[3], a[0])), color=(0.70, 0.3, 0.3, 0.7),
antialias=True, method='agg', parent=self.view.scene)
self.fcapp.ui.wplace_label.set_value(workspace_size[:3])
self.fcapp.ui.wplace_label.setToolTip(workspace_size)
self.fcapp.ui.wplace_label.setStyleSheet("""
QLabel
{
color: black;
background-color: olivedrab;
}
""")
def delete_workspace(self): def delete_workspace(self):
try: try:
self.workspace_line.parent = None self.workspace_line.parent = None
except Exception: except Exception:
pass pass
self.fcapp.ui.wplace_label.setStyleSheet("")
# redraw the workspace lines on the plot by re adding them to the parent view.scene # redraw the workspace lines on the plot by re adding them to the parent view.scene
def restore_workspace(self): def restore_workspace(self):

View File

@@ -19,8 +19,10 @@ from shapely.geometry import Polygon, LineString, LinearRing
from copy import deepcopy from copy import deepcopy
import logging import logging
import numpy as np
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
# Prevent conflict with Qt5 and above. # Prevent conflict with Qt5 and above.
@@ -29,13 +31,13 @@ mpl_use("Qt5Agg")
from matplotlib.figure import Figure from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.lines import Line2D from matplotlib.lines import Line2D
from matplotlib.offsetbox import AnchoredText
# from matplotlib.widgets import Cursor # from matplotlib.widgets import Cursor
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__: if '_' not in builtins.__dict__:
_ = gettext.gettext _ = gettext.gettext
log = logging.getLogger('base') log = logging.getLogger('base')
@@ -45,9 +47,9 @@ class CanvasCache(QtCore.QObject):
Case story #1: Case story #1:
1) No objects in the project. 1) No objects in the project.
2) Object is created (new_object() emits object_created(obj)). 2) Object is created (app_obj.new_object() emits object_created(obj)).
on_object_created() adds (i) object to collection and emits on_object_created() adds (i) object to collection and emits
(ii) new_object_available() then calls (iii) object.plot() (ii) app_obj.new_object_available() then calls (iii) object.plot()
3) object.plot() creates axes if necessary on 3) object.plot() creates axes if necessary on
app.collection.figure. Then plots on it. app.collection.figure. Then plots on it.
4) Plots on a cache-size canvas (in background). 4) Plots on a cache-size canvas (in background).
@@ -113,7 +115,7 @@ class CanvasCache(QtCore.QObject):
# Continue to update the cache. # Continue to update the cache.
# def on_new_object_available(self): # def on_app_obj.new_object_available(self):
# #
# log.debug("A new object is available. Should plot it!") # log.debug("A new object is available. Should plot it!")
@@ -147,9 +149,13 @@ class PlotCanvasLegacy(QtCore.QObject):
if self.app.defaults['global_theme'] == 'white': if self.app.defaults['global_theme'] == 'white':
theme_color = '#FFFFFF' theme_color = '#FFFFFF'
tick_color = '#000000' tick_color = '#000000'
self.rect_hud_color = '#0000FF10'
self.text_hud_color = '#000000'
else: else:
theme_color = '#000000' theme_color = '#000000'
tick_color = '#FFFFFF' tick_color = '#FFFFFF'
self.rect_hud_color = '#80808040'
self.text_hud_color = '#FFFFFF'
# workspace lines; I didn't use the rectangle because I didn't want to add another VisPy Node, # workspace lines; I didn't use the rectangle because I didn't want to add another VisPy Node,
# which might decrease performance # which might decrease performance
@@ -295,14 +301,163 @@ class PlotCanvasLegacy(QtCore.QObject):
# signal is the mouse is dragging # signal is the mouse is dragging
self.is_dragging = False self.is_dragging = False
self.mouse_press_pos = None
# signal if there is a doubleclick # signal if there is a doubleclick
self.is_dblclk = False self.is_dblclk = False
self.hud_enabled = False
self.text_hud = self.Thud(plotcanvas=self)
# enable Grid lines
self.grid_lines_enabled = True
# draw a rectangle made out of 4 lines on the canvas to serve as a hint for the work area # draw a rectangle made out of 4 lines on the canvas to serve as a hint for the work area
# all CNC have a limited workspace # all CNC have a limited workspace
if self.app.defaults['global_workspace'] is True: if self.app.defaults['global_workspace'] is True:
self.draw_workspace(workspace_size=self.app.defaults["global_workspaceT"]) self.draw_workspace(workspace_size=self.app.defaults["global_workspaceT"])
if self.app.defaults['global_hud'] is True:
self.on_toggle_hud(state=True)
# Axis Display
self.axis_enabled = True
# enable Axis
self.on_toggle_axis(state=True)
def on_toggle_axis(self, signal=None, state=None):
if state is None:
state = not self.axis_enabled
if state:
self.axis_enabled = 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)
self.app.ui.axis_status_label.setStyleSheet("""
QLabel
{
color: black;
background-color: orange;
}
""")
self.app.inform[str, bool].emit(_("Axis enabled."), False)
else:
self.axis_enabled = 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)
self.app.ui.axis_status_label.setStyleSheet("")
self.app.inform[str, bool].emit(_("Axis disabled."), False)
self.canvas.draw()
def on_toggle_hud(self, signal=None, state=None):
if state is None:
state = not self.hud_enabled
if state:
self.hud_enabled = True
self.text_hud.add_artist()
self.app.defaults['global_hud'] = True
self.app.ui.hud_label.setStyleSheet("""
QLabel
{
color: black;
background-color: mediumpurple;
}
""")
self.app.inform[str, bool].emit(_("HUD enabled."), False)
else:
self.hud_enabled = False
self.text_hud.remove_artist()
self.app.defaults['global_hud'] = False
self.app.ui.hud_label.setStyleSheet("")
self.app.inform[str, bool].emit(_("HUD disabled."), False)
self.canvas.draw()
class Thud(QtCore.QObject):
text_changed = QtCore.pyqtSignal(str)
def __init__(self, plotcanvas):
super().__init__()
self.p = plotcanvas
units = self.p.app.defaults['units']
self._text = 'Dx: %s [%s]\nDy: %s [%s]\n\nX: %s [%s]\nY: %s [%s]' % \
('0.0000', units, '0.0000', units, '0.0000', units, '0.0000', units)
# set font size
qsettings = QtCore.QSettings("Open Source", "FlatCAM")
if qsettings.contains("hud_font_size"):
# I multiply with 2.5 because this seems to be the difference between the value taken by the VisPy (3D)
# and Matplotlib (Legacy2D FlatCAM graphic engine)
fsize = int(qsettings.value('hud_font_size', type=int) * 2.5)
else:
fsize = 20
self.hud_holder = AnchoredText(self._text, prop=dict(size=fsize), frameon=True, loc='upper left')
self.hud_holder.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
fc_color = self.p.rect_hud_color[:-2]
fc_alpha = int(self.p.rect_hud_color[-2:], 16) / 255
text_color = self.p.text_hud_color
self.hud_holder.patch.set_facecolor(fc_color)
self.hud_holder.patch.set_alpha(fc_alpha)
self.hud_holder.patch.set_edgecolor((0, 0, 0, 0))
self. hud_holder.txt._text.set_color(color=text_color)
self.text_changed.connect(self.on_text_changed)
@property
def text(self):
return self._text
@text.setter
def text(self, val):
self.text_changed.emit(val)
self._text = val
def on_text_changed(self, txt):
try:
txt = txt.replace('\t', ' ')
self.hud_holder.txt.set_text(txt)
self.p.canvas.draw()
except Exception:
pass
def add_artist(self):
if self.hud_holder not in self.p.axes.artists:
self.p.axes.add_artist(self.hud_holder)
def remove_artist(self):
if self.hud_holder in self.p.axes.artists:
self.p.axes.artists.remove(self.hud_holder)
def on_toggle_grid_lines(self):
state = not self.grid_lines_enabled
if state:
self.grid_lines_enabled = True
self.axes.grid(True)
try:
self.canvas.draw()
except IndexError:
pass
self.app.inform[str, bool].emit(_("Grid enabled."), False)
else:
self.grid_lines_enabled = False
self.axes.grid(False)
try:
self.canvas.draw()
except IndexError:
pass
self.app.inform[str, bool].emit(_("Grid disabled."), False)
def draw_workspace(self, workspace_size): def draw_workspace(self, workspace_size):
""" """
Draw a rectangular shape on canvas to specify our valid workspace. Draw a rectangular shape on canvas to specify our valid workspace.
@@ -329,12 +484,23 @@ class PlotCanvasLegacy(QtCore.QObject):
self.axes.add_line(self.workspace_line) self.axes.add_line(self.workspace_line)
self.canvas.draw() self.canvas.draw()
self.app.ui.wplace_label.set_value(workspace_size[:3])
self.app.ui.wplace_label.setToolTip(workspace_size)
self.fcapp.ui.wplace_label.setStyleSheet("""
QLabel
{
color: black;
background-color: olivedrab;
}
""")
def delete_workspace(self): def delete_workspace(self):
try: try:
self.axes.lines.remove(self.workspace_line) self.axes.lines.remove(self.workspace_line)
self.canvas.draw() self.canvas.draw()
except Exception: except Exception:
pass pass
self.fcapp.ui.wplace_label.setStyleSheet("")
def graph_event_connect(self, event_name, callback): def graph_event_connect(self, event_name, callback):
""" """
@@ -423,7 +589,7 @@ class PlotCanvasLegacy(QtCore.QObject):
if self.big_cursor is False: if self.big_cursor is False:
try: try:
x, y = self.app.geo_editor.snap(x_pos, y_pos) x, y = self.snap(x_pos, y_pos)
# Pointer (snapped) # Pointer (snapped)
# The size of the cursor is multiplied by 1.65 because that value made the cursor similar with the # The size of the cursor is multiplied by 1.65 because that value made the cursor similar with the
@@ -456,7 +622,7 @@ class PlotCanvasLegacy(QtCore.QObject):
pass pass
self.canvas.draw_idle() self.canvas.draw_idle()
self.canvas.blit(self.axes.bbox) self.canvas.blit(self.axes.bbox)
def clear_cursor(self, state): def clear_cursor(self, state):
if state is True: if state is True:
@@ -781,6 +947,7 @@ class PlotCanvasLegacy(QtCore.QObject):
def on_mouse_press(self, event): def on_mouse_press(self, event):
self.is_dragging = True self.is_dragging = True
self.mouse_press_pos = (event.x, event.y)
# Check for middle mouse button press # Check for middle mouse button press
if self.app.defaults["global_pan_button"] == '2': if self.app.defaults["global_pan_button"] == '2':
@@ -806,7 +973,11 @@ class PlotCanvasLegacy(QtCore.QObject):
def on_mouse_release(self, event): def on_mouse_release(self, event):
self.is_dragging = False mouse_release_pos = (event.x, event.y)
delta = 0.05
if abs(self.distance(self.mouse_press_pos, mouse_release_pos)) < delta:
self.is_dragging = False
# Check for middle mouse button release to complete pan procedure # Check for middle mouse button release to complete pan procedure
# Check for middle mouse button press # Check for middle mouse button press
@@ -858,7 +1029,7 @@ class PlotCanvasLegacy(QtCore.QObject):
self.canvas.draw_idle() self.canvas.draw_idle()
# #### Temporary place-holder for cached update ##### # #### Temporary place-holder for cached update #####
self.update_screen_request.emit([0, 0, 0, 0, 0]) # self.update_screen_request.emit([0, 0, 0, 0, 0])
if self.app.defaults["global_cursor_color_enabled"] is True: if self.app.defaults["global_cursor_color_enabled"] is True:
self.draw_cursor(x_pos=x, y_pos=y, color=self.app.cursor_color_3D) self.draw_cursor(x_pos=x, y_pos=y, color=self.app.cursor_color_3D)
@@ -910,6 +1081,59 @@ class PlotCanvasLegacy(QtCore.QObject):
return width / xpx, height / ypx return width / xpx, height / ypx
def snap(self, x, y):
"""
Adjusts coordinates to snap settings.
:param x: Input coordinate X
:param y: Input coordinate Y
:return: Snapped (x, y)
"""
snap_x, snap_y = (x, y)
snap_distance = np.Inf
# ### Grid snap
if self.app.grid_status():
if self.app.defaults["global_gridx"] != 0:
try:
snap_x_ = round(x / float(self.app.defaults["global_gridx"])) * \
float(self.app.defaults["global_gridx"])
except TypeError:
snap_x_ = x
else:
snap_x_ = x
# If the Grid_gap_linked on Grid Toolbar is checked then the snap distance on GridY entry will be ignored
# and it will use the snap distance from GridX entry
if self.app.ui.grid_gap_link_cb.isChecked():
if self.app.defaults["global_gridx"] != 0:
try:
snap_y_ = round(y / float(self.app.defaults["global_gridx"])) * \
float(self.app.defaults["global_gridx"])
except TypeError:
snap_y_ = y
else:
snap_y_ = y
else:
if self.app.defaults["global_gridy"] != 0:
try:
snap_y_ = round(y / float(self.app.defaults["global_gridy"])) * \
float(self.app.defaults["global_gridy"])
except TypeError:
snap_y_ = y
else:
snap_y_ = y
nearest_grid_distance = self.distance((x, y), (snap_x_, snap_y_))
if nearest_grid_distance < snap_distance:
snap_x, snap_y = (snap_x_, snap_y_)
return snap_x, snap_y
@staticmethod
def distance(pt1, pt2):
return np.sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)
class FakeCursor(QtCore.QObject): class FakeCursor(QtCore.QObject):
""" """

View File

@@ -13,6 +13,7 @@ import numpy as np
import vispy.scene as scene import vispy.scene as scene
from vispy.scene.cameras.base_camera import BaseCamera from vispy.scene.cameras.base_camera import BaseCamera
# from vispy.scene.widgets import Widget as VisPyWidget
from vispy.color import Color from vispy.color import Color
import time import time

View File

@@ -13,7 +13,7 @@ from vispy.color import Color
from shapely.geometry import Polygon, LineString, LinearRing from shapely.geometry import Polygon, LineString, LinearRing
import threading import threading
import numpy as np import numpy as np
from flatcamGUI.VisPyTesselators import GLUTess from AppGUI.VisPyTesselators import GLUTess
class FlatCAMLineVisual(LineVisual): class FlatCAMLineVisual(LineVisual):

View File

@@ -0,0 +1,327 @@
from typing import Union, Sequence, List
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QSettings
from AppGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \
FCSliderWithSpinner, FCDoubleSpinner, FloatEntry, FCTextArea
import gettext
import AppTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
class OptionUI:
def __init__(self, option: str):
self.option = option
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
"""
Adds the necessary widget to the grid, starting at the supplied row.
Returns the number of rows used (normally 1)
"""
raise NotImplementedError()
def get_field(self):
raise NotImplementedError()
class BasicOptionUI(OptionUI):
"""Abstract OptionUI that has a label on the left then some other widget on the right"""
def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None] = None,
label_bold: bool = False, label_color: Union[str, None] = None):
super().__init__(option=option)
self.label_text = label_text
self.label_tooltip = label_tooltip
self.label_bold = label_bold
self.label_color = label_color
self.label_widget = self.build_label_widget()
self.entry_widget = self.build_entry_widget()
def build_label_widget(self) -> QtWidgets.QLabel:
fmt = "%s:"
if self.label_bold:
fmt = "<b>%s</b>" % fmt
if self.label_color:
fmt = "<span style=\"color:%s;\">%s</span>" % (self.label_color, fmt)
label_widget = QtWidgets.QLabel(fmt % _(self.label_text))
if self.label_tooltip is not None:
label_widget.setToolTip(_(self.label_tooltip))
return label_widget
def build_entry_widget(self) -> QtWidgets.QWidget:
raise NotImplementedError()
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
grid.addWidget(self.label_widget, row, 0)
grid.addWidget(self.entry_widget, row, 1)
return 1
def get_field(self):
return self.entry_widget
class LineEntryOptionUI(BasicOptionUI):
def build_entry_widget(self) -> QtWidgets.QWidget:
return FCEntry()
# Not sure why this is needed over DoubleSpinnerOptionUI
class FloatEntryOptionUI(BasicOptionUI):
def build_entry_widget(self) -> QtWidgets.QWidget:
return FloatEntry()
class RadioSetOptionUI(BasicOptionUI):
def __init__(self, option: str, label_text: str, choices: list, orientation='horizontal', **kwargs):
self.choices = choices
self.orientation = orientation
super().__init__(option=option, label_text=label_text, **kwargs)
def build_entry_widget(self) -> QtWidgets.QWidget:
return RadioSet(choices=self.choices, orientation=self.orientation)
class TextAreaOptionUI(OptionUI):
def __init__(self, option: str, label_text: str, label_tooltip: str):
super().__init__(option=option)
self.label_text = label_text
self.label_tooltip = label_tooltip
self.label_widget = self.build_label_widget()
self.textarea_widget = self.build_textarea_widget()
def build_label_widget(self):
label = QtWidgets.QLabel("%s:" % _(self.label_text))
label.setToolTip(_(self.label_tooltip))
return label
def build_textarea_widget(self):
textarea = FCTextArea()
textarea.setPlaceholderText(_(self.label_tooltip))
qsettings = QSettings("Open Source", "FlatCAM")
if qsettings.contains("textbox_font_size"):
tb_fsize = qsettings.value('textbox_font_size', type=int)
else:
tb_fsize = 10
font = QtGui.QFont()
font.setPointSize(tb_fsize)
textarea.setFont(font)
return textarea
def get_field(self):
return self.textarea_widget
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
grid.addWidget(self.label_widget, row, 0, 1, 3)
grid.addWidget(self.textarea_widget, row+1, 0, 1, 3)
return 2
class CheckboxOptionUI(OptionUI):
def __init__(self, option: str, label_text: str, label_tooltip: str):
super().__init__(option=option)
self.label_text = label_text
self.label_tooltip = label_tooltip
self.checkbox_widget = self.build_checkbox_widget()
def build_checkbox_widget(self):
checkbox = FCCheckBox('%s' % _(self.label_text))
checkbox.setToolTip(_(self.label_tooltip))
return checkbox
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
grid.addWidget(self.checkbox_widget, row, 0, 1, 3)
return 1
def get_field(self):
return self.checkbox_widget
class ComboboxOptionUI(BasicOptionUI):
def __init__(self, option: str, label_text: str, choices: Sequence, **kwargs):
self.choices = choices
super().__init__(option=option, label_text=label_text, **kwargs)
def build_entry_widget(self):
combo = FCComboBox()
for choice in self.choices:
# don't translate the QCombo items as they are used in QSettings and identified by name
combo.addItem(choice)
return combo
class ColorOptionUI(BasicOptionUI):
def build_entry_widget(self) -> QtWidgets.QWidget:
entry = FCColorEntry()
return entry
class SliderWithSpinnerOptionUI(BasicOptionUI):
def __init__(self, option: str, label_text: str, min_value=0, max_value=100, step=1, **kwargs):
self.min_value = min_value
self.max_value = max_value
self.step = step
super().__init__(option=option, label_text=label_text, **kwargs)
def build_entry_widget(self) -> QtWidgets.QWidget:
entry = FCSliderWithSpinner(min=self.min_value, max=self.max_value, step=self.step)
return entry
class ColorAlphaSliderOptionUI(SliderWithSpinnerOptionUI):
def __init__(self, applies_to: List[str], group, label_text: str, **kwargs):
self.applies_to = applies_to
self.group = group
super().__init__(option="__color_alpha_slider", label_text=label_text, min_value=0, max_value=255, step=1,
**kwargs)
self.get_field().valueChanged.connect(self._on_alpha_change)
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
for index, field in enumerate(self._get_target_fields()):
field.entry.textChanged.connect(lambda value, i=index: self._on_target_change(target_index=i))
return super().add_to_grid(grid, row)
def _get_target_fields(self):
return list(map(lambda n: self.group.option_dict()[n].get_field(), self.applies_to))
def _on_target_change(self, target_index: int):
field = self._get_target_fields()[target_index]
color = field.get_value()
alpha_part = color[7:]
if len(alpha_part) != 2:
return
alpha = int(alpha_part, 16)
if alpha < 0 or alpha > 255 or self.get_field().get_value() == alpha:
return
self.get_field().set_value(alpha)
def _on_alpha_change(self):
alpha = self.get_field().get_value()
for field in self._get_target_fields():
old_value = field.get_value()
new_value = self._modify_color_alpha(old_value, alpha=alpha)
field.set_value(new_value)
@staticmethod
def _modify_color_alpha(color: str, alpha: int):
color_without_alpha = color[:7]
if alpha > 255:
return color_without_alpha + "FF"
elif alpha < 0:
return color_without_alpha + "00"
else:
hexalpha = hex(alpha)[2:]
if len(hexalpha) == 1:
hexalpha = "0" + hexalpha
return color_without_alpha + hexalpha
class SpinnerOptionUI(BasicOptionUI):
def __init__(self, option: str, label_text: str, min_value: int, max_value: int, step: int = 1, **kwargs):
self.min_value = min_value
self.max_value = max_value
self.step = step
super().__init__(option=option, label_text=label_text, **kwargs)
def build_entry_widget(self) -> QtWidgets.QWidget:
entry = FCSpinner()
entry.set_range(self.min_value, self.max_value)
entry.set_step(self.step)
entry.setWrapping(True)
return entry
class DoubleSpinnerOptionUI(BasicOptionUI):
def __init__(self, option: str, label_text: str, step: float, decimals: int, min_value=None, max_value=None,
suffix=None, **kwargs):
self.min_value = min_value
self.max_value = max_value
self.step = step
self.suffix = suffix
self.decimals = decimals
super().__init__(option=option, label_text=label_text, **kwargs)
def build_entry_widget(self) -> QtWidgets.QWidget:
entry = FCDoubleSpinner(suffix=self.suffix)
entry.set_precision(self.decimals)
entry.setSingleStep(self.step)
if self.min_value is None:
self.min_value = entry.minimum()
else:
entry.setMinimum(self.min_value)
if self.max_value is None:
self.max_value = entry.maximum()
else:
entry.setMaximum(self.max_value)
return entry
class HeadingOptionUI(OptionUI):
def __init__(self, label_text: str, label_tooltip: Union[str, None] = None):
super().__init__(option="__heading")
self.label_text = label_text
self.label_tooltip = label_tooltip
def build_heading_widget(self):
heading = QtWidgets.QLabel('<b>%s</b>' % _(self.label_text))
heading.setToolTip(_(self.label_tooltip))
return heading
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
grid.addWidget(self.build_heading_widget(), row, 0, 1, 2)
return 1
def get_field(self):
return None
class SeparatorOptionUI(OptionUI):
def __init__(self):
super().__init__(option="__separator")
@staticmethod
def build_separator_widget():
separator = QtWidgets.QFrame()
separator.setFrameShape(QtWidgets.QFrame.HLine)
separator.setFrameShadow(QtWidgets.QFrame.Sunken)
return separator
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
grid.addWidget(self.build_separator_widget(), row, 0, 1, 2)
return 1
def get_field(self):
return None
class FullWidthButtonOptionUI(OptionUI):
def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None]):
super().__init__(option=option)
self.label_text = label_text
self.label_tooltip = label_tooltip
self.button_widget = self.build_button_widget()
def build_button_widget(self):
button = FCButton(_(self.label_text))
if self.label_tooltip is not None:
button.setToolTip(_(self.label_tooltip))
return button
def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int:
grid.addWidget(self.button_widget, row, 0, 1, 3)
return 1
def get_field(self):
return self.button_widget

View File

@@ -0,0 +1,77 @@
# ##########################################################
# FlatCAM: 2D Post-processing for Manufacturing #
# File by: David Robertson (c) #
# Date: 5/2020 #
# License: MIT Licence #
# ##########################################################
from typing import Dict
from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings
import gettext
import AppTranslation as fcTranslate
import builtins
from AppGUI.preferences.OptionUI import OptionUI
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
settings = QSettings("Open Source", "FlatCAM")
if settings.contains("machinist"):
machinist_setting = settings.value('machinist', type=int)
else:
machinist_setting = 0
class OptionsGroupUI(QtWidgets.QGroupBox):
app = None
def __init__(self, title, parent=None):
# QtGui.QGroupBox.__init__(self, title, parent=parent)
super(OptionsGroupUI, self).__init__()
self.setStyleSheet("""
QGroupBox
{
font-size: 16px;
font-weight: bold;
}
""")
self.layout = QtWidgets.QVBoxLayout()
self.setLayout(self.layout)
def option_dict(self) -> Dict[str, OptionUI]:
# FIXME!
return {}
class OptionsGroupUI2(OptionsGroupUI):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.grid = QtWidgets.QGridLayout()
self.layout.addLayout(self.grid)
self.grid.setColumnStretch(0, 0)
self.grid.setColumnStretch(1, 1)
self.options = self.build_options()
row = 0
for option in self.options:
row += option.add_to_grid(grid=self.grid, row=row)
self.layout.addStretch()
def build_options(self) -> [OptionUI]:
return []
def option_dict(self) -> Dict[str, OptionUI]:
result = {}
for optionui in self.options:
result[optionui.option] = optionui
return result

View File

@@ -0,0 +1,41 @@
from typing import Dict
from PyQt5 import QtWidgets, QtCore
from AppGUI.ColumnarFlowLayout import ColumnarFlowLayout
from AppGUI.preferences.OptionUI import OptionUI
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
class PreferencesSectionUI(QtWidgets.QWidget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.layout = ColumnarFlowLayout() # QtWidgets.QHBoxLayout()
self.setLayout(self.layout)
self.groups = self.build_groups()
for group in self.groups:
group.setMinimumWidth(250)
self.layout.addWidget(group)
def build_groups(self) -> [OptionsGroupUI]:
return []
def option_dict(self) -> Dict[str, OptionUI]:
result = {}
for group in self.groups:
groupoptions = group.option_dict()
result.update(groupoptions)
return result
def build_tab(self):
scroll_area = QtWidgets.QScrollArea()
scroll_area.setWidget(self)
scroll_area.setWidgetResizable(True)
return scroll_area
def get_tab_id(self) -> str:
raise NotImplementedError
def get_tab_label(self) -> str:
raise NotImplementedError

View File

@@ -5,7 +5,7 @@ from defaults import FlatCAMDefaults
import logging import logging
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -29,7 +29,7 @@ class PreferencesUIManager:
:param defaults: a dictionary storage where all the application settings are stored :param defaults: a dictionary storage where all the application settings are stored
:param data_path: a path to the file where all the preferences are stored for persistence :param data_path: a path to the file where all the preferences are stored for persistence
:param ui: reference to the FlatCAMGUI class which constructs the UI :param ui: reference to the MainGUI class which constructs the UI
:param inform: a pyqtSignal used to display information's in the StatusBar of the GUI :param inform: a pyqtSignal used to display information's in the StatusBar of the GUI
""" """
@@ -43,7 +43,7 @@ class PreferencesUIManager:
self.preferences_changed_flag = False self.preferences_changed_flag = False
# when adding entries here read the comments in the method found below named: # when adding entries here read the comments in the method found below named:
# def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) # def app_obj.new_object(self, kind, name, initialize, active=True, fit=True, plot=True)
self.defaults_form_fields = { self.defaults_form_fields = {
# General App # General App
"decimals_inch": self.ui.general_defaults_form.general_app_group.precision_inch_entry, "decimals_inch": self.ui.general_defaults_form.general_app_group.precision_inch_entry,
@@ -123,16 +123,10 @@ class PreferencesUIManager:
"gerber_def_zeros": self.ui.gerber_defaults_form.gerber_gen_group.gerber_zeros_radio, "gerber_def_zeros": self.ui.gerber_defaults_form.gerber_gen_group.gerber_zeros_radio,
"gerber_clean_apertures": self.ui.gerber_defaults_form.gerber_gen_group.gerber_clean_cb, "gerber_clean_apertures": self.ui.gerber_defaults_form.gerber_gen_group.gerber_clean_cb,
"gerber_extra_buffering": self.ui.gerber_defaults_form.gerber_gen_group.gerber_extra_buffering, "gerber_extra_buffering": self.ui.gerber_defaults_form.gerber_gen_group.gerber_extra_buffering,
"gerber_plot_fill": self.ui.gerber_defaults_form.gerber_gen_group.pf_color_entry, "gerber_plot_fill": self.ui.gerber_defaults_form.gerber_gen_group.fill_color_entry,
"gerber_plot_line": self.ui.gerber_defaults_form.gerber_gen_group.pl_color_entry, "gerber_plot_line": self.ui.gerber_defaults_form.gerber_gen_group.line_color_entry,
# Gerber Options # Gerber Options
"gerber_isotooldia": self.ui.gerber_defaults_form.gerber_opt_group.iso_tool_dia_entry,
"gerber_isopasses": self.ui.gerber_defaults_form.gerber_opt_group.iso_width_entry,
"gerber_isooverlap": self.ui.gerber_defaults_form.gerber_opt_group.iso_overlap_entry,
"gerber_combine_passes": self.ui.gerber_defaults_form.gerber_opt_group.combine_passes_cb,
"gerber_iso_scope": self.ui.gerber_defaults_form.gerber_opt_group.iso_scope_radio,
"gerber_milling_type": self.ui.gerber_defaults_form.gerber_opt_group.milling_type_radio,
"gerber_noncoppermargin": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_margin_entry, "gerber_noncoppermargin": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_margin_entry,
"gerber_noncopperrounded": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_rounded_cb, "gerber_noncopperrounded": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_rounded_cb,
"gerber_bboxmargin": self.ui.gerber_defaults_form.gerber_opt_group.bbmargin_entry, "gerber_bboxmargin": self.ui.gerber_defaults_form.gerber_opt_group.bbmargin_entry,
@@ -143,12 +137,6 @@ class PreferencesUIManager:
# "gerber_aperture_scale_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.scale_aperture_entry, # "gerber_aperture_scale_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.scale_aperture_entry,
# "gerber_aperture_buffer_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffer_aperture_entry, # "gerber_aperture_buffer_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffer_aperture_entry,
"gerber_follow": self.ui.gerber_defaults_form.gerber_adv_opt_group.follow_cb, "gerber_follow": self.ui.gerber_defaults_form.gerber_adv_opt_group.follow_cb,
"gerber_tool_type": self.ui.gerber_defaults_form.gerber_adv_opt_group.tool_type_radio,
"gerber_vtipdia": self.ui.gerber_defaults_form.gerber_adv_opt_group.tipdia_spinner,
"gerber_vtipangle": self.ui.gerber_defaults_form.gerber_adv_opt_group.tipangle_spinner,
"gerber_vcutz": self.ui.gerber_defaults_form.gerber_adv_opt_group.cutz_spinner,
"gerber_iso_type": self.ui.gerber_defaults_form.gerber_adv_opt_group.iso_type_radio,
"gerber_buffering": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffering_radio, "gerber_buffering": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffering_radio,
"gerber_simplification": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplify_cb, "gerber_simplification": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplify_cb,
"gerber_simp_tolerance": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplification_tol_spinner, "gerber_simp_tolerance": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplification_tol_spinner,
@@ -180,6 +168,7 @@ class PreferencesUIManager:
# Excellon General # Excellon General
"excellon_plot": self.ui.excellon_defaults_form.excellon_gen_group.plot_cb, "excellon_plot": self.ui.excellon_defaults_form.excellon_gen_group.plot_cb,
"excellon_solid": self.ui.excellon_defaults_form.excellon_gen_group.solid_cb, "excellon_solid": self.ui.excellon_defaults_form.excellon_gen_group.solid_cb,
"excellon_multicolored": self.ui.excellon_defaults_form.excellon_gen_group.multicolored_cb,
"excellon_format_upper_in": "excellon_format_upper_in":
self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry, self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry,
"excellon_format_lower_in": "excellon_format_lower_in":
@@ -221,31 +210,31 @@ class PreferencesUIManager:
"excellon_gcode_type": self.ui.excellon_defaults_form.excellon_opt_group.excellon_gcode_type_radio, "excellon_gcode_type": self.ui.excellon_defaults_form.excellon_opt_group.excellon_gcode_type_radio,
# Excellon Advanced Options # Excellon Advanced Options
"excellon_offset": self.ui.excellon_defaults_form.excellon_adv_opt_group.offset_entry, "excellon_offset": self.ui.excellon_defaults_form.excellon_adv_opt_group.offset_entry,
"excellon_toolchangexy": self.ui.excellon_defaults_form.excellon_adv_opt_group.toolchangexy_entry, "excellon_toolchangexy": self.ui.excellon_defaults_form.excellon_adv_opt_group.toolchangexy_entry,
"excellon_startz": self.ui.excellon_defaults_form.excellon_adv_opt_group.estartz_entry, "excellon_startz": self.ui.excellon_defaults_form.excellon_adv_opt_group.estartz_entry,
"excellon_feedrate_rapid": self.ui.excellon_defaults_form.excellon_adv_opt_group.feedrate_rapid_entry, "excellon_feedrate_rapid": self.ui.excellon_defaults_form.excellon_adv_opt_group.feedrate_rapid_entry,
"excellon_z_pdepth": self.ui.excellon_defaults_form.excellon_adv_opt_group.pdepth_entry, "excellon_z_pdepth": self.ui.excellon_defaults_form.excellon_adv_opt_group.pdepth_entry,
"excellon_feedrate_probe": self.ui.excellon_defaults_form.excellon_adv_opt_group.feedrate_probe_entry, "excellon_feedrate_probe": self.ui.excellon_defaults_form.excellon_adv_opt_group.feedrate_probe_entry,
"excellon_spindledir": self.ui.excellon_defaults_form.excellon_adv_opt_group.spindledir_radio, "excellon_spindledir": self.ui.excellon_defaults_form.excellon_adv_opt_group.spindledir_radio,
"excellon_f_plunge": self.ui.excellon_defaults_form.excellon_adv_opt_group.fplunge_cb, "excellon_f_plunge": self.ui.excellon_defaults_form.excellon_adv_opt_group.fplunge_cb,
"excellon_f_retract": self.ui.excellon_defaults_form.excellon_adv_opt_group.fretract_cb, "excellon_f_retract": self.ui.excellon_defaults_form.excellon_adv_opt_group.fretract_cb,
# Excellon Export # Excellon Export
"excellon_exp_units": self.ui.excellon_defaults_form.excellon_exp_group.excellon_units_radio, "excellon_exp_units": self.ui.excellon_defaults_form.excellon_exp_group.excellon_units_radio,
"excellon_exp_format": self.ui.excellon_defaults_form.excellon_exp_group.format_radio, "excellon_exp_format": self.ui.excellon_defaults_form.excellon_exp_group.format_radio,
"excellon_exp_integer": self.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry, "excellon_exp_integer": self.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry,
"excellon_exp_decimals": self.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry, "excellon_exp_decimals": self.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry,
"excellon_exp_zeros": self.ui.excellon_defaults_form.excellon_exp_group.zeros_radio, "excellon_exp_zeros": self.ui.excellon_defaults_form.excellon_exp_group.zeros_radio,
"excellon_exp_slot_type": self.ui.excellon_defaults_form.excellon_exp_group.slot_type_radio, "excellon_exp_slot_type": self.ui.excellon_defaults_form.excellon_exp_group.slot_type_radio,
# Excellon Editor # Excellon Editor
"excellon_editor_sel_limit": self.ui.excellon_defaults_form.excellon_editor_group.sel_limit_entry, "excellon_editor_sel_limit": self.ui.excellon_defaults_form.excellon_editor_group.sel_limit_entry,
"excellon_editor_newdia": self.ui.excellon_defaults_form.excellon_editor_group.addtool_entry, "excellon_editor_newdia": self.ui.excellon_defaults_form.excellon_editor_group.addtool_entry,
"excellon_editor_array_size": self.ui.excellon_defaults_form.excellon_editor_group.drill_array_size_entry, "excellon_editor_array_size": self.ui.excellon_defaults_form.excellon_editor_group.drill_array_size_entry,
"excellon_editor_lin_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_axis_radio, "excellon_editor_lin_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_axis_radio,
"excellon_editor_lin_pitch": self.ui.excellon_defaults_form.excellon_editor_group.drill_pitch_entry, "excellon_editor_lin_pitch": self.ui.excellon_defaults_form.excellon_editor_group.drill_pitch_entry,
"excellon_editor_lin_angle": self.ui.excellon_defaults_form.excellon_editor_group.drill_angle_entry, "excellon_editor_lin_angle": self.ui.excellon_defaults_form.excellon_editor_group.drill_angle_entry,
"excellon_editor_circ_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_dir_radio, "excellon_editor_circ_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_dir_radio,
"excellon_editor_circ_angle": "excellon_editor_circ_angle":
self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_angle_entry, self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_angle_entry,
@@ -270,94 +259,117 @@ class PreferencesUIManager:
self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry, self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry,
# Geometry General # Geometry General
"geometry_plot": self.ui.geometry_defaults_form.geometry_gen_group.plot_cb, "geometry_plot": self.ui.geometry_defaults_form.geometry_gen_group.plot_cb,
"geometry_circle_steps": self.ui.geometry_defaults_form.geometry_gen_group.circle_steps_entry, "geometry_multicolored": self.ui.geometry_defaults_form.geometry_gen_group.multicolored_cb,
"geometry_cnctooldia": self.ui.geometry_defaults_form.geometry_gen_group.cnctooldia_entry, "geometry_circle_steps": self.ui.geometry_defaults_form.geometry_gen_group.circle_steps_entry,
"geometry_plot_line": self.ui.geometry_defaults_form.geometry_gen_group.line_color_entry, "geometry_cnctooldia": self.ui.geometry_defaults_form.geometry_gen_group.cnctooldia_entry,
"geometry_plot_line": self.ui.geometry_defaults_form.geometry_gen_group.line_color_entry,
# Geometry Options # Geometry Options
"geometry_cutz": self.ui.geometry_defaults_form.geometry_opt_group.cutz_entry, "geometry_cutz": self.ui.geometry_defaults_form.geometry_opt_group.cutz_entry,
"geometry_travelz": self.ui.geometry_defaults_form.geometry_opt_group.travelz_entry, "geometry_travelz": self.ui.geometry_defaults_form.geometry_opt_group.travelz_entry,
"geometry_feedrate": self.ui.geometry_defaults_form.geometry_opt_group.cncfeedrate_entry, "geometry_feedrate": self.ui.geometry_defaults_form.geometry_opt_group.cncfeedrate_entry,
"geometry_feedrate_z": self.ui.geometry_defaults_form.geometry_opt_group.feedrate_z_entry, "geometry_feedrate_z": self.ui.geometry_defaults_form.geometry_opt_group.feedrate_z_entry,
"geometry_spindlespeed": self.ui.geometry_defaults_form.geometry_opt_group.cncspindlespeed_entry, "geometry_spindlespeed": self.ui.geometry_defaults_form.geometry_opt_group.cncspindlespeed_entry,
"geometry_dwell": self.ui.geometry_defaults_form.geometry_opt_group.dwell_cb, "geometry_dwell": self.ui.geometry_defaults_form.geometry_opt_group.dwell_cb,
"geometry_dwelltime": self.ui.geometry_defaults_form.geometry_opt_group.dwelltime_entry, "geometry_dwelltime": self.ui.geometry_defaults_form.geometry_opt_group.dwelltime_entry,
"geometry_ppname_g": self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb, "geometry_ppname_g": self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb,
"geometry_toolchange": self.ui.geometry_defaults_form.geometry_opt_group.toolchange_cb, "geometry_toolchange": self.ui.geometry_defaults_form.geometry_opt_group.toolchange_cb,
"geometry_toolchangez": self.ui.geometry_defaults_form.geometry_opt_group.toolchangez_entry, "geometry_toolchangez": self.ui.geometry_defaults_form.geometry_opt_group.toolchangez_entry,
"geometry_endz": self.ui.geometry_defaults_form.geometry_opt_group.endz_entry, "geometry_endz": self.ui.geometry_defaults_form.geometry_opt_group.endz_entry,
"geometry_endxy": self.ui.geometry_defaults_form.geometry_opt_group.endxy_entry, "geometry_endxy": self.ui.geometry_defaults_form.geometry_opt_group.endxy_entry,
"geometry_depthperpass": self.ui.geometry_defaults_form.geometry_opt_group.depthperpass_entry, "geometry_depthperpass": self.ui.geometry_defaults_form.geometry_opt_group.depthperpass_entry,
"geometry_multidepth": self.ui.geometry_defaults_form.geometry_opt_group.multidepth_cb, "geometry_multidepth": self.ui.geometry_defaults_form.geometry_opt_group.multidepth_cb,
# Geometry Advanced Options # Geometry Advanced Options
"geometry_toolchangexy": self.ui.geometry_defaults_form.geometry_adv_opt_group.toolchangexy_entry, "geometry_toolchangexy": self.ui.geometry_defaults_form.geometry_adv_opt_group.toolchangexy_entry,
"geometry_startz": self.ui.geometry_defaults_form.geometry_adv_opt_group.gstartz_entry, "geometry_startz": self.ui.geometry_defaults_form.geometry_adv_opt_group.gstartz_entry,
"geometry_feedrate_rapid": self.ui.geometry_defaults_form.geometry_adv_opt_group.feedrate_rapid_entry, "geometry_feedrate_rapid": self.ui.geometry_defaults_form.geometry_adv_opt_group.feedrate_rapid_entry,
"geometry_extracut": self.ui.geometry_defaults_form.geometry_adv_opt_group.extracut_cb, "geometry_extracut": self.ui.geometry_defaults_form.geometry_adv_opt_group.extracut_cb,
"geometry_extracut_length": self.ui.geometry_defaults_form.geometry_adv_opt_group.e_cut_entry, "geometry_extracut_length": self.ui.geometry_defaults_form.geometry_adv_opt_group.e_cut_entry,
"geometry_z_pdepth": self.ui.geometry_defaults_form.geometry_adv_opt_group.pdepth_entry, "geometry_z_pdepth": self.ui.geometry_defaults_form.geometry_adv_opt_group.pdepth_entry,
"geometry_feedrate_probe": self.ui.geometry_defaults_form.geometry_adv_opt_group.feedrate_probe_entry, "geometry_feedrate_probe": self.ui.geometry_defaults_form.geometry_adv_opt_group.feedrate_probe_entry,
"geometry_spindledir": self.ui.geometry_defaults_form.geometry_adv_opt_group.spindledir_radio, "geometry_spindledir": self.ui.geometry_defaults_form.geometry_adv_opt_group.spindledir_radio,
"geometry_f_plunge": self.ui.geometry_defaults_form.geometry_adv_opt_group.fplunge_cb, "geometry_f_plunge": self.ui.geometry_defaults_form.geometry_adv_opt_group.fplunge_cb,
"geometry_segx": self.ui.geometry_defaults_form.geometry_adv_opt_group.segx_entry, "geometry_segx": self.ui.geometry_defaults_form.geometry_adv_opt_group.segx_entry,
"geometry_segy": self.ui.geometry_defaults_form.geometry_adv_opt_group.segy_entry, "geometry_segy": self.ui.geometry_defaults_form.geometry_adv_opt_group.segy_entry,
"geometry_area_exclusion": self.ui.geometry_defaults_form.geometry_adv_opt_group.exclusion_cb, "geometry_area_exclusion": self.ui.geometry_defaults_form.geometry_adv_opt_group.exclusion_cb,
"geometry_area_shape": self.ui.geometry_defaults_form.geometry_adv_opt_group.area_shape_radio, "geometry_area_shape": self.ui.geometry_defaults_form.geometry_adv_opt_group.area_shape_radio,
"geometry_area_strategy": self.ui.geometry_defaults_form.geometry_adv_opt_group.strategy_radio, "geometry_area_strategy": self.ui.geometry_defaults_form.geometry_adv_opt_group.strategy_radio,
"geometry_area_overz": self.ui.geometry_defaults_form.geometry_adv_opt_group.over_z_entry, "geometry_area_overz": self.ui.geometry_defaults_form.geometry_adv_opt_group.over_z_entry,
# Geometry Editor # Geometry Editor
"geometry_editor_sel_limit": self.ui.geometry_defaults_form.geometry_editor_group.sel_limit_entry, "geometry_editor_sel_limit": self.ui.geometry_defaults_form.geometry_editor_group.sel_limit_entry,
"geometry_editor_milling_type": self.ui.geometry_defaults_form.geometry_editor_group.milling_type_radio, "geometry_editor_milling_type": self.ui.geometry_defaults_form.geometry_editor_group.milling_type_radio,
# CNCJob General # CNCJob General
"cncjob_plot": self.ui.cncjob_defaults_form.cncjob_gen_group.plot_cb, "cncjob_plot": self.ui.cncjob_defaults_form.cncjob_gen_group.plot_cb,
"cncjob_plot_kind": self.ui.cncjob_defaults_form.cncjob_gen_group.cncplot_method_radio, "cncjob_plot_kind": self.ui.cncjob_defaults_form.cncjob_gen_group.cncplot_method_radio,
"cncjob_annotation": self.ui.cncjob_defaults_form.cncjob_gen_group.annotation_cb, "cncjob_annotation": self.ui.cncjob_defaults_form.cncjob_gen_group.annotation_cb,
"cncjob_tooldia": self.ui.cncjob_defaults_form.cncjob_gen_group.tooldia_entry, "cncjob_tooldia": self.ui.cncjob_defaults_form.cncjob_gen_group.tooldia_entry,
"cncjob_coords_type": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_type_radio, "cncjob_coords_type": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_type_radio,
"cncjob_coords_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_dec_entry, "cncjob_coords_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_dec_entry,
"cncjob_fr_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.fr_dec_entry, "cncjob_fr_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.fr_dec_entry,
"cncjob_steps_per_circle": self.ui.cncjob_defaults_form.cncjob_gen_group.steps_per_circle_entry, "cncjob_steps_per_circle": self.ui.cncjob_defaults_form.cncjob_gen_group.steps_per_circle_entry,
"cncjob_line_ending": self.ui.cncjob_defaults_form.cncjob_gen_group.line_ending_cb, "cncjob_line_ending": self.ui.cncjob_defaults_form.cncjob_gen_group.line_ending_cb,
"cncjob_plot_line": self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_entry, "cncjob_plot_line": self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_entry,
"cncjob_plot_fill": self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_entry, "cncjob_plot_fill": self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_entry,
"cncjob_travel_line": self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_entry, "cncjob_travel_line": self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_entry,
"cncjob_travel_fill": self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry, "cncjob_travel_fill": self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry,
# CNC Job Options # CNC Job Options
"cncjob_prepend": self.ui.cncjob_defaults_form.cncjob_opt_group.prepend_text, "cncjob_prepend": self.ui.cncjob_defaults_form.cncjob_opt_group.prepend_text,
"cncjob_append": self.ui.cncjob_defaults_form.cncjob_opt_group.append_text, "cncjob_append": self.ui.cncjob_defaults_form.cncjob_opt_group.append_text,
# CNC Job Advanced Options # CNC Job Advanced Options
"cncjob_toolchange_macro": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_text, "cncjob_toolchange_macro": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_text,
"cncjob_toolchange_macro_enable": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_cb, "cncjob_toolchange_macro_enable": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_cb,
"cncjob_annotation_fontsize": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontsize_sp, "cncjob_annotation_fontsize": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontsize_sp,
"cncjob_annotation_fontcolor": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry, "cncjob_annotation_fontcolor": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry,
# Isolation Routing Tool
"tools_iso_tooldia": self.ui.tools_defaults_form.tools_iso_group.tool_dia_entry,
"tools_iso_order": self.ui.tools_defaults_form.tools_iso_group.order_radio,
"tools_iso_tool_type": self.ui.tools_defaults_form.tools_iso_group.tool_type_radio,
"tools_iso_tool_vtipdia": self.ui.tools_defaults_form.tools_iso_group.tipdia_entry,
"tools_iso_tool_vtipangle": self.ui.tools_defaults_form.tools_iso_group.tipangle_entry,
"tools_iso_tool_cutz": self.ui.tools_defaults_form.tools_iso_group.cutz_entry,
"tools_iso_newdia": self.ui.tools_defaults_form.tools_iso_group.newdia_entry,
"tools_iso_passes": self.ui.tools_defaults_form.tools_iso_group.passes_entry,
"tools_iso_overlap": self.ui.tools_defaults_form.tools_iso_group.overlap_entry,
"tools_iso_milling_type": self.ui.tools_defaults_form.tools_iso_group.milling_type_radio,
"tools_iso_follow": self.ui.tools_defaults_form.tools_iso_group.follow_cb,
"tools_iso_isotype": self.ui.tools_defaults_form.tools_iso_group.iso_type_radio,
"tools_iso_rest": self.ui.tools_defaults_form.tools_iso_group.rest_cb,
"tools_iso_combine_passes": self.ui.tools_defaults_form.tools_iso_group.combine_passes_cb,
"tools_iso_isoexcept": self.ui.tools_defaults_form.tools_iso_group.except_cb,
"tools_iso_selection": self.ui.tools_defaults_form.tools_iso_group.select_combo,
"tools_iso_area_shape": self.ui.tools_defaults_form.tools_iso_group.area_shape_radio,
"tools_iso_plotting": self.ui.tools_defaults_form.tools_iso_group.plotting_radio,
# NCC Tool # NCC Tool
"tools_ncctools": self.ui.tools_defaults_form.tools_ncc_group.ncc_tool_dia_entry, "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_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_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_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_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_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_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_nccrest": 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_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_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_nccref": 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_ncc_area_shape": self.ui.tools_defaults_form.tools_ncc_group.area_shape_radio,
"tools_ncc_plotting": self.ui.tools_defaults_form.tools_ncc_group.ncc_plotting_radio, "tools_nccmilling_type": self.ui.tools_defaults_form.tools_ncc_group.milling_type_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_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_ncccutz": self.ui.tools_defaults_form.tools_ncc_group.cutz_entry, "tools_ncctipdia": self.ui.tools_defaults_form.tools_ncc_group.tipdia_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_ncctipangle": self.ui.tools_defaults_form.tools_ncc_group.tipangle_entry, "tools_nccnewdia": self.ui.tools_defaults_form.tools_ncc_group.newdia_entry,
"tools_nccnewdia": self.ui.tools_defaults_form.tools_ncc_group.newdia_entry, "tools_ncc_plotting": self.ui.tools_defaults_form.tools_ncc_group.plotting_radio,
# CutOut Tool # CutOut Tool
"tools_cutouttooldia": self.ui.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry, "tools_cutouttooldia": self.ui.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry,
@@ -467,6 +479,12 @@ class PreferencesUIManager:
"tools_solderpaste_pp": self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo, "tools_solderpaste_pp": self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo,
"tools_sub_close_paths": self.ui.tools_defaults_form.tools_sub_group.close_paths_cb, "tools_sub_close_paths": self.ui.tools_defaults_form.tools_sub_group.close_paths_cb,
# Corner Markers Tool
"tools_corners_thickness": self.ui.tools_defaults_form.tools_corners_group.thick_entry,
"tools_corners_length": self.ui.tools_defaults_form.tools_corners_group.l_entry,
"tools_corners_margin": self.ui.tools_defaults_form.tools_corners_group.margin_entry,
# ####################################################################################################### # #######################################################################################################
# ########################################## TOOLS 2 #################################################### # ########################################## TOOLS 2 ####################################################
# ####################################################################################################### # #######################################################################################################
@@ -650,7 +668,7 @@ class PreferencesUIManager:
def show_preferences_gui(self): def show_preferences_gui(self):
""" """
Called to initialize and show the Preferences GUI Called to initialize and show the Preferences AppGUI
:return: None :return: None
""" """
@@ -719,7 +737,7 @@ class PreferencesUIManager:
self.ui.fa_scroll_area.setWidget(fa_form) self.ui.fa_scroll_area.setWidget(fa_form)
fa_form.show() fa_form.show()
# Initialize the color box's color in Preferences -> Global -> Colo # Initialize the color box's color in Preferences -> Global -> Colors
self.__init_color_pickers() self.__init_color_pickers()
# Button handlers # Button handlers
@@ -732,167 +750,90 @@ class PreferencesUIManager:
def __init_color_pickers(self): def __init_color_pickers(self):
# Init Gerber Plot Colors # Init Gerber Plot Colors
self.ui.gerber_defaults_form.gerber_gen_group.pf_color_entry.set_value(self.defaults['gerber_plot_fill']) self.ui.gerber_defaults_form.gerber_gen_group.fill_color_entry.set_value(self.defaults['gerber_plot_fill'])
self.ui.gerber_defaults_form.gerber_gen_group.pf_color_button.setStyleSheet( self.ui.gerber_defaults_form.gerber_gen_group.line_color_entry.set_value(self.defaults['gerber_plot_line'])
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['gerber_plot_fill'])[:7])
self.ui.gerber_defaults_form.gerber_gen_group.pf_color_alpha_spinner.set_value(
int(self.defaults['gerber_plot_fill'][7:9], 16))
self.ui.gerber_defaults_form.gerber_gen_group.pf_color_alpha_slider.setValue(
int(self.defaults['gerber_plot_fill'][7:9], 16))
self.ui.gerber_defaults_form.gerber_gen_group.pl_color_entry.set_value(self.defaults['gerber_plot_line']) self.ui.gerber_defaults_form.gerber_gen_group.gerber_alpha_entry.set_value(
self.ui.gerber_defaults_form.gerber_gen_group.pl_color_button.setStyleSheet( int(self.defaults['gerber_plot_fill'][7:9], 16)) # alpha
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['gerber_plot_line'])[:7])
# Init Excellon Plot Colors # Init Excellon Plot Colors
self.ui.excellon_defaults_form.excellon_gen_group.fill_color_entry.set_value( self.ui.excellon_defaults_form.excellon_gen_group.fill_color_entry.set_value(
self.defaults['excellon_plot_fill']) self.defaults['excellon_plot_fill'])
self.ui.excellon_defaults_form.excellon_gen_group.fill_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['excellon_plot_fill'])[:7])
self.ui.excellon_defaults_form.excellon_gen_group.color_alpha_spinner.set_value(
int(self.defaults['excellon_plot_fill'][7:9], 16))
self.ui.excellon_defaults_form.excellon_gen_group.color_alpha_slider.setValue(
int(self.defaults['excellon_plot_fill'][7:9], 16))
self.ui.excellon_defaults_form.excellon_gen_group.line_color_entry.set_value( self.ui.excellon_defaults_form.excellon_gen_group.line_color_entry.set_value(
self.defaults['excellon_plot_line']) self.defaults['excellon_plot_line'])
self.ui.excellon_defaults_form.excellon_gen_group.line_color_button.setStyleSheet(
"background-color:%s;" self.ui.excellon_defaults_form.excellon_gen_group.excellon_alpha_entry.set_value(
"border-color: dimgray" % str(self.defaults['excellon_plot_line'])[:7]) int(self.defaults['excellon_plot_fill'][7:9], 16))
# Init Geometry Plot Colors # Init Geometry Plot Colors
self.ui.geometry_defaults_form.geometry_gen_group.line_color_entry.set_value( self.ui.geometry_defaults_form.geometry_gen_group.line_color_entry.set_value(
self.defaults['geometry_plot_line']) self.defaults['geometry_plot_line'])
self.ui.geometry_defaults_form.geometry_gen_group.line_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['geometry_plot_line'])[:7])
# Init CNCJob Travel Line Colors # Init CNCJob Travel Line Colors
self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry.set_value( self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry.set_value(
self.defaults['cncjob_travel_fill']) self.defaults['cncjob_travel_fill'])
self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['cncjob_travel_fill'])[:7])
self.ui.cncjob_defaults_form.cncjob_gen_group.tcolor_alpha_spinner.set_value(
int(self.defaults['cncjob_travel_fill'][7:9], 16))
self.ui.cncjob_defaults_form.cncjob_gen_group.tcolor_alpha_slider.setValue(
int(self.defaults['cncjob_travel_fill'][7:9], 16))
self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_entry.set_value( self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_entry.set_value(
self.defaults['cncjob_travel_line']) self.defaults['cncjob_travel_line'])
self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_button.setStyleSheet(
"background-color:%s;" self.ui.cncjob_defaults_form.cncjob_gen_group.cncjob_alpha_entry.set_value(
"border-color: dimgray" % str(self.defaults['cncjob_travel_line'])[:7]) int(self.defaults['cncjob_travel_fill'][7:9], 16)) # alpha
# Init CNCJob Plot Colors # Init CNCJob Plot Colors
self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_entry.set_value( self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_entry.set_value(
self.defaults['cncjob_plot_fill']) self.defaults['cncjob_plot_fill'])
self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['cncjob_plot_fill'])[:7])
self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_entry.set_value( self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_entry.set_value(
self.defaults['cncjob_plot_line']) self.defaults['cncjob_plot_line'])
self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['cncjob_plot_line'])[:7])
# Init Left-Right Selection colors # Init Left-Right Selection colors
self.ui.general_defaults_form.general_gui_group.sf_color_entry.set_value(self.defaults['global_sel_fill']) self.ui.general_defaults_form.general_gui_group.sf_color_entry.set_value(self.defaults['global_sel_fill'])
self.ui.general_defaults_form.general_gui_group.sf_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['global_sel_fill'])[:7])
self.ui.general_defaults_form.general_gui_group.sf_color_alpha_spinner.set_value(
int(self.defaults['global_sel_fill'][7:9], 16))
self.ui.general_defaults_form.general_gui_group.sf_color_alpha_slider.setValue(
int(self.defaults['global_sel_fill'][7:9], 16))
self.ui.general_defaults_form.general_gui_group.sl_color_entry.set_value(self.defaults['global_sel_line']) self.ui.general_defaults_form.general_gui_group.sl_color_entry.set_value(self.defaults['global_sel_line'])
self.ui.general_defaults_form.general_gui_group.sl_color_button.setStyleSheet(
"background-color:%s;" self.ui.general_defaults_form.general_gui_group.left_right_alpha_entry.set_value(
"border-color: dimgray" % str(self.defaults['global_sel_line'])[:7]) int(self.defaults['global_sel_fill'][7:9], 16))
# Init Right-Left Selection colors # Init Right-Left Selection colors
self.ui.general_defaults_form.general_gui_group.alt_sf_color_entry.set_value( self.ui.general_defaults_form.general_gui_group.alt_sf_color_entry.set_value(
self.defaults['global_alt_sel_fill']) self.defaults['global_alt_sel_fill'])
self.ui.general_defaults_form.general_gui_group.alt_sf_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['global_alt_sel_fill'])[:7])
self.ui.general_defaults_form.general_gui_group.alt_sf_color_alpha_spinner.set_value(
int(self.defaults['global_sel_fill'][7:9], 16))
self.ui.general_defaults_form.general_gui_group.alt_sf_color_alpha_slider.setValue(
int(self.defaults['global_sel_fill'][7:9], 16))
self.ui.general_defaults_form.general_gui_group.alt_sl_color_entry.set_value( self.ui.general_defaults_form.general_gui_group.alt_sl_color_entry.set_value(
self.defaults['global_alt_sel_line']) self.defaults['global_alt_sel_line'])
self.ui.general_defaults_form.general_gui_group.alt_sl_color_button.setStyleSheet(
"background-color:%s;" self.ui.general_defaults_form.general_gui_group.right_left_alpha_entry.set_value(
"border-color: dimgray" % str(self.defaults['global_alt_sel_line'])[:7]) int(self.defaults['global_sel_fill'][7:9], 16))
# Init Draw color and Selection Draw Color # Init Draw color and Selection Draw Color
self.ui.general_defaults_form.general_gui_group.draw_color_entry.set_value( self.ui.general_defaults_form.general_gui_group.draw_color_entry.set_value(
self.defaults['global_draw_color']) self.defaults['global_draw_color'])
self.ui.general_defaults_form.general_gui_group.draw_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['global_draw_color'])[:7])
self.ui.general_defaults_form.general_gui_group.sel_draw_color_entry.set_value( self.ui.general_defaults_form.general_gui_group.sel_draw_color_entry.set_value(
self.defaults['global_sel_draw_color']) self.defaults['global_sel_draw_color'])
self.ui.general_defaults_form.general_gui_group.sel_draw_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['global_sel_draw_color'])[:7])
# Init Project Items color # Init Project Items color
self.ui.general_defaults_form.general_gui_group.proj_color_entry.set_value( self.ui.general_defaults_form.general_gui_group.proj_color_entry.set_value(
self.defaults['global_proj_item_color']) self.defaults['global_proj_item_color'])
self.ui.general_defaults_form.general_gui_group.proj_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['global_proj_item_color'])[:7])
# Init Project Disabled Items color # Init Project Disabled Items color
self.ui.general_defaults_form.general_gui_group.proj_color_dis_entry.set_value( self.ui.general_defaults_form.general_gui_group.proj_color_dis_entry.set_value(
self.defaults['global_proj_item_dis_color']) self.defaults['global_proj_item_dis_color'])
self.ui.general_defaults_form.general_gui_group.proj_color_dis_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['global_proj_item_dis_color'])[:7])
# Init Project Disabled Items color # Init Mouse Cursor color
self.ui.general_defaults_form.general_app_set_group.mouse_cursor_entry.set_value( self.ui.general_defaults_form.general_app_set_group.mouse_cursor_entry.set_value(
self.defaults['global_cursor_color']) self.defaults['global_cursor_color'])
self.ui.general_defaults_form.general_app_set_group.mouse_cursor_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['global_cursor_color'])[:7])
# Init the Annotation CNC Job color # Init the Annotation CNC Job color
self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry.set_value( self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry.set_value(
self.defaults['cncjob_annotation_fontcolor']) self.defaults['cncjob_annotation_fontcolor'])
self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['cncjob_annotation_fontcolor'])[:7])
# Init the Tool Film color # Init the Tool Film color
self.ui.tools_defaults_form.tools_film_group.film_color_entry.set_value( self.ui.tools_defaults_form.tools_film_group.film_color_entry.set_value(
self.defaults['tools_film_color']) self.defaults['tools_film_color'])
self.ui.tools_defaults_form.tools_film_group.film_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['tools_film_color'])[:7]
)
# Init the Tool QRCode colors # Init the Tool QRCode colors
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_entry.set_value( self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_entry.set_value(
self.defaults['tools_qrcode_fill_color']) self.defaults['tools_qrcode_fill_color'])
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['tools_qrcode_fill_color'])[:7])
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_entry.set_value( self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_entry.set_value(
self.defaults['tools_qrcode_back_color']) self.defaults['tools_qrcode_back_color'])
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_button.setStyleSheet(
"background-color:%s;"
"border-color: dimgray" % str(self.defaults['tools_qrcode_back_color'])[:7])
def on_save_button(self, save_to_file=True): def on_save_button(self, save_to_file=True):
log.debug("on_save_button() --> Applying preferences to file.") log.debug("on_save_button() --> Applying preferences to file.")
@@ -921,12 +862,17 @@ class PreferencesUIManager:
theme = 'white' theme = 'white'
should_restart = False should_restart = False
val = self.ui.general_defaults_form.general_gui_group.theme_radio.get_value() theme_new_val = self.ui.general_defaults_form.general_gui_group.theme_radio.get_value()
if val != theme:
ge = self.defaults["global_graphic_engine"]
ge_val = self.ui.general_defaults_form.general_app_group.ge_radio.get_value()
if theme_new_val != theme or ge != ge_val:
msgbox = QtWidgets.QMessageBox() msgbox = QtWidgets.QMessageBox()
msgbox.setText(_("Are you sure you want to continue?")) msgbox.setText(_("Are you sure you want to continue?"))
msgbox.setWindowTitle(_("Application restart")) msgbox.setWindowTitle(_("Application will restart"))
msgbox.setWindowIcon(QtGui.QIcon(self.ui.app.resource_location + '/warning.png')) msgbox.setWindowIcon(QtGui.QIcon(self.ui.app.resource_location + '/warning.png'))
msgbox.setIcon(QtWidgets.QMessageBox.Question)
bt_yes = msgbox.addButton(_('Yes'), QtWidgets.QMessageBox.YesRole) bt_yes = msgbox.addButton(_('Yes'), QtWidgets.QMessageBox.YesRole)
msgbox.addButton(_('Cancel'), QtWidgets.QMessageBox.NoRole) msgbox.addButton(_('Cancel'), QtWidgets.QMessageBox.NoRole)
@@ -935,15 +881,22 @@ class PreferencesUIManager:
msgbox.exec_() msgbox.exec_()
response = msgbox.clickedButton() response = msgbox.clickedButton()
if response == bt_yes: if theme_new_val != theme:
theme_settings.setValue('theme', val) if response == bt_yes:
theme_settings.setValue('theme', theme_new_val)
# This will write the setting to the platform specific storage. # This will write the setting to the platform specific storage.
del theme_settings del theme_settings
should_restart = True should_restart = True
else:
self.ui.general_defaults_form.general_gui_group.theme_radio.set_value(theme)
else: else:
self.ui.general_defaults_form.general_gui_group.theme_radio.set_value(theme) if response == bt_yes:
self.defaults["global_graphic_engine"] = ge_val
should_restart = True
else:
self.ui.general_defaults_form.general_app_group.ge_radio.set_value(ge)
if save_to_file or should_restart is True: if save_to_file or should_restart is True:
self.save_defaults(silent=False) self.save_defaults(silent=False)
@@ -967,6 +920,10 @@ class PreferencesUIManager:
tb_fsize = self.ui.general_defaults_form.general_app_set_group.textbox_font_size_spinner.get_value() tb_fsize = self.ui.general_defaults_form.general_app_set_group.textbox_font_size_spinner.get_value()
settgs.setValue('textbox_font_size', tb_fsize) settgs.setValue('textbox_font_size', tb_fsize)
# save the HUD font size
hud_fsize = self.ui.general_defaults_form.general_app_set_group.hud_font_size_spinner.get_value()
settgs.setValue('hud_font_size', hud_fsize)
settgs.setValue( settgs.setValue(
'machinist', 'machinist',
1 if self.ui.general_defaults_form.general_app_set_group.machinist_cb.get_value() else 0 1 if self.ui.general_defaults_form.general_app_set_group.machinist_cb.get_value() else 0
@@ -991,10 +948,14 @@ class PreferencesUIManager:
self.preferences_changed_flag = False self.preferences_changed_flag = False
self.ignore_tab_close_event = True self.ignore_tab_close_event = True
# restore stylesheet to default for the statusBar icon
self.ui.pref_status_label.setStyleSheet("")
try: try:
self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.disconnect() self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.disconnect()
except (TypeError, AttributeError): except (TypeError, AttributeError):
pass pass
self.defaults_write_form(source_dict=self.defaults.current_defaults) self.defaults_write_form(source_dict=self.defaults.current_defaults)
self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect( self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect(
lambda: self.ui.app.on_toggle_units(no_pref=False)) lambda: self.ui.app.on_toggle_units(no_pref=False))
@@ -1035,6 +996,7 @@ class PreferencesUIManager:
:return: None :return: None
""" """
self.defaults.report_usage("save_defaults") self.defaults.report_usage("save_defaults")
log.debug("App.PreferencesUIManager.save_defaults()")
if data_path is None: if data_path is None:
data_path = self.data_path data_path = self.data_path
@@ -1071,7 +1033,7 @@ class PreferencesUIManager:
if self.ui.toolbarfile.isVisible(): if self.ui.toolbarfile.isVisible():
tb_status += 1 tb_status += 1
if self.ui.toolbargeo.isVisible(): if self.ui.toolbaredit.isVisible():
tb_status += 2 tb_status += 2
if self.ui.toolbarview.isVisible(): if self.ui.toolbarview.isVisible():
@@ -1089,7 +1051,7 @@ class PreferencesUIManager:
if self.ui.grb_edit_toolbar.isVisible(): if self.ui.grb_edit_toolbar.isVisible():
tb_status += 64 tb_status += 64
if self.ui.snap_toolbar.isVisible(): if self.ui.status_toolbar.isVisible():
tb_status += 128 tb_status += 128
if self.ui.toolbarshell.isVisible(): if self.ui.toolbarshell.isVisible():
@@ -1118,6 +1080,9 @@ class PreferencesUIManager:
if self.ignore_tab_close_event: if self.ignore_tab_close_event:
return return
# restore stylesheet to default for the statusBar icon
self.ui.pref_status_label.setStyleSheet("")
# disconnect # disconnect
for idx in range(self.ui.pref_tab_area.count()): for idx in range(self.ui.pref_tab_area.count()):
for tb in self.ui.pref_tab_area.widget(idx).findChildren(QtCore.QObject): for tb in self.ui.pref_tab_area.widget(idx).findChildren(QtCore.QObject):
@@ -1153,6 +1118,7 @@ class PreferencesUIManager:
"Do you want to save the Preferences?")) "Do you want to save the Preferences?"))
msgbox.setWindowTitle(_("Save Preferences")) msgbox.setWindowTitle(_("Save Preferences"))
msgbox.setWindowIcon(QtGui.QIcon(self.ui.app.resource_location + '/save_as.png')) msgbox.setWindowIcon(QtGui.QIcon(self.ui.app.resource_location + '/save_as.png'))
msgbox.setIcon(QtWidgets.QMessageBox.Question)
bt_yes = msgbox.addButton(_('Yes'), QtWidgets.QMessageBox.YesRole) bt_yes = msgbox.addButton(_('Yes'), QtWidgets.QMessageBox.YesRole)
msgbox.addButton(_('No'), QtWidgets.QMessageBox.NoRole) msgbox.addButton(_('No'), QtWidgets.QMessageBox.NoRole)

View File

@@ -1,6 +1,6 @@
from flatcamGUI.GUIElements import * from AppGUI.GUIElements import *
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins

View File

@@ -1,10 +1,10 @@
from PyQt5 import QtWidgets, QtGui, QtCore from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QSettings, Qt from PyQt5.QtCore import QSettings, Qt
from flatcamGUI.GUIElements import FCTextArea, FCCheckBox, FCComboBox, FCSpinner, FCEntry from AppGUI.GUIElements import FCTextArea, FCCheckBox, FCComboBox, FCSpinner, FCColorEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -158,28 +158,16 @@ class CNCJobAdvOptPrefGroupUI(OptionsGroupUI):
self.annotation_color_label.setToolTip( self.annotation_color_label.setToolTip(
_("Set the font color for the annotation texts.") _("Set the font color for the annotation texts.")
) )
self.annotation_fontcolor_entry = FCEntry() self.annotation_fontcolor_entry = FCColorEntry()
self.annotation_fontcolor_button = QtWidgets.QPushButton()
self.annotation_fontcolor_button.setFixedSize(15, 15)
self.form_box_child = QtWidgets.QHBoxLayout()
self.form_box_child.setContentsMargins(0, 0, 0, 0)
self.form_box_child.addWidget(self.annotation_fontcolor_entry)
self.form_box_child.addWidget(self.annotation_fontcolor_button, alignment=Qt.AlignRight)
self.form_box_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
color_widget = QtWidgets.QWidget()
color_widget.setLayout(self.form_box_child)
grid0.addWidget(self.annotation_color_label, 3, 0) grid0.addWidget(self.annotation_color_label, 3, 0)
grid0.addWidget(color_widget, 3, 1) grid0.addWidget(self.annotation_fontcolor_entry, 3, 1)
grid0.addWidget(QtWidgets.QLabel(''), 3, 2)
grid0.addWidget(QtWidgets.QLabel(''), 3, 2)
self.layout.addStretch() self.layout.addStretch()
self.tc_variable_combo.currentIndexChanged[str].connect(self.on_cnc_custom_parameters) self.tc_variable_combo.currentIndexChanged[str].connect(self.on_cnc_custom_parameters)
self.annotation_fontcolor_entry.editingFinished.connect(self.on_annotation_fontcolor_entry) self.annotation_fontcolor_entry.editingFinished.connect(self.on_annotation_fontcolor_entry)
self.annotation_fontcolor_button.clicked.connect(self.on_annotation_fontcolor_button)
def on_cnc_custom_parameters(self, signal_text): def on_cnc_custom_parameters(self, signal_text):
if signal_text == 'Parameters': if signal_text == 'Parameters':
@@ -189,20 +177,3 @@ class CNCJobAdvOptPrefGroupUI(OptionsGroupUI):
def on_annotation_fontcolor_entry(self): def on_annotation_fontcolor_entry(self):
self.app.defaults['cncjob_annotation_fontcolor'] = self.annotation_fontcolor_entry.get_value() self.app.defaults['cncjob_annotation_fontcolor'] = self.annotation_fontcolor_entry.get_value()
self.annotation_fontcolor_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['cncjob_annotation_fontcolor']))
def on_annotation_fontcolor_button(self):
current_color = QtGui.QColor(self.app.defaults['cncjob_annotation_fontcolor'])
c_dialog = QtWidgets.QColorDialog()
annotation_color = c_dialog.getColor(initial=current_color)
if annotation_color.isValid() is False:
return
self.annotation_fontcolor_button.setStyleSheet("background-color:%s" % str(annotation_color.name()))
new_val_sel = str(annotation_color.name())
self.annotation_fontcolor_entry.set_value(new_val_sel)
self.app.defaults['cncjob_annotation_fontcolor'] = new_val_sel

View File

@@ -1,10 +1,10 @@
from PyQt5 import QtWidgets, QtCore, QtGui from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCSpinner, FCDoubleSpinner, FCEntry from AppGUI.GUIElements import FCCheckBox, RadioSet, FCSpinner, FCDoubleSpinner, FCSliderWithSpinner, FCColorEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -170,17 +170,10 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
self.tline_color_label.setToolTip( self.tline_color_label.setToolTip(
_("Set the travel line color for plotted objects.") _("Set the travel line color for plotted objects.")
) )
self.tline_color_entry = FCEntry() self.tline_color_entry = FCColorEntry()
self.tline_color_button = QtWidgets.QPushButton()
self.tline_color_button.setFixedSize(15, 15)
self.form_box_child_2 = QtWidgets.QHBoxLayout()
self.form_box_child_2.addWidget(self.tline_color_entry)
self.form_box_child_2.addWidget(self.tline_color_button)
self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.tline_color_label, 14, 0) grid0.addWidget(self.tline_color_label, 14, 0)
grid0.addLayout(self.form_box_child_2, 14, 1) grid0.addWidget(self.tline_color_entry, 14, 1)
# Plot Fill Color # Plot Fill Color
self.tfill_color_label = QtWidgets.QLabel('%s:' % _('Fill')) self.tfill_color_label = QtWidgets.QLabel('%s:' % _('Fill'))
@@ -189,38 +182,20 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
"First 6 digits are the color and the last 2\n" "First 6 digits are the color and the last 2\n"
"digits are for alpha (transparency) level.") "digits are for alpha (transparency) level.")
) )
self.tfill_color_entry = FCEntry() self.tfill_color_entry = FCColorEntry()
self.tfill_color_button = QtWidgets.QPushButton()
self.tfill_color_button.setFixedSize(15, 15)
self.form_box_child_1 = QtWidgets.QHBoxLayout()
self.form_box_child_1.addWidget(self.tfill_color_entry)
self.form_box_child_1.addWidget(self.tfill_color_button)
self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.tfill_color_label, 15, 0) grid0.addWidget(self.tfill_color_label, 15, 0)
grid0.addLayout(self.form_box_child_1, 15, 1) grid0.addWidget(self.tfill_color_entry, 15, 1)
# Plot Fill Transparency Level # Plot Fill Transparency Level
self.alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) self.cncjob_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
self.alpha_label.setToolTip( self.cncjob_alpha_label.setToolTip(
_("Set the fill transparency for plotted objects.") _("Set the fill transparency for plotted objects.")
) )
self.tcolor_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) self.cncjob_alpha_entry = FCSliderWithSpinner(0, 255, 1)
self.tcolor_alpha_slider.setMinimum(0)
self.tcolor_alpha_slider.setMaximum(255)
self.tcolor_alpha_slider.setSingleStep(1)
self.tcolor_alpha_spinner = FCSpinner() grid0.addWidget(self.cncjob_alpha_label, 16, 0)
self.tcolor_alpha_spinner.setMinimumWidth(70) grid0.addWidget(self.cncjob_alpha_entry, 16, 1)
self.tcolor_alpha_spinner.set_range(0, 255)
self.form_box_child_3 = QtWidgets.QHBoxLayout()
self.form_box_child_3.addWidget(self.tcolor_alpha_slider)
self.form_box_child_3.addWidget(self.tcolor_alpha_spinner)
grid0.addWidget(self.alpha_label, 16, 0)
grid0.addLayout(self.form_box_child_3, 16, 1)
separator_line = QtWidgets.QFrame() separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShape(QtWidgets.QFrame.HLine)
@@ -228,7 +203,7 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
grid0.addWidget(separator_line, 17, 0, 1, 2) grid0.addWidget(separator_line, 17, 0, 1, 2)
# CNCJob Object Color # CNCJob Object Color
self.cnc_color_label = QtWidgets.QLabel('<b>%s</b>' % _('CNCJob Object Color')) self.cnc_color_label = QtWidgets.QLabel('<b>%s</b>' % _('Object Color'))
grid0.addWidget(self.cnc_color_label, 18, 0, 1, 2) grid0.addWidget(self.cnc_color_label, 18, 0, 1, 2)
# Plot Line Color # Plot Line Color
@@ -236,17 +211,10 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
self.line_color_label.setToolTip( self.line_color_label.setToolTip(
_("Set the color for plotted objects.") _("Set the color for plotted objects.")
) )
self.line_color_entry = FCEntry() self.line_color_entry = FCColorEntry()
self.line_color_button = QtWidgets.QPushButton()
self.line_color_button.setFixedSize(15, 15)
self.form_box_child_2 = QtWidgets.QHBoxLayout()
self.form_box_child_2.addWidget(self.line_color_entry)
self.form_box_child_2.addWidget(self.line_color_button)
self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.line_color_label, 19, 0) grid0.addWidget(self.line_color_label, 19, 0)
grid0.addLayout(self.form_box_child_2, 19, 1) grid0.addWidget(self.line_color_entry, 19, 1)
# Plot Fill Color # Plot Fill Color
self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill')) self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill'))
@@ -255,32 +223,21 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
"First 6 digits are the color and the last 2\n" "First 6 digits are the color and the last 2\n"
"digits are for alpha (transparency) level.") "digits are for alpha (transparency) level.")
) )
self.fill_color_entry = FCEntry() self.fill_color_entry = FCColorEntry()
self.fill_color_button = QtWidgets.QPushButton()
self.fill_color_button.setFixedSize(15, 15)
self.form_box_child_1 = QtWidgets.QHBoxLayout()
self.form_box_child_1.addWidget(self.fill_color_entry)
self.form_box_child_1.addWidget(self.fill_color_button)
self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.fill_color_label, 20, 0) grid0.addWidget(self.fill_color_label, 20, 0)
grid0.addLayout(self.form_box_child_1, 20, 1) grid0.addWidget(self.fill_color_entry, 20, 1)
self.layout.addStretch() self.layout.addStretch()
# Setting plot colors signals # Setting plot colors signals
self.tline_color_entry.editingFinished.connect(self.on_tline_color_entry) self.tline_color_entry.editingFinished.connect(self.on_tline_color_entry)
self.tline_color_button.clicked.connect(self.on_tline_color_button)
self.tfill_color_entry.editingFinished.connect(self.on_tfill_color_entry) self.tfill_color_entry.editingFinished.connect(self.on_tfill_color_entry)
self.tfill_color_button.clicked.connect(self.on_tfill_color_button)
self.tcolor_alpha_spinner.valueChanged.connect(self.on_tcolor_spinner) self.cncjob_alpha_entry.valueChanged.connect(self.on_cncjob_alpha_changed) # alpha
self.tcolor_alpha_slider.valueChanged.connect(self.on_tcolor_slider)
self.line_color_entry.editingFinished.connect(self.on_line_color_entry) self.line_color_entry.editingFinished.connect(self.on_line_color_entry)
self.line_color_button.clicked.connect(self.on_line_color_button)
self.fill_color_entry.editingFinished.connect(self.on_fill_color_entry) self.fill_color_entry.editingFinished.connect(self.on_fill_color_entry)
self.fill_color_button.clicked.connect(self.on_fill_color_button)
# ------------------------------------------------------ # ------------------------------------------------------
# Setting travel colors handlers # Setting travel colors handlers
@@ -288,27 +245,12 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
def on_tfill_color_entry(self): def on_tfill_color_entry(self):
self.app.defaults['cncjob_travel_fill'] = self.tfill_color_entry.get_value()[:7] + \ self.app.defaults['cncjob_travel_fill'] = self.tfill_color_entry.get_value()[:7] + \
self.app.defaults['cncjob_travel_fill'][7:9] self.app.defaults['cncjob_travel_fill'][7:9]
self.tfill_color_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['cncjob_travel_fill'])[:7])
def on_tfill_color_button(self): def on_tline_color_entry(self):
current_color = QtGui.QColor(self.app.defaults['cncjob_travel_fill'][:7]) self.app.defaults['cncjob_travel_line'] = self.tline_color_entry.get_value()[:7] + \
self.app.defaults['cncjob_travel_line'][7:9]
c_dialog = QtWidgets.QColorDialog() def on_cncjob_alpha_changed(self, spinner_value):
plot_fill_color = c_dialog.getColor(initial=current_color)
if plot_fill_color.isValid() is False:
return
self.tfill_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name()))
new_val = str(plot_fill_color.name()) + str(self.app.defaults['cncjob_travel_fill'][7:9])
self.tfill_color_entry.set_value(new_val)
self.app.defaults['cncjob_travel_fill'] = new_val
def on_tcolor_spinner(self):
spinner_value = self.tcolor_alpha_spinner.value()
self.tcolor_alpha_slider.setValue(spinner_value)
self.app.defaults['cncjob_travel_fill'] = \ self.app.defaults['cncjob_travel_fill'] = \
self.app.defaults['cncjob_travel_fill'][:7] + \ self.app.defaults['cncjob_travel_fill'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
@@ -316,74 +258,13 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
self.app.defaults['cncjob_travel_line'][:7] + \ self.app.defaults['cncjob_travel_line'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
def on_tcolor_slider(self):
slider_value = self.tcolor_alpha_slider.value()
self.tcolor_alpha_spinner.setValue(slider_value)
def on_tline_color_entry(self):
self.app.defaults['cncjob_travel_line'] = self.tline_color_entry.get_value()[:7] + \
self.app.defaults['cncjob_travel_line'][7:9]
self.tline_color_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['cncjob_travel_line'])[:7])
def on_tline_color_button(self):
current_color = QtGui.QColor(self.app.defaults['cncjob_travel_line'][:7])
# print(current_color)
c_dialog = QtWidgets.QColorDialog()
plot_line_color = c_dialog.getColor(initial=current_color)
if plot_line_color.isValid() is False:
return
self.tline_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name()))
new_val_line = str(plot_line_color.name()) + str(self.app.defaults['cncjob_travel_line'][7:9])
self.tline_color_entry.set_value(new_val_line)
self.app.defaults['cncjob_travel_line'] = new_val_line
# ------------------------------------------------------ # ------------------------------------------------------
# Setting plot colors handlers # Setting plot colors handlers
# ------------------------------------------------------ # ------------------------------------------------------
def on_fill_color_entry(self): def on_fill_color_entry(self):
self.app.defaults['cncjob_plot_fill'] = self.fill_color_entry.get_value()[:7] + \ self.app.defaults['cncjob_plot_fill'] = self.fill_color_entry.get_value()[:7] + \
self.app.defaults['cncjob_plot_fill'][7:9] self.app.defaults['cncjob_plot_fill'][7:9]
self.fill_color_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['cncjob_plot_fill'])[:7])
def on_fill_color_button(self):
current_color = QtGui.QColor(self.app.defaults['cncjob_plot_fill'][:7])
c_dialog = QtWidgets.QColorDialog()
plot_fill_color = c_dialog.getColor(initial=current_color)
if plot_fill_color.isValid() is False:
return
self.fill_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name()))
new_val = str(plot_fill_color.name()) + str(self.app.defaults['cncjob_plot_fill'][7:9])
self.fill_color_entry.set_value(new_val)
self.app.defaults['cncjob_plot_fill'] = new_val
def on_line_color_entry(self): def on_line_color_entry(self):
self.app.defaults['cncjob_plot_line'] = self.line_color_entry.get_value()[:7] + \ self.app.defaults['cncjob_plot_line'] = self.line_color_entry.get_value()[:7] + \
self.app.defaults['cncjob_plot_line'][7:9] self.app.defaults['cncjob_plot_line'][7:9]
self.line_color_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['cncjob_plot_line'])[:7])
def on_line_color_button(self):
current_color = QtGui.QColor(self.app.defaults['cncjob_plot_line'][:7])
# print(current_color)
c_dialog = QtWidgets.QColorDialog()
plot_line_color = c_dialog.getColor(initial=current_color)
if plot_line_color.isValid() is False:
return
self.line_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name()))
new_val_line = str(plot_line_color.name()) + str(self.app.defaults['cncjob_plot_line'][7:9])
self.line_color_entry.set_value(new_val_line)
self.app.defaults['cncjob_plot_line'] = new_val_line

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtGui from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCTextArea from AppGUI.GUIElements import FCTextArea
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,8 +1,8 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from flatcamGUI.preferences.cncjob.CNCJobAdvOptPrefGroupUI import CNCJobAdvOptPrefGroupUI from AppGUI.preferences.cncjob.CNCJobAdvOptPrefGroupUI import CNCJobAdvOptPrefGroupUI
from flatcamGUI.preferences.cncjob.CNCJobOptPrefGroupUI import CNCJobOptPrefGroupUI from AppGUI.preferences.cncjob.CNCJobOptPrefGroupUI import CNCJobOptPrefGroupUI
from flatcamGUI.preferences.cncjob.CNCJobGenPrefGroupUI import CNCJobGenPrefGroupUI from AppGUI.preferences.cncjob.CNCJobGenPrefGroupUI import CNCJobGenPrefGroupUI
class CNCJobPreferencesUI(QtWidgets.QWidget): class CNCJobPreferencesUI(QtWidgets.QWidget):

View File

@@ -1,10 +1,10 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner, FCEntry, FloatEntry, RadioSet, FCCheckBox from AppGUI.GUIElements import FCDoubleSpinner, RadioSet, FCCheckBox, NumericalEvalTupleEntry, NumericalEvalEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -60,7 +60,7 @@ class ExcellonAdvOptPrefGroupUI(OptionsGroupUI):
toolchange_xy_label.setToolTip( toolchange_xy_label.setToolTip(
_("Toolchange X,Y position.") _("Toolchange X,Y position.")
) )
self.toolchangexy_entry = FCEntry() self.toolchangexy_entry = NumericalEvalTupleEntry(border_color='#0069A9')
grid1.addWidget(toolchange_xy_label, 1, 0) grid1.addWidget(toolchange_xy_label, 1, 0)
grid1.addWidget(self.toolchangexy_entry, 1, 1) grid1.addWidget(self.toolchangexy_entry, 1, 1)
@@ -71,7 +71,7 @@ class ExcellonAdvOptPrefGroupUI(OptionsGroupUI):
_("Height of the tool just after start.\n" _("Height of the tool just after start.\n"
"Delete the value if you don't need this feature.") "Delete the value if you don't need this feature.")
) )
self.estartz_entry = FloatEntry() self.estartz_entry = NumericalEvalEntry(border_color='#0069A9')
grid1.addWidget(startzlabel, 2, 0) grid1.addWidget(startzlabel, 2, 0)
grid1.addWidget(self.estartz_entry, 2, 1) grid1.addWidget(self.estartz_entry, 2, 1)

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet from AppGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,10 +1,10 @@
from PyQt5 import QtWidgets, QtCore from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import RadioSet, FCSpinner from AppGUI.GUIElements import RadioSet, FCSpinner
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -3,10 +3,10 @@ import platform
from PyQt5 import QtWidgets, QtCore, QtGui from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry from AppGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry, FCSliderWithSpinner, FCColorEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -36,22 +36,31 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
grid1 = QtWidgets.QGridLayout() grid1 = QtWidgets.QGridLayout()
self.layout.addLayout(grid1) self.layout.addLayout(grid1)
# Plot CB
self.plot_cb = FCCheckBox(label=_('Plot')) self.plot_cb = FCCheckBox(label=_('Plot'))
self.plot_cb.setToolTip( self.plot_cb.setToolTip(
"Plot (show) this object." "Plot (show) this object."
) )
grid1.addWidget(self.plot_cb, 0, 0) grid1.addWidget(self.plot_cb, 0, 0)
# Solid CB
self.solid_cb = FCCheckBox(label=_('Solid')) self.solid_cb = FCCheckBox(label=_('Solid'))
self.solid_cb.setToolTip( self.solid_cb.setToolTip(
"Plot as solid circles." "Plot as solid circles."
) )
grid1.addWidget(self.solid_cb, 0, 1) grid1.addWidget(self.solid_cb, 0, 1)
# Multicolored CB
self.multicolored_cb = FCCheckBox(label='%s' % _('M-Color'))
self.multicolored_cb.setToolTip(
_("Draw polygons in different colors.")
)
grid1.addWidget(self.multicolored_cb, 0, 2)
separator_line = QtWidgets.QFrame() separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid1.addWidget(separator_line, 1, 0, 1, 2) grid1.addWidget(separator_line, 1, 0, 1, 3)
grid2 = QtWidgets.QGridLayout() grid2 = QtWidgets.QGridLayout()
self.layout.addLayout(grid2) self.layout.addLayout(grid2)
@@ -255,7 +264,7 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
grid2.addWidget(separator_line, 11, 0, 1, 2) grid2.addWidget(separator_line, 11, 0, 1, 2)
# Excellon Object Color # Excellon Object Color
self.gerber_color_label = QtWidgets.QLabel('<b>%s</b>' % _('Excellon Object Color')) self.gerber_color_label = QtWidgets.QLabel('<b>%s</b>' % _('Object Color'))
grid2.addWidget(self.gerber_color_label, 12, 0, 1, 2) grid2.addWidget(self.gerber_color_label, 12, 0, 1, 2)
# Plot Line Color # Plot Line Color
@@ -263,17 +272,10 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
self.line_color_label.setToolTip( self.line_color_label.setToolTip(
_("Set the line color for plotted objects.") _("Set the line color for plotted objects.")
) )
self.line_color_entry = FCEntry() self.line_color_entry = FCColorEntry()
self.line_color_button = QtWidgets.QPushButton()
self.line_color_button.setFixedSize(15, 15)
self.form_box_child_2 = QtWidgets.QHBoxLayout()
self.form_box_child_2.addWidget(self.line_color_entry)
self.form_box_child_2.addWidget(self.line_color_button)
self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid2.addWidget(self.line_color_label, 13, 0) grid2.addWidget(self.line_color_label, 13, 0)
grid2.addLayout(self.form_box_child_2, 13, 1) grid2.addWidget(self.line_color_entry, 13, 1)
# Plot Fill Color # Plot Fill Color
self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill')) self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill'))
@@ -282,38 +284,20 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
"First 6 digits are the color and the last 2\n" "First 6 digits are the color and the last 2\n"
"digits are for alpha (transparency) level.") "digits are for alpha (transparency) level.")
) )
self.fill_color_entry = FCEntry() self.fill_color_entry = FCColorEntry()
self.fill_color_button = QtWidgets.QPushButton()
self.fill_color_button.setFixedSize(15, 15)
self.form_box_child_1 = QtWidgets.QHBoxLayout()
self.form_box_child_1.addWidget(self.fill_color_entry)
self.form_box_child_1.addWidget(self.fill_color_button)
self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid2.addWidget(self.fill_color_label, 14, 0) grid2.addWidget(self.fill_color_label, 14, 0)
grid2.addLayout(self.form_box_child_1, 14, 1) grid2.addWidget(self.fill_color_entry, 14, 1)
# Plot Fill Transparency Level # Plot Fill Transparency Level
self.alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) self.excellon_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
self.alpha_label.setToolTip( self.excellon_alpha_label.setToolTip(
_("Set the fill transparency for plotted objects.") _("Set the fill transparency for plotted objects.")
) )
self.color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) self.excellon_alpha_entry = FCSliderWithSpinner(0, 255, 1)
self.color_alpha_slider.setMinimum(0)
self.color_alpha_slider.setMaximum(255)
self.color_alpha_slider.setSingleStep(1)
self.color_alpha_spinner = FCSpinner() grid2.addWidget(self.excellon_alpha_label, 15, 0)
self.color_alpha_spinner.setMinimumWidth(70) grid2.addWidget(self.excellon_alpha_entry, 15, 1)
self.color_alpha_spinner.set_range(0, 255)
self.form_box_child_3 = QtWidgets.QHBoxLayout()
self.form_box_child_3.addWidget(self.color_alpha_slider)
self.form_box_child_3.addWidget(self.color_alpha_spinner)
grid2.addWidget(self.alpha_label, 15, 0)
grid2.addLayout(self.form_box_child_3, 15, 1)
self.layout.addStretch() self.layout.addStretch()
@@ -333,14 +317,18 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
# Setting plot colors signals # Setting plot colors signals
self.line_color_entry.editingFinished.connect(self.on_line_color_entry) self.line_color_entry.editingFinished.connect(self.on_line_color_entry)
self.line_color_button.clicked.connect(self.on_line_color_button)
self.fill_color_entry.editingFinished.connect(self.on_fill_color_entry) self.fill_color_entry.editingFinished.connect(self.on_fill_color_entry)
self.fill_color_button.clicked.connect(self.on_fill_color_button)
self.color_alpha_spinner.valueChanged.connect(self.on_color_spinner) self.excellon_alpha_entry.valueChanged.connect(self.on_excellon_alpha_changed) # alpha
self.color_alpha_slider.valueChanged.connect(self.on_color_slider)
# Load the defaults values into the Excellon Format and Excellon Zeros fields # Load the defaults values into the Excellon Format and Excellon Zeros fields
self.excellon_defaults_button.clicked.connect(self.on_excellon_defaults_button) self.excellon_defaults_button.clicked.connect(self.on_excellon_defaults_button)
# Make sure that when the Excellon loading parameters are changed, the change is reflected in the
# Export Excellon parameters.
self.update_excellon_cb.stateChanged.connect(self.on_update_exc_export)
# call it once to make sure it is updated at startup
self.on_update_exc_export(state=self.app.defaults["excellon_update"])
def optimization_selection(self): def optimization_selection(self):
if self.excellon_optimization_radio.get_value() == 'M': if self.excellon_optimization_radio.get_value() == 'M':
@@ -354,26 +342,12 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
def on_fill_color_entry(self): def on_fill_color_entry(self):
self.app.defaults['excellon_plot_fill'] = self.fill_color_entry.get_value()[:7] + \ self.app.defaults['excellon_plot_fill'] = self.fill_color_entry.get_value()[:7] + \
self.app.defaults['excellon_plot_fill'][7:9] self.app.defaults['excellon_plot_fill'][7:9]
self.fill_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['excellon_plot_fill'])[:7])
def on_fill_color_button(self): def on_line_color_entry(self):
current_color = QtGui.QColor(self.app.defaults['excellon_plot_fill'][:7]) self.app.defaults['excellon_plot_line'] = self.line_color_entry.get_value()[:7] + \
self.app.defaults['excellon_plot_line'][7:9]
c_dialog = QtWidgets.QColorDialog() def on_excellon_alpha_changed(self, spinner_value):
plot_fill_color = c_dialog.getColor(initial=current_color)
if plot_fill_color.isValid() is False:
return
self.fill_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name()))
new_val = str(plot_fill_color.name()) + str(self.app.defaults['excellon_plot_fill'][7:9])
self.fill_color_entry.set_value(new_val)
self.app.defaults['excellon_plot_fill'] = new_val
def on_color_spinner(self):
spinner_value = self.color_alpha_spinner.value()
self.color_alpha_slider.setValue(spinner_value)
self.app.defaults['excellon_plot_fill'] = \ self.app.defaults['excellon_plot_fill'] = \
self.app.defaults['excellon_plot_fill'][:7] + \ self.app.defaults['excellon_plot_fill'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
@@ -381,31 +355,6 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
self.app.defaults['excellon_plot_line'][:7] + \ self.app.defaults['excellon_plot_line'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
def on_color_slider(self):
slider_value = self.color_alpha_slider.value()
self.color_alpha_spinner.setValue(slider_value)
def on_line_color_entry(self):
self.app.defaults['excellon_plot_line'] = self.line_color_entry.get_value()[:7] + \
self.app.defaults['excellon_plot_line'][7:9]
self.line_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['excellon_plot_line'])[:7])
def on_line_color_button(self):
current_color = QtGui.QColor(self.app.defaults['excellon_plot_line'][:7])
# print(current_color)
c_dialog = QtWidgets.QColorDialog()
plot_line_color = c_dialog.getColor(initial=current_color)
if plot_line_color.isValid() is False:
return
self.line_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name()))
new_val_line = str(plot_line_color.name()) + str(self.app.defaults['excellon_plot_line'][7:9])
self.line_color_entry.set_value(new_val_line)
self.app.defaults['excellon_plot_line'] = new_val_line
def on_excellon_defaults_button(self): def on_excellon_defaults_button(self):
self.app.preferencesUiManager.defaults_form_fields["excellon_format_lower_in"].set_value('4') self.app.preferencesUiManager.defaults_form_fields["excellon_format_lower_in"].set_value('4')
self.app.preferencesUiManager.defaults_form_fields["excellon_format_upper_in"].set_value('2') self.app.preferencesUiManager.defaults_form_fields["excellon_format_upper_in"].set_value('2')
@@ -413,3 +362,105 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
self.app.preferencesUiManager.defaults_form_fields["excellon_format_upper_mm"].set_value('3') self.app.preferencesUiManager.defaults_form_fields["excellon_format_upper_mm"].set_value('3')
self.app.preferencesUiManager.defaults_form_fields["excellon_zeros"].set_value('L') self.app.preferencesUiManager.defaults_form_fields["excellon_zeros"].set_value('L')
self.app.preferencesUiManager.defaults_form_fields["excellon_units"].set_value('INCH') self.app.preferencesUiManager.defaults_form_fields["excellon_units"].set_value('INCH')
def on_update_exc_export(self, state):
"""
This is handling the update of Excellon Export parameters based on the ones in the Excellon General but only
if the update_excellon_cb checkbox is checked
:param state: state of the checkbox whose signals is tied to his slot
:return:
"""
if state:
# first try to disconnect
try:
self.excellon_format_upper_in_entry.returnPressed.disconnect(self.on_excellon_format_changed)
except TypeError:
pass
try:
self.excellon_format_lower_in_entry.returnPressed.disconnect(self.on_excellon_format_changed)
except TypeError:
pass
try:
self.excellon_format_upper_mm_entry.returnPressed.disconnect(self.on_excellon_format_changed)
except TypeError:
pass
try:
self.excellon_format_lower_mm_entry.returnPressed.disconnect(self.on_excellon_format_changed)
except TypeError:
pass
try:
self.excellon_zeros_radio.activated_custom.disconnect(self.on_excellon_zeros_changed)
except TypeError:
pass
try:
self.excellon_units_radio.activated_custom.disconnect(self.on_excellon_zeros_changed)
except TypeError:
pass
# the connect them
self.excellon_format_upper_in_entry.returnPressed.connect(self.on_excellon_format_changed)
self.excellon_format_lower_in_entry.returnPressed.connect(self.on_excellon_format_changed)
self.excellon_format_upper_mm_entry.returnPressed.connect(self.on_excellon_format_changed)
self.excellon_format_lower_mm_entry.returnPressed.connect(self.on_excellon_format_changed)
self.excellon_zeros_radio.activated_custom.connect(self.on_excellon_zeros_changed)
self.excellon_units_radio.activated_custom.connect(self.on_excellon_units_changed)
else:
# disconnect the signals
try:
self.excellon_format_upper_in_entry.returnPressed.disconnect(self.on_excellon_format_changed)
except TypeError:
pass
try:
self.excellon_format_lower_in_entry.returnPressed.disconnect(self.on_excellon_format_changed)
except TypeError:
pass
try:
self.excellon_format_upper_mm_entry.returnPressed.disconnect(self.on_excellon_format_changed)
except TypeError:
pass
try:
self.excellon_format_lower_mm_entry.returnPressed.disconnect(self.on_excellon_format_changed)
except TypeError:
pass
try:
self.excellon_zeros_radio.activated_custom.disconnect(self.on_excellon_zeros_changed)
except TypeError:
pass
try:
self.excellon_units_radio.activated_custom.disconnect(self.on_excellon_zeros_changed)
except TypeError:
pass
def on_excellon_format_changed(self):
"""
Slot activated when the user changes the Excellon format values in Preferences -> Excellon -> Excellon General
:return: None
"""
if self.excellon_units_radio.get_value().upper() == 'METRIC':
self.app.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry.set_value(
self.excellon_format_upper_mm_entry.get_value())
self.app.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry.set_value(
self.excellon_format_lower_mm_entry.get_value())
else:
self.app.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry.set_value(
self.excellon_format_upper_in_entry.get_value())
self.app.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry.set_value(
self.excellon_format_lower_in_entry.get_value())
def on_excellon_zeros_changed(self, val):
"""
Slot activated when the user changes the Excellon zeros values in Preferences -> Excellon -> Excellon General
:return: None
"""
self.app.ui.excellon_defaults_form.excellon_exp_group.zeros_radio.set_value(val + 'Z')
def on_excellon_units_changed(self, val):
"""
Slot activated when the user changes the Excellon unit values in Preferences -> Excellon -> Excellon General
:return: None
"""
self.app.ui.excellon_defaults_form.excellon_exp_group.excellon_units_radio.set_value(val)
self.on_excellon_format_changed()

View File

@@ -1,12 +1,12 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt, QSettings from PyQt5.QtCore import Qt, QSettings
from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, FCEntry, FCSpinner, OptionalInputSection, \ from AppGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, FCEntry, FCSpinner, OptionalInputSection, \
FCComboBox FCComboBox, NumericalEvalTupleEntry
from flatcamGUI.preferences import machinist_setting from AppGUI.preferences import machinist_setting
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -198,7 +198,7 @@ class ExcellonOptPrefGroupUI(OptionsGroupUI):
"If no value is entered then there is no move\n" "If no value is entered then there is no move\n"
"on X,Y plane at the end of the job.") "on X,Y plane at the end of the job.")
) )
self.endxy_entry = FCEntry() self.endxy_entry = NumericalEvalTupleEntry(border_color='#0069A9')
grid2.addWidget(endmove_xy_label, 9, 0) grid2.addWidget(endmove_xy_label, 9, 0)
grid2.addWidget(self.endxy_entry, 9, 1) grid2.addWidget(self.endxy_entry, 9, 1)

View File

@@ -1,14 +1,14 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.preferences.excellon.ExcellonEditorPrefGroupUI import ExcellonEditorPrefGroupUI from AppGUI.preferences.excellon.ExcellonEditorPrefGroupUI import ExcellonEditorPrefGroupUI
from flatcamGUI.preferences.excellon.ExcellonExpPrefGroupUI import ExcellonExpPrefGroupUI from AppGUI.preferences.excellon.ExcellonExpPrefGroupUI import ExcellonExpPrefGroupUI
from flatcamGUI.preferences.excellon.ExcellonAdvOptPrefGroupUI import ExcellonAdvOptPrefGroupUI from AppGUI.preferences.excellon.ExcellonAdvOptPrefGroupUI import ExcellonAdvOptPrefGroupUI
from flatcamGUI.preferences.excellon.ExcellonOptPrefGroupUI import ExcellonOptPrefGroupUI from AppGUI.preferences.excellon.ExcellonOptPrefGroupUI import ExcellonOptPrefGroupUI
from flatcamGUI.preferences.excellon.ExcellonGenPrefGroupUI import ExcellonGenPrefGroupUI from AppGUI.preferences.excellon.ExcellonGenPrefGroupUI import ExcellonGenPrefGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -31,7 +31,7 @@ class ExcellonPreferencesUI(QtWidgets.QWidget):
self.decimals = decimals self.decimals = decimals
self.excellon_gen_group = ExcellonGenPrefGroupUI(decimals=self.decimals) self.excellon_gen_group = ExcellonGenPrefGroupUI(decimals=self.decimals)
self.excellon_gen_group.setMinimumWidth(220) self.excellon_gen_group.setMinimumWidth(240)
self.excellon_opt_group = ExcellonOptPrefGroupUI(decimals=self.decimals) self.excellon_opt_group = ExcellonOptPrefGroupUI(decimals=self.decimals)
self.excellon_opt_group.setMinimumWidth(290) self.excellon_opt_group.setMinimumWidth(290)
self.excellon_exp_group = ExcellonExpPrefGroupUI(decimals=self.decimals) self.excellon_exp_group = ExcellonExpPrefGroupUI(decimals=self.decimals)

View File

@@ -1,13 +1,13 @@
from PyQt5 import QtCore, QtWidgets, QtGui from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCComboBox, RadioSet, OptionalInputSection, FCSpinner, \ from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCComboBox, RadioSet, OptionalInputSection, FCSpinner, \
FCEntry FCColorEntry
from flatcamGUI.preferences import settings from AppGUI.preferences import settings
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -177,14 +177,6 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
{'label': _('Landscape'), 'value': 'l'}, {'label': _('Landscape'), 'value': 'l'},
], stretch=False) ], stretch=False)
self.wks = OptionalInputSection(self.workspace_cb,
[
self.workspace_type_lbl,
self.wk_cb,
self.wk_orientation_label,
self.wk_orientation_radio
])
grid0.addWidget(self.wk_orientation_label, 8, 0) grid0.addWidget(self.wk_orientation_label, 8, 0)
grid0.addWidget(self.wk_orientation_radio, 8, 1) grid0.addWidget(self.wk_orientation_radio, 8, 1)
@@ -201,7 +193,7 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
self.notebook_font_size_label = QtWidgets.QLabel('%s:' % _('Notebook')) self.notebook_font_size_label = QtWidgets.QLabel('%s:' % _('Notebook'))
self.notebook_font_size_label.setToolTip( self.notebook_font_size_label.setToolTip(
_("This sets the font size for the elements found in the Notebook.\n" _("This sets the font size for the elements found in the Notebook.\n"
"The notebook is the collapsible area in the left side of the GUI,\n" "The notebook is the collapsible area in the left side of the AppGUI,\n"
"and include the Project, Selected and Tool tabs.") "and include the Project, Selected and Tool tabs.")
) )
@@ -240,8 +232,8 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
# TextBox Font Size # TextBox Font Size
self.textbox_font_size_label = QtWidgets.QLabel('%s:' % _('Textbox')) self.textbox_font_size_label = QtWidgets.QLabel('%s:' % _('Textbox'))
self.textbox_font_size_label.setToolTip( self.textbox_font_size_label.setToolTip(
_("This sets the font size for the Textbox GUI\n" _("This sets the font size for the Textbox AppGUI\n"
"elements that are used in FlatCAM.") "elements that are used in the application.")
) )
self.textbox_font_size_spinner = FCSpinner() self.textbox_font_size_spinner = FCSpinner()
@@ -257,10 +249,29 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
grid0.addWidget(self.textbox_font_size_label, 13, 0) grid0.addWidget(self.textbox_font_size_label, 13, 0)
grid0.addWidget(self.textbox_font_size_spinner, 13, 1) grid0.addWidget(self.textbox_font_size_spinner, 13, 1)
# HUD Font Size
self.hud_font_size_label = QtWidgets.QLabel('%s:' % _('HUD'))
self.hud_font_size_label.setToolTip(
_("This sets the font size for the Heads Up Display.")
)
self.hud_font_size_spinner = FCSpinner()
self.hud_font_size_spinner.set_range(8, 40)
self.hud_font_size_spinner.setWrapping(True)
qsettings = QSettings("Open Source", "FlatCAM")
if qsettings.contains("hud_font_size"):
self.hud_font_size_spinner.set_value(settings.value('hud_font_size', type=int))
else:
self.hud_font_size_spinner.set_value(8)
grid0.addWidget(self.hud_font_size_label, 14, 0)
grid0.addWidget(self.hud_font_size_spinner, 14, 1)
separator_line = QtWidgets.QFrame() separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid0.addWidget(separator_line, 14, 0, 1, 2) grid0.addWidget(separator_line, 16, 0, 1, 2)
# ----------------------------------------------------------- # -----------------------------------------------------------
# -------------- MOUSE SETTINGS ----------------------------- # -------------- MOUSE SETTINGS -----------------------------
@@ -323,24 +334,16 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
self.mouse_color_label.setToolTip( self.mouse_color_label.setToolTip(
_("Set the color of the mouse cursor.") _("Set the color of the mouse cursor.")
) )
self.mouse_cursor_entry = FCEntry() self.mouse_cursor_entry = FCColorEntry()
self.mouse_cursor_button = QtWidgets.QPushButton()
self.mouse_cursor_button.setFixedSize(15, 15)
self.form_box_child_1 = QtWidgets.QHBoxLayout()
self.form_box_child_1.addWidget(self.mouse_cursor_entry)
self.form_box_child_1.addWidget(self.mouse_cursor_button)
self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.mouse_color_label, 26, 0) grid0.addWidget(self.mouse_color_label, 26, 0)
grid0.addLayout(self.form_box_child_1, 26, 1) grid0.addWidget(self.mouse_cursor_entry, 26, 1)
self.mois = OptionalInputSection( self.mois = OptionalInputSection(
self.mouse_cursor_color_cb, self.mouse_cursor_color_cb,
[ [
self.mouse_color_label, self.mouse_color_label,
self.mouse_cursor_entry, self.mouse_cursor_entry
self.mouse_cursor_button
] ]
) )
# Select mouse pan button # Select mouse pan button
@@ -440,9 +443,7 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
self.layout.addStretch() self.layout.addStretch()
self.mouse_cursor_color_cb.stateChanged.connect(self.on_mouse_cursor_color_enable) self.mouse_cursor_color_cb.stateChanged.connect(self.on_mouse_cursor_color_enable)
self.mouse_cursor_entry.editingFinished.connect(self.on_mouse_cursor_entry) self.mouse_cursor_entry.editingFinished.connect(self.on_mouse_cursor_entry)
self.mouse_cursor_button.clicked.connect(self.on_mouse_cursor_button)
def on_mouse_cursor_color_enable(self, val): def on_mouse_cursor_color_enable(self, val):
if val: if val:
@@ -461,23 +462,4 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
def on_mouse_cursor_entry(self): def on_mouse_cursor_entry(self):
self.app.defaults['global_cursor_color'] = self.mouse_cursor_entry.get_value() self.app.defaults['global_cursor_color'] = self.mouse_cursor_entry.get_value()
self.mouse_cursor_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_cursor_color']))
self.app.cursor_color_3D = self.app.defaults["global_cursor_color"]
def on_mouse_cursor_button(self):
current_color = QtGui.QColor(self.app.defaults['global_cursor_color'])
c_dialog = QtWidgets.QColorDialog()
proj_color = c_dialog.getColor(initial=current_color)
if proj_color.isValid() is False:
return
self.mouse_cursor_button.setStyleSheet("background-color:%s" % str(proj_color.name()))
new_val_sel = str(proj_color.name())
self.mouse_cursor_entry.set_value(new_val_sel)
self.app.defaults['global_cursor_color'] = new_val_sel
self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] self.app.cursor_color_3D = self.app.defaults["global_cursor_color"]

View File

@@ -3,12 +3,12 @@ import sys
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import RadioSet, FCSpinner, FCCheckBox, FCComboBox, FCButton, OptionalInputSection, \ from AppGUI.GUIElements import RadioSet, FCSpinner, FCCheckBox, FCComboBox, FCButton, OptionalInputSection, \
FCDoubleSpinner FCDoubleSpinner
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -380,12 +380,11 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
def on_toggle_shell_from_settings(self, state): def on_toggle_shell_from_settings(self, state):
""" """
Toggle shell: if is visible close it, if it is closed then open it Toggle shell ui: if is visible close it, if it is closed then open it
:return: None :return: None
""" """
self.app.defaults.report_usage("on_toggle_shell_from_settings()")
if state is True: if state is True:
if not self.app.ui.shell_dock.isVisible(): if not self.app.ui.shell_dock.isVisible():
self.app.ui.shell_dock.show() self.app.ui.shell_dock.show()

View File

@@ -0,0 +1,302 @@
from PyQt5 import QtCore
from PyQt5.QtCore import QSettings
from AppGUI.GUIElements import OptionalInputSection
from AppGUI.preferences import settings
from AppGUI.preferences.OptionUI import *
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI2
import gettext
import AppTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
class GeneralAppSettingsGroupUI(OptionsGroupUI2):
def __init__(self, decimals=4, **kwargs):
self.decimals = decimals
self.pagesize = {}
self.pagesize.update(
{
'A0': (841, 1189),
'A1': (594, 841),
'A2': (420, 594),
'A3': (297, 420),
'A4': (210, 297),
'A5': (148, 210),
'A6': (105, 148),
'A7': (74, 105),
'A8': (52, 74),
'A9': (37, 52),
'A10': (26, 37),
'B0': (1000, 1414),
'B1': (707, 1000),
'B2': (500, 707),
'B3': (353, 500),
'B4': (250, 353),
'B5': (176, 250),
'B6': (125, 176),
'B7': (88, 125),
'B8': (62, 88),
'B9': (44, 62),
'B10': (31, 44),
'C0': (917, 1297),
'C1': (648, 917),
'C2': (458, 648),
'C3': (324, 458),
'C4': (229, 324),
'C5': (162, 229),
'C6': (114, 162),
'C7': (81, 114),
'C8': (57, 81),
'C9': (40, 57),
'C10': (28, 40),
# American paper sizes
'LETTER': (8.5, 11),
'LEGAL': (8.5, 14),
'ELEVENSEVENTEEN': (11, 17),
# From https://en.wikipedia.org/wiki/Paper_size
'JUNIOR_LEGAL': (5, 8),
'HALF_LETTER': (5.5, 8),
'GOV_LETTER': (8, 10.5),
'GOV_LEGAL': (8.5, 13),
'LEDGER': (17, 11),
}
)
super().__init__(**kwargs)
self.setTitle(str(_("App Settings")))
qsettings = QSettings("Open Source", "FlatCAM")
self.notebook_font_size_field = self.option_dict()["notebook_font_size"].get_field()
if qsettings.contains("notebook_font_size"):
self.notebook_font_size_field.set_value(qsettings.value('notebook_font_size', type=int))
else:
self.notebook_font_size_field.set_value(12)
self.axis_font_size_field = self.option_dict()["axis_font_size"].get_field()
if qsettings.contains("axis_font_size"):
self.axis_font_size_field.set_value(qsettings.value('axis_font_size', type=int))
else:
self.axis_font_size_field.set_value(8)
self.textbox_font_size_field = self.option_dict()["textbox_font_size"].get_field()
if qsettings.contains("textbox_font_size"):
self.textbox_font_size_field.set_value(settings.value('textbox_font_size', type=int))
else:
self.textbox_font_size_field.set_value(10)
self.workspace_enabled_field = self.option_dict()["global_workspace"].get_field()
self.workspace_type_field = self.option_dict()["global_workspaceT"].get_field()
self.workspace_type_label = self.option_dict()["global_workspaceT"].label_widget
self.workspace_orientation_field = self.option_dict()["global_workspace_orientation"].get_field()
self.workspace_orientation_label = self.option_dict()["global_workspace_orientation"].label_widget
self.wks = OptionalInputSection(self.workspace_enabled_field, [self.workspace_type_label, self.workspace_type_field, self.workspace_orientation_label, self.workspace_orientation_field])
self.mouse_cursor_color_enabled_field = self.option_dict()["global_cursor_color_enabled"].get_field()
self.mouse_cursor_color_field = self.option_dict()["global_cursor_color"].get_field()
self.mouse_cursor_color_label = self.option_dict()["global_cursor_color"].label_widget
self.mois = OptionalInputSection(self.mouse_cursor_color_enabled_field, [self.mouse_cursor_color_label, self.mouse_cursor_color_field])
self.mouse_cursor_color_enabled_field.stateChanged.connect(self.on_mouse_cursor_color_enable)
self.mouse_cursor_color_field.entry.editingFinished.connect(self.on_mouse_cursor_entry)
def build_options(self) -> [OptionUI]:
return [
HeadingOptionUI(label_text="Grid Settings", label_tooltip=None),
DoubleSpinnerOptionUI(
option="global_gridx",
label_text="X value",
label_tooltip="This is the Grid snap value on X axis.",
step=0.1,
decimals=self.decimals
),
DoubleSpinnerOptionUI(
option="global_gridy",
label_text='Y value',
label_tooltip="This is the Grid snap value on Y axis.",
step=0.1,
decimals=self.decimals
),
DoubleSpinnerOptionUI(
option="global_snap_max",
label_text="Snap Max",
label_tooltip="Max. magnet distance",
step=0.1,
decimals=self.decimals
),
SeparatorOptionUI(),
HeadingOptionUI(label_text="Workspace Settings", label_tooltip=None),
CheckboxOptionUI(
option="global_workspace",
label_text="Active",
label_tooltip="Draw a delimiting rectangle on canvas.\n"
"The purpose is to illustrate the limits for our work."
),
ComboboxOptionUI(
option="global_workspaceT",
label_text="Size",
label_tooltip="Select the type of rectangle to be used on canvas,\nas valid workspace.",
choices=list(self.pagesize.keys())
),
RadioSetOptionUI(
option="global_workspace_orientation",
label_text="Orientation",
label_tooltip="Can be:\n- Portrait\n- Landscape",
choices=[
{'label': _('Portrait'), 'value': 'p'},
{'label': _('Landscape'), 'value': 'l'},
]
),
# FIXME enabling OptionalInputSection ??
SeparatorOptionUI(),
HeadingOptionUI(label_text="Font Size", label_tooltip=None),
SpinnerOptionUI(
option="notebook_font_size",
label_text="Notebook",
label_tooltip="This sets the font size for the elements found in the Notebook.\n"
"The notebook is the collapsible area in the left side of the GUI,\n"
"and include the Project, Selected and Tool tabs.",
min_value=8, max_value=40, step=1
),
SpinnerOptionUI(
option="axis_font_size",
label_text="Axis",
label_tooltip="This sets the font size for canvas axis.",
min_value=8, max_value=40, step=1
),
SpinnerOptionUI(
option="textbox_font_size",
label_text="Textbox",
label_tooltip="This sets the font size for the Textbox GUI\n"
"elements that are used in the application.",
min_value=8, max_value=40, step=1
),
SeparatorOptionUI(),
HeadingOptionUI(label_text="Mouse Settings", label_tooltip=None),
RadioSetOptionUI(
option="global_cursor_type",
label_text="Cursor Shape",
label_tooltip="Choose a mouse cursor shape.\n"
"- Small -> with a customizable size.\n"
"- Big -> Infinite lines",
choices=[
{"label": _("Small"), "value": "small"},
{"label": _("Big"), "value": "big"}
]
),
SpinnerOptionUI(
option="global_cursor_size",
label_text="Cursor Size",
label_tooltip="Set the size of the mouse cursor, in pixels.",
min_value=10, max_value=70, step=1
),
SpinnerOptionUI(
option="global_cursor_width",
label_text="Cursor Width",
label_tooltip="Set the line width of the mouse cursor, in pixels.",
min_value=1, max_value=10, step=1
),
CheckboxOptionUI(
option="global_cursor_color_enabled",
label_text="Cursor Color",
label_tooltip="Check this box to color mouse cursor."
),
ColorOptionUI(
option="global_cursor_color",
label_text="Cursor Color",
label_tooltip="Set the color of the mouse cursor."
),
# FIXME enabling of cursor color
RadioSetOptionUI(
option="global_pan_button",
label_text="Pan Button",
label_tooltip="Select the mouse button to use for panning:\n"
"- MMB --> Middle Mouse Button\n"
"- RMB --> Right Mouse Button",
choices=[{'label': _('MMB'), 'value': '3'},
{'label': _('RMB'), 'value': '2'}]
),
RadioSetOptionUI(
option="global_mselect_key",
label_text="Multiple Selection",
label_tooltip="Select the key used for multiple selection.",
choices=[{'label': _('CTRL'), 'value': 'Control'},
{'label': _('SHIFT'), 'value': 'Shift'}]
),
SeparatorOptionUI(),
CheckboxOptionUI(
option="global_delete_confirmation",
label_text="Delete object confirmation",
label_tooltip="When checked the application will ask for user confirmation\n"
"whenever the Delete object(s) event is triggered, either by\n"
"menu shortcut or key shortcut."
),
CheckboxOptionUI(
option="global_open_style",
label_text='"Open" behavior',
label_tooltip="When checked the path for the last saved file is used when saving files,\n"
"and the path for the last opened file is used when opening files.\n\n"
"When unchecked the path for opening files is the one used last: either the\n"
"path for saving files or the path for opening files."
),
CheckboxOptionUI(
option="global_toggle_tooltips",
label_text="Enable ToolTips",
label_tooltip="Check this box if you want to have toolTips displayed\n"
"when hovering with mouse over items throughout the App."
),
CheckboxOptionUI(
option="global_machinist_setting",
label_text="Allow Machinist Unsafe Settings",
label_tooltip="If checked, some of the application settings will be allowed\n"
"to have values that are usually unsafe to use.\n"
"Like Z travel negative values or Z Cut positive values.\n"
"It will applied at the next application start.\n"
"<<WARNING>>: Don't change this unless you know what you are doing !!!"
),
SpinnerOptionUI(
option="global_bookmarks_limit",
label_text="Bookmarks limit",
label_tooltip="The maximum number of bookmarks that may be installed in the menu.\n"
"The number of bookmarks in the bookmark manager may be greater\n"
"but the menu will hold only so much.",
min_value=0, max_value=9999, step=1
),
ComboboxOptionUI(
option="global_activity_icon",
label_text="Activity Icon",
label_tooltip="Select the GIF that show activity when FlatCAM is active.",
choices=['Ball black', 'Ball green', 'Arrow green', 'Eclipse green']
)
]
def on_mouse_cursor_color_enable(self, val):
if val:
self.app.cursor_color_3D = self.app.defaults["global_cursor_color"]
else:
theme_settings = QtCore.QSettings("Open Source", "FlatCAM")
if theme_settings.contains("theme"):
theme = theme_settings.value('theme', type=str)
else:
theme = 'white'
if theme == 'white':
self.app.cursor_color_3D = 'black'
else:
self.app.cursor_color_3D = 'gray'
def on_mouse_cursor_entry(self):
self.app.defaults['global_cursor_color'] = self.mouse_cursor_color_field.get_value()
self.app.cursor_color_3D = self.app.defaults["global_cursor_color"]

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtCore, QtGui from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import QSettings, Qt from PyQt5.QtCore import QSettings, Qt
from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner from AppGUI.GUIElements import RadioSet, FCCheckBox, FCComboBox, FCSliderWithSpinner, FCColorEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -35,7 +35,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
# Theme selection # Theme selection
self.theme_label = QtWidgets.QLabel('%s:' % _('Theme')) self.theme_label = QtWidgets.QLabel('%s:' % _('Theme'))
self.theme_label.setToolTip( self.theme_label.setToolTip(
_("Select a theme for FlatCAM.\n" _("Select a theme for the application.\n"
"It will theme the plot area.") "It will theme the plot area.")
) )
@@ -72,7 +72,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
# Layout selection # Layout selection
self.layout_label = QtWidgets.QLabel('%s:' % _('Layout')) self.layout_label = QtWidgets.QLabel('%s:' % _('Layout'))
self.layout_label.setToolTip( self.layout_label.setToolTip(
_("Select an layout for FlatCAM.\n" _("Select a layout for the application.\n"
"It is applied immediately.") "It is applied immediately.")
) )
self.layout_combo = FCComboBox() self.layout_combo = FCComboBox()
@@ -94,7 +94,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
# Style selection # Style selection
self.style_label = QtWidgets.QLabel('%s:' % _('Style')) self.style_label = QtWidgets.QLabel('%s:' % _('Style'))
self.style_label.setToolTip( self.style_label.setToolTip(
_("Select an style for FlatCAM.\n" _("Select a style for the application.\n"
"It will be applied at the next app start.") "It will be applied at the next app start.")
) )
self.style_combo = FCComboBox() self.style_combo = FCComboBox()
@@ -110,7 +110,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
# Enable High DPI Support # Enable High DPI Support
self.hdpi_cb = FCCheckBox('%s' % _('Activate HDPI Support')) self.hdpi_cb = FCCheckBox('%s' % _('Activate HDPI Support'))
self.hdpi_cb.setToolTip( self.hdpi_cb.setToolTip(
_("Enable High DPI support for FlatCAM.\n" _("Enable High DPI support for the application.\n"
"It will be applied at the next app start.") "It will be applied at the next app start.")
) )
@@ -126,7 +126,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
# Enable Hover box # Enable Hover box
self.hover_cb = FCCheckBox('%s' % _('Display Hover Shape')) self.hover_cb = FCCheckBox('%s' % _('Display Hover Shape'))
self.hover_cb.setToolTip( self.hover_cb.setToolTip(
_("Enable display of a hover shape for FlatCAM objects.\n" _("Enable display of a hover shape for the application objects.\n"
"It is displayed whenever the mouse cursor is hovering\n" "It is displayed whenever the mouse cursor is hovering\n"
"over any kind of not-selected object.") "over any kind of not-selected object.")
) )
@@ -135,7 +135,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
# Enable Selection box # Enable Selection box
self.selection_cb = FCCheckBox('%s' % _('Display Selection Shape')) self.selection_cb = FCCheckBox('%s' % _('Display Selection Shape'))
self.selection_cb.setToolTip( self.selection_cb.setToolTip(
_("Enable the display of a selection shape for FlatCAM objects.\n" _("Enable the display of a selection shape for the application objects.\n"
"It is displayed whenever the mouse selects an object\n" "It is displayed whenever the mouse selects an object\n"
"either by clicking or dragging mouse from left to right or\n" "either by clicking or dragging mouse from left to right or\n"
"right to left.") "right to left.")
@@ -155,17 +155,10 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
self.sl_color_label.setToolTip( self.sl_color_label.setToolTip(
_("Set the line color for the 'left to right' selection box.") _("Set the line color for the 'left to right' selection box.")
) )
self.sl_color_entry = FCEntry() self.sl_color_entry = FCColorEntry()
self.sl_color_button = QtWidgets.QPushButton()
self.sl_color_button.setFixedSize(15, 15)
self.form_box_child_4 = QtWidgets.QHBoxLayout()
self.form_box_child_4.addWidget(self.sl_color_entry)
self.form_box_child_4.addWidget(self.sl_color_button)
self.form_box_child_4.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.sl_color_label, 16, 0) grid0.addWidget(self.sl_color_label, 16, 0)
grid0.addLayout(self.form_box_child_4, 16, 1) grid0.addWidget(self.sl_color_entry, 16, 1)
self.sf_color_label = QtWidgets.QLabel('%s:' % _('Fill')) self.sf_color_label = QtWidgets.QLabel('%s:' % _('Fill'))
self.sf_color_label.setToolTip( self.sf_color_label.setToolTip(
@@ -174,38 +167,20 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
"First 6 digits are the color and the last 2\n" "First 6 digits are the color and the last 2\n"
"digits are for alpha (transparency) level.") "digits are for alpha (transparency) level.")
) )
self.sf_color_entry = FCEntry() self.sf_color_entry = FCColorEntry()
self.sf_color_button = QtWidgets.QPushButton()
self.sf_color_button.setFixedSize(15, 15)
self.form_box_child_5 = QtWidgets.QHBoxLayout()
self.form_box_child_5.addWidget(self.sf_color_entry)
self.form_box_child_5.addWidget(self.sf_color_button)
self.form_box_child_5.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.sf_color_label, 17, 0) grid0.addWidget(self.sf_color_label, 17, 0)
grid0.addLayout(self.form_box_child_5, 17, 1) grid0.addWidget(self.sf_color_entry, 17, 1)
# Plot Selection (left - right) Fill Transparency Level # Plot Selection (left - right) Fill Transparency Level
self.sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) self.left_right_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
self.sf_alpha_label.setToolTip( self.left_right_alpha_label.setToolTip(
_("Set the fill transparency for the 'left to right' selection box.") _("Set the fill transparency for the 'left to right' selection box.")
) )
self.sf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) self.left_right_alpha_entry = FCSliderWithSpinner(0, 255, 1)
self.sf_color_alpha_slider.setMinimum(0)
self.sf_color_alpha_slider.setMaximum(255)
self.sf_color_alpha_slider.setSingleStep(1)
self.sf_color_alpha_spinner = FCSpinner() grid0.addWidget(self.left_right_alpha_label, 18, 0)
self.sf_color_alpha_spinner.setMinimumWidth(70) grid0.addWidget(self.left_right_alpha_entry, 18, 1)
self.sf_color_alpha_spinner.set_range(0, 255)
self.form_box_child_6 = QtWidgets.QHBoxLayout()
self.form_box_child_6.addWidget(self.sf_color_alpha_slider)
self.form_box_child_6.addWidget(self.sf_color_alpha_spinner)
grid0.addWidget(self.sf_alpha_label, 18, 0)
grid0.addLayout(self.form_box_child_6, 18, 1)
separator_line = QtWidgets.QFrame() separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShape(QtWidgets.QFrame.HLine)
@@ -221,17 +196,10 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
self.alt_sl_color_label.setToolTip( self.alt_sl_color_label.setToolTip(
_("Set the line color for the 'right to left' selection box.") _("Set the line color for the 'right to left' selection box.")
) )
self.alt_sl_color_entry = FCEntry() self.alt_sl_color_entry = FCColorEntry()
self.alt_sl_color_button = QtWidgets.QPushButton()
self.alt_sl_color_button.setFixedSize(15, 15)
self.form_box_child_7 = QtWidgets.QHBoxLayout()
self.form_box_child_7.addWidget(self.alt_sl_color_entry)
self.form_box_child_7.addWidget(self.alt_sl_color_button)
self.form_box_child_7.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.alt_sl_color_label, 21, 0) grid0.addWidget(self.alt_sl_color_label, 21, 0)
grid0.addLayout(self.form_box_child_7, 21, 1) grid0.addWidget(self.alt_sl_color_entry, 21, 1)
# Plot Selection (right - left) Fill Color # Plot Selection (right - left) Fill Color
self.alt_sf_color_label = QtWidgets.QLabel('%s:' % _('Fill')) self.alt_sf_color_label = QtWidgets.QLabel('%s:' % _('Fill'))
@@ -241,38 +209,20 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
"First 6 digits are the color and the last 2\n" "First 6 digits are the color and the last 2\n"
"digits are for alpha (transparency) level.") "digits are for alpha (transparency) level.")
) )
self.alt_sf_color_entry = FCEntry() self.alt_sf_color_entry = FCColorEntry()
self.alt_sf_color_button = QtWidgets.QPushButton()
self.alt_sf_color_button.setFixedSize(15, 15)
self.form_box_child_8 = QtWidgets.QHBoxLayout()
self.form_box_child_8.addWidget(self.alt_sf_color_entry)
self.form_box_child_8.addWidget(self.alt_sf_color_button)
self.form_box_child_8.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.alt_sf_color_label, 22, 0) grid0.addWidget(self.alt_sf_color_label, 22, 0)
grid0.addLayout(self.form_box_child_8, 22, 1) grid0.addWidget(self.alt_sf_color_entry, 22, 1)
# Plot Selection (right - left) Fill Transparency Level # Plot Selection (right - left) Fill Transparency Level
self.alt_sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) self.right_left_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
self.alt_sf_alpha_label.setToolTip( self.right_left_alpha_label.setToolTip(
_("Set the fill transparency for selection 'right to left' box.") _("Set the fill transparency for selection 'right to left' box.")
) )
self.alt_sf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) self.right_left_alpha_entry = FCSliderWithSpinner(0, 255, 1)
self.alt_sf_color_alpha_slider.setMinimum(0)
self.alt_sf_color_alpha_slider.setMaximum(255)
self.alt_sf_color_alpha_slider.setSingleStep(1)
self.alt_sf_color_alpha_spinner = FCSpinner() grid0.addWidget(self.right_left_alpha_label, 23, 0)
self.alt_sf_color_alpha_spinner.setMinimumWidth(70) grid0.addWidget(self.right_left_alpha_entry, 23, 1)
self.alt_sf_color_alpha_spinner.set_range(0, 255)
self.form_box_child_9 = QtWidgets.QHBoxLayout()
self.form_box_child_9.addWidget(self.alt_sf_color_alpha_slider)
self.form_box_child_9.addWidget(self.alt_sf_color_alpha_spinner)
grid0.addWidget(self.alt_sf_alpha_label, 23, 0)
grid0.addLayout(self.form_box_child_9, 23, 1)
separator_line = QtWidgets.QFrame() separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShape(QtWidgets.QFrame.HLine)
@@ -291,34 +241,20 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
self.alt_sf_color_label.setToolTip( self.alt_sf_color_label.setToolTip(
_("Set the color for the shape.") _("Set the color for the shape.")
) )
self.draw_color_entry = FCEntry() self.draw_color_entry = FCColorEntry()
self.draw_color_button = QtWidgets.QPushButton()
self.draw_color_button.setFixedSize(15, 15)
self.form_box_child_10 = QtWidgets.QHBoxLayout()
self.form_box_child_10.addWidget(self.draw_color_entry)
self.form_box_child_10.addWidget(self.draw_color_button)
self.form_box_child_10.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.draw_color_label, 26, 0) grid0.addWidget(self.draw_color_label, 26, 0)
grid0.addLayout(self.form_box_child_10, 26, 1) grid0.addWidget(self.draw_color_entry, 26, 1)
# Editor Draw Selection Color # Editor Draw Selection Color
self.sel_draw_color_label = QtWidgets.QLabel('%s:' % _('Selection')) self.sel_draw_color_label = QtWidgets.QLabel('%s:' % _('Selection'))
self.sel_draw_color_label.setToolTip( self.sel_draw_color_label.setToolTip(
_("Set the color of the shape when selected.") _("Set the color of the shape when selected.")
) )
self.sel_draw_color_entry = FCEntry() self.sel_draw_color_entry = FCColorEntry()
self.sel_draw_color_button = QtWidgets.QPushButton()
self.sel_draw_color_button.setFixedSize(15, 15)
self.form_box_child_11 = QtWidgets.QHBoxLayout()
self.form_box_child_11.addWidget(self.sel_draw_color_entry)
self.form_box_child_11.addWidget(self.sel_draw_color_button)
self.form_box_child_11.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.sel_draw_color_label, 27, 0) grid0.addWidget(self.sel_draw_color_label, 27, 0)
grid0.addLayout(self.form_box_child_11, 27, 1) grid0.addWidget(self.sel_draw_color_entry, 27, 1)
separator_line = QtWidgets.QFrame() separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShape(QtWidgets.QFrame.HLine)
@@ -337,34 +273,20 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
self.proj_color_label.setToolTip( self.proj_color_label.setToolTip(
_("Set the color of the items in Project Tab Tree.") _("Set the color of the items in Project Tab Tree.")
) )
self.proj_color_entry = FCEntry() self.proj_color_entry = FCColorEntry()
self.proj_color_button = QtWidgets.QPushButton()
self.proj_color_button.setFixedSize(15, 15)
self.form_box_child_12 = QtWidgets.QHBoxLayout()
self.form_box_child_12.addWidget(self.proj_color_entry)
self.form_box_child_12.addWidget(self.proj_color_button)
self.form_box_child_12.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.proj_color_label, 30, 0) grid0.addWidget(self.proj_color_label, 30, 0)
grid0.addLayout(self.form_box_child_12, 30, 1) grid0.addWidget(self.proj_color_entry, 30, 1)
self.proj_color_dis_label = QtWidgets.QLabel('%s:' % _('Disabled')) self.proj_color_dis_label = QtWidgets.QLabel('%s:' % _('Disabled'))
self.proj_color_dis_label.setToolTip( self.proj_color_dis_label.setToolTip(
_("Set the color of the items in Project Tab Tree,\n" _("Set the color of the items in Project Tab Tree,\n"
"for the case when the items are disabled.") "for the case when the items are disabled.")
) )
self.proj_color_dis_entry = FCEntry() self.proj_color_dis_entry = FCColorEntry()
self.proj_color_dis_button = QtWidgets.QPushButton()
self.proj_color_dis_button.setFixedSize(15, 15)
self.form_box_child_13 = QtWidgets.QHBoxLayout()
self.form_box_child_13.addWidget(self.proj_color_dis_entry)
self.form_box_child_13.addWidget(self.proj_color_dis_button)
self.form_box_child_13.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.proj_color_dis_label, 31, 0) grid0.addWidget(self.proj_color_dis_label, 31, 0)
grid0.addLayout(self.form_box_child_13, 31, 1) grid0.addWidget(self.proj_color_dis_entry, 31, 1)
# Project autohide CB # Project autohide CB
self.project_autohide_cb = FCCheckBox(label=_('Project AutoHide')) self.project_autohide_cb = FCCheckBox(label=_('Project AutoHide'))
@@ -387,32 +309,22 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
# Setting selection (left - right) colors signals # Setting selection (left - right) colors signals
self.sf_color_entry.editingFinished.connect(self.on_sf_color_entry) self.sf_color_entry.editingFinished.connect(self.on_sf_color_entry)
self.sf_color_button.clicked.connect(self.on_sf_color_button)
self.sf_color_alpha_spinner.valueChanged.connect(self.on_sf_color_spinner)
self.sf_color_alpha_slider.valueChanged.connect(self.on_sf_color_slider)
self.sl_color_entry.editingFinished.connect(self.on_sl_color_entry) self.sl_color_entry.editingFinished.connect(self.on_sl_color_entry)
self.sl_color_button.clicked.connect(self.on_sl_color_button)
self.left_right_alpha_entry.valueChanged.connect(self.on_left_right_alpha_changed) # alpha
# Setting selection (right - left) colors signals # Setting selection (right - left) colors signals
self.alt_sf_color_entry.editingFinished.connect(self.on_alt_sf_color_entry) self.alt_sf_color_entry.editingFinished.connect(self.on_alt_sf_color_entry)
self.alt_sf_color_button.clicked.connect(self.on_alt_sf_color_button)
self.alt_sf_color_alpha_spinner.valueChanged.connect(self.on_alt_sf_color_spinner)
self.alt_sf_color_alpha_slider.valueChanged.connect(self.on_alt_sf_color_slider)
self.alt_sl_color_entry.editingFinished.connect(self.on_alt_sl_color_entry) self.alt_sl_color_entry.editingFinished.connect(self.on_alt_sl_color_entry)
self.alt_sl_color_button.clicked.connect(self.on_alt_sl_color_button)
self.right_left_alpha_entry.valueChanged.connect(self.on_right_left_alpha_changed) # alpha
# Setting Editor Draw colors signals # Setting Editor Draw colors signals
self.draw_color_entry.editingFinished.connect(self.on_draw_color_entry) self.draw_color_entry.editingFinished.connect(self.on_draw_color_entry)
self.draw_color_button.clicked.connect(self.on_draw_color_button)
self.sel_draw_color_entry.editingFinished.connect(self.on_sel_draw_color_entry) self.sel_draw_color_entry.editingFinished.connect(self.on_sel_draw_color_entry)
self.sel_draw_color_button.clicked.connect(self.on_sel_draw_color_button)
self.proj_color_entry.editingFinished.connect(self.on_proj_color_entry) self.proj_color_entry.editingFinished.connect(self.on_proj_color_entry)
self.proj_color_button.clicked.connect(self.on_proj_color_button)
self.proj_color_dis_entry.editingFinished.connect(self.on_proj_color_dis_entry) self.proj_color_dis_entry.editingFinished.connect(self.on_proj_color_dis_entry)
self.proj_color_dis_button.clicked.connect(self.on_proj_color_dis_button)
self.layout_combo.activated.connect(self.on_layout) self.layout_combo.activated.connect(self.on_layout)
@@ -437,191 +349,64 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
# Setting selection colors (left - right) handlers # Setting selection colors (left - right) handlers
def on_sf_color_entry(self): def on_sf_color_entry(self):
self.app.defaults['global_sel_fill'] = self.app.defaults['global_sel_fill'][7:9] self.app.defaults['global_sel_fill'] = self.app.defaults['global_sel_fill'][7:9]
self.sf_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_sel_fill'])[:7])
def on_sf_color_button(self): def on_sl_color_entry(self):
current_color = QtGui.QColor(self.app.defaults['global_sel_fill'][:7]) self.app.defaults['global_sel_line'] = self.sl_color_entry.get_value()[:7] + \
self.app.defaults['global_sel_line'][7:9]
c_dialog = QtWidgets.QColorDialog() def on_left_right_alpha_changed(self, spinner_value):
plot_fill_color = c_dialog.getColor(initial=current_color) """
Change the alpha level for the color of the selection box when selection is done left to right.
Called on valueChanged of a FCSliderWithSpinner.
if plot_fill_color.isValid() is False: :param spinner_value: passed value within [0, 255]
return :type spinner_value: int
:return: None
:rtype:
"""
self.sf_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name()))
new_val = str(plot_fill_color.name()) + str(self.app.defaults['global_sel_fill'][7:9])
self.sf_color_entry.set_value(new_val)
self.app.defaults['global_sel_fill'] = new_val
def on_sf_color_spinner(self):
spinner_value = self.sf_color_alpha_spinner.value()
self.sf_color_alpha_slider.setValue(spinner_value)
self.app.defaults['global_sel_fill'] = self.app.defaults['global_sel_fill'][:7] + \ self.app.defaults['global_sel_fill'] = self.app.defaults['global_sel_fill'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
self.app.defaults['global_sel_line'] = self.app.defaults['global_sel_line'][:7] + \ self.app.defaults['global_sel_line'] = self.app.defaults['global_sel_line'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
def on_sf_color_slider(self):
slider_value = self.sf_color_alpha_slider.value()
self.sf_color_alpha_spinner.setValue(slider_value)
def on_sl_color_entry(self):
self.app.defaults['global_sel_line'] = self.sl_color_entry.get_value()[:7] + \
self.app.defaults['global_sel_line'][7:9]
self.sl_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_sel_line'])[:7])
def on_sl_color_button(self):
current_color = QtGui.QColor(self.app.defaults['global_sel_line'][:7])
c_dialog = QtWidgets.QColorDialog()
plot_line_color = c_dialog.getColor(initial=current_color)
if plot_line_color.isValid() is False:
return
self.sl_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name()))
new_val_line = str(plot_line_color.name()) + str(self.app.defaults['global_sel_line'][7:9])
self.sl_color_entry.set_value(new_val_line)
self.app.defaults['global_sel_line'] = new_val_line
# Setting selection colors (right - left) handlers # Setting selection colors (right - left) handlers
def on_alt_sf_color_entry(self): def on_alt_sf_color_entry(self):
self.app.defaults['global_alt_sel_fill'] = self.alt_sf_color_entry.get_value()[:7] + \ self.app.defaults['global_alt_sel_fill'] = self.alt_sf_color_entry.get_value()[:7] + \
self.app.defaults['global_alt_sel_fill'][7:9] self.app.defaults['global_alt_sel_fill'][7:9]
self.alt_sf_color_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['global_alt_sel_fill'])[:7]
)
def on_alt_sf_color_button(self): def on_alt_sl_color_entry(self):
current_color = QtGui.QColor(self.app.defaults['global_alt_sel_fill'][:7]) self.app.defaults['global_alt_sel_line'] = self.alt_sl_color_entry.get_value()[:7] + \
self.app.defaults['global_alt_sel_line'][7:9]
c_dialog = QtWidgets.QColorDialog() def on_right_left_alpha_changed(self, spinner_value):
plot_fill_color = c_dialog.getColor(initial=current_color) """
Change the alpha level for the color of the selection box when selection is done right to left.
Called on valueChanged of a FCSliderWithSpinner.
if plot_fill_color.isValid() is False: :param spinner_value: passed value within [0, 255]
return :type spinner_value: int
:return: None
:rtype:
"""
self.alt_sf_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name()))
new_val = str(plot_fill_color.name()) + str(self.app.defaults['global_alt_sel_fill'][7:9])
self.alt_sf_color_entry.set_value(new_val)
self.app.defaults['global_alt_sel_fill'] = new_val
def on_alt_sf_color_spinner(self):
spinner_value = self.alt_sf_color_alpha_spinner.value()
self.alt_sf_color_alpha_slider.setValue(spinner_value)
self.app.defaults['global_alt_sel_fill'] = self.app.defaults['global_alt_sel_fill'][:7] + \ self.app.defaults['global_alt_sel_fill'] = self.app.defaults['global_alt_sel_fill'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
self.app.defaults['global_alt_sel_line'] = self.app.defaults['global_alt_sel_line'][:7] + \ self.app.defaults['global_alt_sel_line'] = self.app.defaults['global_alt_sel_line'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
def on_alt_sf_color_slider(self):
slider_value = self.alt_sf_color_alpha_slider.value()
self.alt_sf_color_alpha_spinner.setValue(slider_value)
def on_alt_sl_color_entry(self):
self.app.defaults['global_alt_sel_line'] = self.alt_sl_color_entry.get_value()[:7] + \
self.app.defaults['global_alt_sel_line'][7:9]
self.alt_sl_color_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['global_alt_sel_line'])[:7]
)
def on_alt_sl_color_button(self):
current_color = QtGui.QColor(self.app.defaults['global_alt_sel_line'][:7])
c_dialog = QtWidgets.QColorDialog()
plot_line_color = c_dialog.getColor(initial=current_color)
if plot_line_color.isValid() is False:
return
self.alt_sl_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name()))
new_val_line = str(plot_line_color.name()) + str(self.app.defaults['global_alt_sel_line'][7:9])
self.alt_sl_color_entry.set_value(new_val_line)
self.app.defaults['global_alt_sel_line'] = new_val_line
# Setting Editor colors # Setting Editor colors
def on_draw_color_entry(self): def on_draw_color_entry(self):
self.app.defaults['global_draw_color'] = self.draw_color_entry.get_value() self.app.defaults['global_draw_color'] = self.draw_color_entry.get_value()
self.draw_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_draw_color']))
def on_draw_color_button(self):
current_color = QtGui.QColor(self.app.defaults['global_draw_color'])
c_dialog = QtWidgets.QColorDialog()
draw_color = c_dialog.getColor(initial=current_color)
if draw_color.isValid() is False:
return
self.draw_color_button.setStyleSheet("background-color:%s" % str(draw_color.name()))
new_val = str(draw_color.name())
self.draw_color_entry.set_value(new_val)
self.app.defaults['global_draw_color'] = new_val
def on_sel_draw_color_entry(self): def on_sel_draw_color_entry(self):
self.app.defaults['global_sel_draw_color'] = self.sel_draw_color_entry.get_value() self.app.defaults['global_sel_draw_color'] = self.sel_draw_color_entry.get_value()
self.sel_draw_color_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['global_sel_draw_color']))
def on_sel_draw_color_button(self):
current_color = QtGui.QColor(self.app.defaults['global_sel_draw_color'])
c_dialog = QtWidgets.QColorDialog()
sel_draw_color = c_dialog.getColor(initial=current_color)
if sel_draw_color.isValid() is False:
return
self.sel_draw_color_button.setStyleSheet("background-color:%s" % str(sel_draw_color.name()))
new_val_sel = str(sel_draw_color.name())
self.sel_draw_color_entry.set_value(new_val_sel)
self.app.defaults['global_sel_draw_color'] = new_val_sel
def on_proj_color_entry(self): def on_proj_color_entry(self):
self.app.defaults['global_proj_item_color'] = self.proj_color_entry.get_value() self.app.defaults['global_proj_item_color'] = self.proj_color_entry.get_value()
self.proj_color_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['global_proj_item_color']))
def on_proj_color_button(self):
current_color = QtGui.QColor(self.app.defaults['global_proj_item_color'])
c_dialog = QtWidgets.QColorDialog()
proj_color = c_dialog.getColor(initial=current_color)
if proj_color.isValid() is False:
return
self.proj_color_button.setStyleSheet("background-color:%s" % str(proj_color.name()))
new_val_sel = str(proj_color.name())
self.proj_color_entry.set_value(new_val_sel)
self.app.defaults['global_proj_item_color'] = new_val_sel
def on_proj_color_dis_entry(self): def on_proj_color_dis_entry(self):
self.app.defaults['global_proj_item_dis_color'] = self.proj_color_dis_entry.get_value() self.app.defaults['global_proj_item_dis_color'] = self.proj_color_dis_entry.get_value()
self.proj_color_dis_button.setStyleSheet(
"background-color:%s" % str(self.app.defaults['global_proj_item_dis_color']))
def on_proj_color_dis_button(self):
current_color = QtGui.QColor(self.app.defaults['global_proj_item_dis_color'])
c_dialog = QtWidgets.QColorDialog()
proj_color = c_dialog.getColor(initial=current_color)
if proj_color.isValid() is False:
return
self.proj_color_dis_button.setStyleSheet("background-color:%s" % str(proj_color.name()))
new_val_sel = str(proj_color.name())
self.proj_color_dis_entry.set_value(new_val_sel)
self.app.defaults['global_proj_item_dis_color'] = new_val_sel
def on_layout(self, index=None, lay=None): def on_layout(self, index=None, lay=None):
""" """
@@ -647,14 +432,13 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
# first remove the toolbars: # first remove the toolbars:
try: try:
self.app.ui.removeToolBar(self.app.ui.toolbarfile) self.app.ui.removeToolBar(self.app.ui.toolbarfile)
self.app.ui.removeToolBar(self.app.ui.toolbargeo) self.app.ui.removeToolBar(self.app.ui.toolbaredit)
self.app.ui.removeToolBar(self.app.ui.toolbarview) self.app.ui.removeToolBar(self.app.ui.toolbarview)
self.app.ui.removeToolBar(self.app.ui.toolbarshell) self.app.ui.removeToolBar(self.app.ui.toolbarshell)
self.app.ui.removeToolBar(self.app.ui.toolbartools) self.app.ui.removeToolBar(self.app.ui.toolbartools)
self.app.ui.removeToolBar(self.app.ui.exc_edit_toolbar) self.app.ui.removeToolBar(self.app.ui.exc_edit_toolbar)
self.app.ui.removeToolBar(self.app.ui.geo_edit_toolbar) self.app.ui.removeToolBar(self.app.ui.geo_edit_toolbar)
self.app.ui.removeToolBar(self.app.ui.grb_edit_toolbar) self.app.ui.removeToolBar(self.app.ui.grb_edit_toolbar)
self.app.ui.removeToolBar(self.app.ui.snap_toolbar)
self.app.ui.removeToolBar(self.app.ui.toolbarshell) self.app.ui.removeToolBar(self.app.ui.toolbarshell)
except Exception: except Exception:
pass pass
@@ -665,9 +449,9 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
self.app.ui.toolbarfile.setObjectName('File_TB') self.app.ui.toolbarfile.setObjectName('File_TB')
self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarfile) self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarfile)
self.app.ui.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') self.app.ui.toolbaredit = QtWidgets.QToolBar('Edit Toolbar')
self.app.ui.toolbargeo.setObjectName('Edit_TB') self.app.ui.toolbaredit.setObjectName('Edit_TB')
self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbargeo) self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbaredit)
self.app.ui.toolbarshell = QtWidgets.QToolBar('Shell Toolbar') self.app.ui.toolbarshell = QtWidgets.QToolBar('Shell Toolbar')
self.app.ui.toolbarshell.setObjectName('Shell_TB') self.app.ui.toolbarshell.setObjectName('Shell_TB')
@@ -697,22 +481,15 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
self.app.ui.exc_edit_toolbar.setObjectName('ExcEditor_TB') self.app.ui.exc_edit_toolbar.setObjectName('ExcEditor_TB')
self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.exc_edit_toolbar) self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.exc_edit_toolbar)
self.app.ui.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar')
self.app.ui.snap_toolbar.setObjectName('Snap_TB')
self.app.ui.snap_toolbar.setMaximumHeight(30)
self.app.ui.splitter_left.addWidget(self.app.ui.snap_toolbar)
self.app.ui.corner_snap_btn.setVisible(True)
self.app.ui.snap_magnet.setVisible(True)
else: else:
# ## TOOLBAR INSTALLATION # ## # ## TOOLBAR INSTALLATION # ##
self.app.ui.toolbarfile = QtWidgets.QToolBar('File Toolbar') self.app.ui.toolbarfile = QtWidgets.QToolBar('File Toolbar')
self.app.ui.toolbarfile.setObjectName('File_TB') self.app.ui.toolbarfile.setObjectName('File_TB')
self.app.ui.addToolBar(self.app.ui.toolbarfile) self.app.ui.addToolBar(self.app.ui.toolbarfile)
self.app.ui.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') self.app.ui.toolbaredit = QtWidgets.QToolBar('Edit Toolbar')
self.app.ui.toolbargeo.setObjectName('Edit_TB') self.app.ui.toolbaredit.setObjectName('Edit_TB')
self.app.ui.addToolBar(self.app.ui.toolbargeo) self.app.ui.addToolBar(self.app.ui.toolbaredit)
self.app.ui.toolbarview = QtWidgets.QToolBar('View Toolbar') self.app.ui.toolbarview = QtWidgets.QToolBar('View Toolbar')
self.app.ui.toolbarview.setObjectName('View_TB') self.app.ui.toolbarview.setObjectName('View_TB')
@@ -743,18 +520,9 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
self.app.ui.grb_edit_toolbar.setObjectName('GrbEditor_TB') self.app.ui.grb_edit_toolbar.setObjectName('GrbEditor_TB')
self.app.ui.addToolBar(self.app.ui.grb_edit_toolbar) self.app.ui.addToolBar(self.app.ui.grb_edit_toolbar)
self.app.ui.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar')
self.app.ui.snap_toolbar.setObjectName('Snap_TB')
# self.app.ui.snap_toolbar.setMaximumHeight(30)
self.app.ui.addToolBar(self.app.ui.snap_toolbar)
self.app.ui.corner_snap_btn.setVisible(False)
self.app.ui.snap_magnet.setVisible(False)
if current_layout == 'minimal': if current_layout == 'minimal':
self.app.ui.toolbarview.setVisible(False) self.app.ui.toolbarview.setVisible(False)
self.app.ui.toolbarshell.setVisible(False) self.app.ui.toolbarshell.setVisible(False)
self.app.ui.snap_toolbar.setVisible(False)
self.app.ui.geo_edit_toolbar.setVisible(False) self.app.ui.geo_edit_toolbar.setVisible(False)
self.app.ui.grb_edit_toolbar.setVisible(False) self.app.ui.grb_edit_toolbar.setVisible(False)
self.app.ui.exc_edit_toolbar.setVisible(False) self.app.ui.exc_edit_toolbar.setVisible(False)
@@ -767,7 +535,9 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
self.app.connect_toolbar_signals() self.app.connect_toolbar_signals()
self.app.ui.grid_snap_btn.setChecked(True) self.app.ui.grid_snap_btn.setChecked(True)
self.app.ui.on_grid_snap_triggered(state=True)
self.app.ui.corner_snap_btn.setVisible(False)
self.app.ui.snap_magnet.setVisible(False)
self.app.ui.grid_gap_x_entry.setText(str(self.app.defaults["global_gridx"])) self.app.ui.grid_gap_x_entry.setText(str(self.app.defaults["global_gridx"]))
self.app.ui.grid_gap_y_entry.setText(str(self.app.defaults["global_gridy"])) self.app.ui.grid_gap_y_entry.setText(str(self.app.defaults["global_gridy"]))

View File

@@ -1,12 +1,12 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.preferences.general.GeneralAppPrefGroupUI import GeneralAppPrefGroupUI from AppGUI.preferences.general.GeneralAppPrefGroupUI import GeneralAppPrefGroupUI
from flatcamGUI.preferences.general.GeneralAPPSetGroupUI import GeneralAPPSetGroupUI from AppGUI.preferences.general.GeneralAPPSetGroupUI import GeneralAPPSetGroupUI
from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI from AppGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,12 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCEntry, FloatEntry, FCDoubleSpinner, FCCheckBox, RadioSet, FCLabel from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, RadioSet, FCLabel, NumericalEvalTupleEntry, \
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI NumericalEvalEntry
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -46,8 +47,9 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
toolchange_xy_label.setToolTip( toolchange_xy_label.setToolTip(
_("Toolchange X,Y position.") _("Toolchange X,Y position.")
) )
self.toolchangexy_entry = NumericalEvalTupleEntry(border_color='#0069A9')
grid1.addWidget(toolchange_xy_label, 1, 0) grid1.addWidget(toolchange_xy_label, 1, 0)
self.toolchangexy_entry = FCEntry()
grid1.addWidget(self.toolchangexy_entry, 1, 1) grid1.addWidget(self.toolchangexy_entry, 1, 1)
# Start move Z # Start move Z
@@ -56,8 +58,9 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
_("Height of the tool just after starting the work.\n" _("Height of the tool just after starting the work.\n"
"Delete the value if you don't need this feature.") "Delete the value if you don't need this feature.")
) )
self.gstartz_entry = NumericalEvalEntry(border_color='#0069A9')
grid1.addWidget(startzlabel, 2, 0) grid1.addWidget(startzlabel, 2, 0)
self.gstartz_entry = FloatEntry()
grid1.addWidget(self.gstartz_entry, 2, 1) grid1.addWidget(self.gstartz_entry, 2, 1)
# Feedrate rapids # Feedrate rapids
@@ -186,6 +189,11 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
grid1.addWidget(segy_label, 11, 0) grid1.addWidget(segy_label, 11, 0)
grid1.addWidget(self.segy_entry, 11, 1) grid1.addWidget(self.segy_entry, 11, 1)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid1.addWidget(separator_line, 12, 0, 1, 2)
# ----------------------------- # -----------------------------
# --- Area Exclusion ---------- # --- Area Exclusion ----------
# ----------------------------- # -----------------------------
@@ -195,10 +203,10 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
"Those parameters are available only for\n" "Those parameters are available only for\n"
"Advanced App. Level.") "Advanced App. Level.")
) )
grid1.addWidget(self.adv_label, 12, 0, 1, 2) grid1.addWidget(self.adv_label, 13, 0, 1, 2)
# Exclusion Area CB # Exclusion Area CB
self.exclusion_cb = FCCheckBox('%s:' % _("Exclusion areas")) self.exclusion_cb = FCCheckBox('%s' % _("Exclusion areas"))
self.exclusion_cb.setToolTip( self.exclusion_cb.setToolTip(
_( _(
"Include exclusion areas.\n" "Include exclusion areas.\n"
@@ -206,7 +214,7 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
"is forbidden." "is forbidden."
) )
) )
grid1.addWidget(self.exclusion_cb, 13, 0, 1, 2) grid1.addWidget(self.exclusion_cb, 14, 0, 1, 2)
# Area Selection shape # Area Selection shape
self.area_shape_label = QtWidgets.QLabel('%s:' % _("Shape")) self.area_shape_label = QtWidgets.QLabel('%s:' % _("Shape"))
@@ -217,8 +225,8 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'}, self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'},
{'label': _("Polygon"), 'value': 'polygon'}]) {'label': _("Polygon"), 'value': 'polygon'}])
grid1.addWidget(self.area_shape_label, 14, 0) grid1.addWidget(self.area_shape_label, 15, 0)
grid1.addWidget(self.area_shape_radio, 14, 1) grid1.addWidget(self.area_shape_radio, 15, 1)
# Chose Strategy # Chose Strategy
self.strategy_label = FCLabel('%s:' % _("Strategy")) self.strategy_label = FCLabel('%s:' % _("Strategy"))
@@ -229,8 +237,8 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
self.strategy_radio = RadioSet([{'label': _('Over'), 'value': 'over'}, self.strategy_radio = RadioSet([{'label': _('Over'), 'value': 'over'},
{'label': _('Around'), 'value': 'around'}]) {'label': _('Around'), 'value': 'around'}])
grid1.addWidget(self.strategy_label, 15, 0) grid1.addWidget(self.strategy_label, 16, 0)
grid1.addWidget(self.strategy_radio, 15, 1) grid1.addWidget(self.strategy_radio, 16, 1)
# Over Z # Over Z
self.over_z_label = FCLabel('%s:' % _("Over Z")) self.over_z_label = FCLabel('%s:' % _("Over Z"))

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCSpinner, RadioSet from AppGUI.GUIElements import FCSpinner, RadioSet
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtCore, QtGui from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, FCEntry from AppGUI.GUIElements import FCCheckBox, FCSpinner, FCEntry, FCColorEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -31,12 +31,22 @@ class GeometryGenPrefGroupUI(OptionsGroupUI):
self.plot_options_label = QtWidgets.QLabel("<b>%s:</b>" % _("Plot Options")) self.plot_options_label = QtWidgets.QLabel("<b>%s:</b>" % _("Plot Options"))
self.layout.addWidget(self.plot_options_label) self.layout.addWidget(self.plot_options_label)
plot_hlay = QtWidgets.QHBoxLayout()
self.layout.addLayout(plot_hlay)
# Plot CB # Plot CB
self.plot_cb = FCCheckBox(label=_('Plot')) self.plot_cb = FCCheckBox(label=_('Plot'))
self.plot_cb.setToolTip( self.plot_cb.setToolTip(
_("Plot (show) this object.") _("Plot (show) this object.")
) )
self.layout.addWidget(self.plot_cb) plot_hlay.addWidget(self.plot_cb)
# Multicolored CB
self.multicolored_cb = FCCheckBox(label=_('M-Color'))
self.multicolored_cb.setToolTip(
_("Draw polygons in different colors.")
)
plot_hlay.addWidget(self.multicolored_cb)
grid0 = QtWidgets.QGridLayout() grid0 = QtWidgets.QGridLayout()
self.layout.addLayout(grid0) self.layout.addLayout(grid0)
@@ -77,7 +87,7 @@ class GeometryGenPrefGroupUI(OptionsGroupUI):
grid0.addWidget(separator_line, 9, 0, 1, 2) grid0.addWidget(separator_line, 9, 0, 1, 2)
# Geometry Object Color # Geometry Object Color
self.gerber_color_label = QtWidgets.QLabel('<b>%s</b>' % _('Geometry Object Color')) self.gerber_color_label = QtWidgets.QLabel('<b>%s</b>' % _('Object Color'))
grid0.addWidget(self.gerber_color_label, 10, 0, 1, 2) grid0.addWidget(self.gerber_color_label, 10, 0, 1, 2)
# Plot Line Color # Plot Line Color
@@ -85,39 +95,15 @@ class GeometryGenPrefGroupUI(OptionsGroupUI):
self.line_color_label.setToolTip( self.line_color_label.setToolTip(
_("Set the line color for plotted objects.") _("Set the line color for plotted objects.")
) )
self.line_color_entry = FCEntry() self.line_color_entry = FCColorEntry()
self.line_color_button = QtWidgets.QPushButton()
self.line_color_button.setFixedSize(15, 15)
self.form_box_child_2 = QtWidgets.QHBoxLayout()
self.form_box_child_2.addWidget(self.line_color_entry)
self.form_box_child_2.addWidget(self.line_color_button)
self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.line_color_label, 11, 0) grid0.addWidget(self.line_color_label, 11, 0)
grid0.addLayout(self.form_box_child_2, 11, 1) grid0.addWidget(self.line_color_entry, 11, 1)
self.layout.addStretch() self.layout.addStretch()
# Setting plot colors signals # Setting plot colors signals
self.line_color_entry.editingFinished.connect(self.on_line_color_entry) self.line_color_entry.editingFinished.connect(self.on_line_color_entry)
self.line_color_button.clicked.connect(self.on_line_color_button)
def on_line_color_entry(self): def on_line_color_entry(self):
self.app.defaults['geometry_plot_line'] = self.line_color_entry.get_value()[:7] + 'FF' self.app.defaults['geometry_plot_line'] = self.line_color_entry.get_value()[:7] + 'FF'
self.line_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['geometry_plot_line'])[:7])
def on_line_color_button(self):
current_color = QtGui.QColor(self.app.defaults['geometry_plot_line'][:7])
# print(current_color)
c_dialog = QtWidgets.QColorDialog()
plot_line_color = c_dialog.getColor(initial=current_color)
if plot_line_color.isValid() is False:
return
self.line_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name()))
new_val_line = str(plot_line_color.name()) + str(self.app.defaults['geometry_plot_line'][7:9])
self.line_color_entry.set_value(new_val_line)

View File

@@ -1,12 +1,13 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt, QSettings from PyQt5.QtCore import Qt, QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, OptionalInputSection, FCEntry, FCSpinner, FCComboBox from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, OptionalInputSection, FCSpinner, FCComboBox, \
from flatcamGUI.preferences import machinist_setting NumericalEvalTupleEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences import machinist_setting
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -176,7 +177,7 @@ class GeometryOptPrefGroupUI(OptionsGroupUI):
"If no value is entered then there is no move\n" "If no value is entered then there is no move\n"
"on X,Y plane at the end of the job.") "on X,Y plane at the end of the job.")
) )
self.endxy_entry = FCEntry() self.endxy_entry = NumericalEvalTupleEntry(border_color='#0069A9')
grid1.addWidget(endmove_xy_label, 7, 0) grid1.addWidget(endmove_xy_label, 7, 0)
grid1.addWidget(self.endxy_entry, 7, 1) grid1.addWidget(self.endxy_entry, 7, 1)

View File

@@ -1,13 +1,13 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.preferences.geometry.GeometryEditorPrefGroupUI import GeometryEditorPrefGroupUI from AppGUI.preferences.geometry.GeometryEditorPrefGroupUI import GeometryEditorPrefGroupUI
from flatcamGUI.preferences.geometry.GeometryAdvOptPrefGroupUI import GeometryAdvOptPrefGroupUI from AppGUI.preferences.geometry.GeometryAdvOptPrefGroupUI import GeometryAdvOptPrefGroupUI
from flatcamGUI.preferences.geometry.GeometryOptPrefGroupUI import GeometryOptPrefGroupUI from AppGUI.preferences.geometry.GeometryOptPrefGroupUI import GeometryOptPrefGroupUI
from flatcamGUI.preferences.geometry.GeometryGenPrefGroupUI import GeometryGenPrefGroupUI from AppGUI.preferences.geometry.GeometryGenPrefGroupUI import GeometryGenPrefGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner, FCSpinner, OptionalInputSection from AppGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner, FCSpinner, OptionalInputSection
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -63,85 +63,6 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid0.addWidget(separator_line, 2, 0, 1, 2) grid0.addWidget(separator_line, 2, 0, 1, 2)
# Tool Type
self.tool_type_label = QtWidgets.QLabel('<b>%s</b>' % _('Tool Type'))
self.tool_type_label.setToolTip(
_("Choose which tool to use for Gerber isolation:\n"
"'Circular' or 'V-shape'.\n"
"When the 'V-shape' is selected then the tool\n"
"diameter will depend on the chosen cut depth.")
)
self.tool_type_radio = RadioSet([{'label': 'Circular', 'value': 'circular'},
{'label': 'V-Shape', 'value': 'v'}])
grid0.addWidget(self.tool_type_label, 3, 0)
grid0.addWidget(self.tool_type_radio, 3, 1, 1, 2)
# Tip Dia
self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia'))
self.tipdialabel.setToolTip(
_("The tip diameter for V-Shape Tool")
)
self.tipdia_spinner = FCDoubleSpinner()
self.tipdia_spinner.set_precision(self.decimals)
self.tipdia_spinner.set_range(-99.9999, 99.9999)
self.tipdia_spinner.setSingleStep(0.1)
self.tipdia_spinner.setWrapping(True)
grid0.addWidget(self.tipdialabel, 4, 0)
grid0.addWidget(self.tipdia_spinner, 4, 1, 1, 2)
# Tip Angle
self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle'))
self.tipanglelabel.setToolTip(
_("The tip angle for V-Shape Tool.\n"
"In degree.")
)
self.tipangle_spinner = FCSpinner()
self.tipangle_spinner.set_range(1, 180)
self.tipangle_spinner.set_step(5)
self.tipangle_spinner.setWrapping(True)
grid0.addWidget(self.tipanglelabel, 5, 0)
grid0.addWidget(self.tipangle_spinner, 5, 1, 1, 2)
# Cut Z
self.cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
self.cutzlabel.setToolTip(
_("Cutting depth (negative)\n"
"below the copper surface.")
)
self.cutz_spinner = FCDoubleSpinner()
self.cutz_spinner.set_precision(self.decimals)
self.cutz_spinner.set_range(-99.9999, 0.0000)
self.cutz_spinner.setSingleStep(0.1)
self.cutz_spinner.setWrapping(True)
grid0.addWidget(self.cutzlabel, 6, 0)
grid0.addWidget(self.cutz_spinner, 6, 1, 1, 2)
# Isolation Type
self.iso_type_label = QtWidgets.QLabel('%s:' % _('Isolation Type'))
self.iso_type_label.setToolTip(
_("Choose how the isolation will be executed:\n"
"- 'Full' -> complete isolation of polygons\n"
"- 'Ext' -> will isolate only on the outside\n"
"- 'Int' -> will isolate only on the inside\n"
"'Exterior' isolation is almost always possible\n"
"(with the right tool) but 'Interior'\n"
"isolation can be done only when there is an opening\n"
"inside of the polygon (e.g polygon is a 'doughnut' shape).")
)
self.iso_type_radio = RadioSet([{'label': _('Full'), 'value': 'full'},
{'label': _('Exterior'), 'value': 'ext'},
{'label': _('Interior'), 'value': 'int'}])
grid0.addWidget(self.iso_type_label, 7, 0,)
grid0.addWidget(self.iso_type_radio, 7, 1, 1, 2)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid0.addWidget(separator_line, 8, 0, 1, 2)
# Buffering Type # Buffering Type
buffering_label = QtWidgets.QLabel('%s:' % _('Buffering')) buffering_label = QtWidgets.QLabel('%s:' % _('Buffering'))
buffering_label.setToolTip( buffering_label.setToolTip(

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, FCComboBox, FCEntry, RadioSet from AppGUI.GUIElements import FCSpinner, FCDoubleSpinner, FCComboBox, FCEntry, RadioSet, NumericalEvalTupleEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -109,8 +109,9 @@ class GerberEditorPrefGroupUI(OptionsGroupUI):
"The value of the diameter has to use the dot decimals separator.\n" "The value of the diameter has to use the dot decimals separator.\n"
"Valid values: 0.3, 1.0") "Valid values: 0.3, 1.0")
) )
self.adddim_entry = NumericalEvalTupleEntry(border_color='#0069A9')
grid0.addWidget(self.adddim_label, 5, 0) grid0.addWidget(self.adddim_label, 5, 0)
self.adddim_entry = FCEntry()
grid0.addWidget(self.adddim_entry, 5, 1) grid0.addWidget(self.adddim_entry, 5, 1)
self.grb_array_linear_label = QtWidgets.QLabel('<b>%s:</b>' % _('Linear Pad Array')) self.grb_array_linear_label = QtWidgets.QLabel('<b>%s:</b>' % _('Linear Pad Array'))

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtCore from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import RadioSet, FCSpinner from AppGUI.GUIElements import RadioSet, FCSpinner
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtCore, QtGui from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry from AppGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry, FCSliderWithSpinner, FCColorEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -34,26 +34,26 @@ class GerberGenPrefGroupUI(OptionsGroupUI):
grid0 = QtWidgets.QGridLayout() grid0 = QtWidgets.QGridLayout()
self.layout.addLayout(grid0) self.layout.addLayout(grid0)
# Plot CB
self.plot_cb = FCCheckBox(label='%s' % _('Plot'))
self.plot_options_label.setToolTip(
_("Plot (show) this object.")
)
grid0.addWidget(self.plot_cb, 0, 0)
# Solid CB # Solid CB
self.solid_cb = FCCheckBox(label='%s' % _('Solid')) self.solid_cb = FCCheckBox(label='%s' % _('Solid'))
self.solid_cb.setToolTip( self.solid_cb.setToolTip(
_("Solid color polygons.") _("Solid color polygons.")
) )
grid0.addWidget(self.solid_cb, 0, 0) grid0.addWidget(self.solid_cb, 0, 1)
# Multicolored CB # Multicolored CB
self.multicolored_cb = FCCheckBox(label='%s' % _('M-Color')) self.multicolored_cb = FCCheckBox(label='%s' % _('M-Color'))
self.multicolored_cb.setToolTip( self.multicolored_cb.setToolTip(
_("Draw polygons in different colors.") _("Draw polygons in different colors.")
) )
grid0.addWidget(self.multicolored_cb, 0, 1) grid0.addWidget(self.multicolored_cb, 0, 2)
# Plot CB
self.plot_cb = FCCheckBox(label='%s' % _('Plot'))
self.plot_options_label.setToolTip(
_("Plot (show) this object.")
)
grid0.addWidget(self.plot_cb, 0, 2)
# Number of circle steps for circular aperture linear approximation # Number of circle steps for circular aperture linear approximation
self.circle_steps_label = QtWidgets.QLabel('%s:' % _("Circle Steps")) self.circle_steps_label = QtWidgets.QLabel('%s:' % _("Circle Steps"))
@@ -146,100 +146,55 @@ class GerberGenPrefGroupUI(OptionsGroupUI):
grid0.addWidget(separator_line, 9, 0, 1, 3) grid0.addWidget(separator_line, 9, 0, 1, 3)
# Gerber Object Color # Gerber Object Color
self.gerber_color_label = QtWidgets.QLabel('<b>%s</b>' % _('Gerber Object Color')) self.gerber_color_label = QtWidgets.QLabel('<b>%s</b>' % _('Object Color'))
grid0.addWidget(self.gerber_color_label, 10, 0, 1, 3) grid0.addWidget(self.gerber_color_label, 10, 0, 1, 3)
# Plot Line Color # Plot Line Color
self.pl_color_label = QtWidgets.QLabel('%s:' % _('Outline')) self.line_color_label = QtWidgets.QLabel('%s:' % _('Outline'))
self.pl_color_label.setToolTip( self.line_color_label.setToolTip(
_("Set the line color for plotted objects.") _("Set the line color for plotted objects.")
) )
self.pl_color_entry = FCEntry() self.line_color_entry = FCColorEntry()
self.pl_color_button = QtWidgets.QPushButton()
self.pl_color_button.setFixedSize(15, 15)
self.form_box_child_2 = QtWidgets.QHBoxLayout() grid0.addWidget(self.line_color_label, 11, 0)
self.form_box_child_2.addWidget(self.pl_color_entry) grid0.addWidget(self.line_color_entry, 11, 1, 1, 2)
self.form_box_child_2.addWidget(self.pl_color_button)
self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.pl_color_label, 11, 0)
grid0.addLayout(self.form_box_child_2, 11, 1, 1, 2)
# Plot Fill Color # Plot Fill Color
self.pf_color_label = QtWidgets.QLabel('%s:' % _('Fill')) self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill'))
self.pf_color_label.setToolTip( self.fill_color_label.setToolTip(
_("Set the fill color for plotted objects.\n" _("Set the fill color for plotted objects.\n"
"First 6 digits are the color and the last 2\n" "First 6 digits are the color and the last 2\n"
"digits are for alpha (transparency) level.") "digits are for alpha (transparency) level.")
) )
self.pf_color_entry = FCEntry() self.fill_color_entry = FCColorEntry()
self.pf_color_button = QtWidgets.QPushButton()
self.pf_color_button.setFixedSize(15, 15)
self.form_box_child_1 = QtWidgets.QHBoxLayout() grid0.addWidget(self.fill_color_label, 12, 0)
self.form_box_child_1.addWidget(self.pf_color_entry) grid0.addWidget(self.fill_color_entry, 12, 1, 1, 2)
self.form_box_child_1.addWidget(self.pf_color_button)
self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
grid0.addWidget(self.pf_color_label, 12, 0)
grid0.addLayout(self.form_box_child_1, 12, 1, 1, 2)
# Plot Fill Transparency Level # Plot Fill Transparency Level
self.pf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) self.gerber_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
self.pf_alpha_label.setToolTip( self.gerber_alpha_label.setToolTip(
_("Set the fill transparency for plotted objects.") _("Set the fill transparency for plotted objects.")
) )
self.pf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) self.gerber_alpha_entry = FCSliderWithSpinner(0, 255, 1)
self.pf_color_alpha_slider.setMinimum(0)
self.pf_color_alpha_slider.setMaximum(255)
self.pf_color_alpha_slider.setSingleStep(1)
self.pf_color_alpha_spinner = FCSpinner() grid0.addWidget(self.gerber_alpha_label, 13, 0)
self.pf_color_alpha_spinner.setMinimumWidth(70) grid0.addWidget(self.gerber_alpha_entry, 13, 1, 1, 2)
self.pf_color_alpha_spinner.set_range(0, 255)
self.form_box_child_3 = QtWidgets.QHBoxLayout()
self.form_box_child_3.addWidget(self.pf_color_alpha_slider)
self.form_box_child_3.addWidget(self.pf_color_alpha_spinner)
grid0.addWidget(self.pf_alpha_label, 13, 0)
grid0.addLayout(self.form_box_child_3, 13, 1, 1, 2)
self.layout.addStretch() self.layout.addStretch()
# Setting plot colors signals # Setting plot colors signals
self.pl_color_entry.editingFinished.connect(self.on_pl_color_entry) self.line_color_entry.editingFinished.connect(self.on_line_color_changed)
self.pl_color_button.clicked.connect(self.on_pl_color_button) self.fill_color_entry.editingFinished.connect(self.on_fill_color_changed)
self.pf_color_entry.editingFinished.connect(self.on_pf_color_entry)
self.pf_color_button.clicked.connect(self.on_pf_color_button) self.gerber_alpha_entry.valueChanged.connect(self.on_gerber_alpha_changed) # alpha
self.pf_color_alpha_spinner.valueChanged.connect(self.on_pf_color_spinner)
self.pf_color_alpha_slider.valueChanged.connect(self.on_pf_color_slider)
# Setting plot colors handlers # Setting plot colors handlers
def on_pf_color_entry(self): def on_fill_color_changed(self):
self.app.defaults['gerber_plot_fill'] = self.pf_color_entry.get_value()[:7] + \ self.app.defaults['gerber_plot_fill'] = self.fill_color_entry.get_value()[:7] + \
self.app.defaults['gerber_plot_fill'][7:9] self.app.defaults['gerber_plot_fill'][7:9]
self.pf_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['gerber_plot_fill'])[:7])
def on_pf_color_button(self): def on_gerber_alpha_changed(self, spinner_value):
current_color = QtGui.QColor(self.app.defaults['gerber_plot_fill'][:7])
c_dialog = QtWidgets.QColorDialog()
plot_fill_color = c_dialog.getColor(initial=current_color)
if plot_fill_color.isValid() is False:
return
self.pf_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name()))
new_val = str(plot_fill_color.name()) + str(self.app.defaults['gerber_plot_fill'][7:9])
self.pf_color_entry.set_value(new_val)
self.app.defaults['gerber_plot_fill'] = new_val
def on_pf_color_spinner(self):
spinner_value = self.pf_color_alpha_spinner.value()
self.pf_color_alpha_slider.setValue(spinner_value)
self.app.defaults['gerber_plot_fill'] = \ self.app.defaults['gerber_plot_fill'] = \
self.app.defaults['gerber_plot_fill'][:7] + \ self.app.defaults['gerber_plot_fill'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
@@ -247,27 +202,6 @@ class GerberGenPrefGroupUI(OptionsGroupUI):
self.app.defaults['gerber_plot_line'][:7] + \ self.app.defaults['gerber_plot_line'][:7] + \
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
def on_pf_color_slider(self): def on_line_color_changed(self):
slider_value = self.pf_color_alpha_slider.value() self.app.defaults['gerber_plot_line'] = self.line_color_entry.get_value()[:7] + \
self.pf_color_alpha_spinner.setValue(slider_value)
def on_pl_color_entry(self):
self.app.defaults['gerber_plot_line'] = self.pl_color_entry.get_value()[:7] + \
self.app.defaults['gerber_plot_line'][7:9] self.app.defaults['gerber_plot_line'][7:9]
self.pl_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['gerber_plot_line'])[:7])
def on_pl_color_button(self):
current_color = QtGui.QColor(self.app.defaults['gerber_plot_line'][:7])
# print(current_color)
c_dialog = QtWidgets.QColorDialog()
plot_line_color = c_dialog.getColor(initial=current_color)
if plot_line_color.isValid() is False:
return
self.pl_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name()))
new_val_line = str(plot_line_color.name()) + str(self.app.defaults['gerber_plot_line'][7:9])
self.pl_color_entry.set_value(new_val_line)
self.app.defaults['gerber_plot_line'] = new_val_line

View File

@@ -0,0 +1,100 @@
from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings
from AppGUI.GUIElements import FCDoubleSpinner, FCSpinner, RadioSet, FCCheckBox, FCComboBox
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext
import AppTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
settings = QSettings("Open Source", "FlatCAM")
if settings.contains("machinist"):
machinist_setting = settings.value('machinist', type=int)
else:
machinist_setting = 0
class GerberOptPrefGroupUI(OptionsGroupUI):
def __init__(self, decimals=4, parent=None):
# OptionsGroupUI.__init__(self, "Gerber Options Preferences", parent=parent)
super(GerberOptPrefGroupUI, self).__init__(self, parent=parent)
self.decimals = decimals
self.setTitle(str(_("Gerber Options")))
# ## Clear non-copper regions
self.clearcopper_label = QtWidgets.QLabel("<b>%s:</b>" % _("Non-copper regions"))
self.clearcopper_label.setToolTip(
_("Create polygons covering the\n"
"areas without copper on the PCB.\n"
"Equivalent to the inverse of this\n"
"object. Can be used to remove all\n"
"copper from a specified region.")
)
self.layout.addWidget(self.clearcopper_label)
grid1 = QtWidgets.QGridLayout()
self.layout.addLayout(grid1)
# Margin
bmlabel = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
bmlabel.setToolTip(
_("Specify the edge of the PCB\n"
"by drawing a box around all\n"
"objects with this minimum\n"
"distance.")
)
grid1.addWidget(bmlabel, 0, 0)
self.noncopper_margin_entry = FCDoubleSpinner()
self.noncopper_margin_entry.set_precision(self.decimals)
self.noncopper_margin_entry.setSingleStep(0.1)
self.noncopper_margin_entry.set_range(-9999, 9999)
grid1.addWidget(self.noncopper_margin_entry, 0, 1)
# Rounded corners
self.noncopper_rounded_cb = FCCheckBox(label=_("Rounded Geo"))
self.noncopper_rounded_cb.setToolTip(
_("Resulting geometry will have rounded corners.")
)
grid1.addWidget(self.noncopper_rounded_cb, 1, 0, 1, 2)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid1.addWidget(separator_line, 2, 0, 1, 2)
# ## Bounding box
self.boundingbox_label = QtWidgets.QLabel('<b>%s:</b>' % _('Bounding Box'))
self.layout.addWidget(self.boundingbox_label)
grid2 = QtWidgets.QGridLayout()
self.layout.addLayout(grid2)
bbmargin = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
bbmargin.setToolTip(
_("Distance of the edges of the box\n"
"to the nearest polygon.")
)
self.bbmargin_entry = FCDoubleSpinner()
self.bbmargin_entry.set_precision(self.decimals)
self.bbmargin_entry.setSingleStep(0.1)
self.bbmargin_entry.set_range(-9999, 9999)
grid2.addWidget(bbmargin, 0, 0)
grid2.addWidget(self.bbmargin_entry, 0, 1)
self.bbrounded_cb = FCCheckBox(label='%s' % _("Rounded Geo"))
self.bbrounded_cb.setToolTip(
_("If the bounding box is \n"
"to have rounded corners\n"
"their radius is equal to\n"
"the margin.")
)
grid2.addWidget(self.bbrounded_cb, 1, 0, 1, 2)
self.layout.addStretch()

View File

@@ -1,14 +1,14 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.preferences.gerber.GerberEditorPrefGroupUI import GerberEditorPrefGroupUI from AppGUI.preferences.gerber.GerberEditorPrefGroupUI import GerberEditorPrefGroupUI
from flatcamGUI.preferences.gerber.GerberExpPrefGroupUI import GerberExpPrefGroupUI from AppGUI.preferences.gerber.GerberExpPrefGroupUI import GerberExpPrefGroupUI
from flatcamGUI.preferences.gerber.GerberAdvOptPrefGroupUI import GerberAdvOptPrefGroupUI from AppGUI.preferences.gerber.GerberAdvOptPrefGroupUI import GerberAdvOptPrefGroupUI
from flatcamGUI.preferences.gerber.GerberOptPrefGroupUI import GerberOptPrefGroupUI from AppGUI.preferences.gerber.GerberOptPrefGroupUI import GerberOptPrefGroupUI
from flatcamGUI.preferences.gerber.GerberGenPrefGroupUI import GerberGenPrefGroupUI from AppGUI.preferences.gerber.GerberGenPrefGroupUI import GerberGenPrefGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -44,6 +44,7 @@ class GerberPreferencesUI(QtWidgets.QWidget):
self.vlay = QtWidgets.QVBoxLayout() self.vlay = QtWidgets.QVBoxLayout()
self.vlay.addWidget(self.gerber_opt_group) self.vlay.addWidget(self.gerber_opt_group)
self.vlay.addWidget(self.gerber_exp_group) self.vlay.addWidget(self.gerber_exp_group)
self.vlay.addStretch()
self.layout.addWidget(self.gerber_gen_group) self.layout.addWidget(self.gerber_gen_group)
self.layout.addLayout(self.vlay) self.layout.addLayout(self.vlay)

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet from AppGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, FCEntry from AppGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, NumericalEvalTupleEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -116,7 +116,7 @@ class Tools2CalPrefGroupUI(OptionsGroupUI):
"(x, y) point will be used,") "(x, y) point will be used,")
) )
self.toolchange_xy_entry = FCEntry() self.toolchange_xy_entry = NumericalEvalTupleEntry(border_color='#0069A9')
grid_lay.addWidget(toolchangexy_lbl, 7, 0) grid_lay.addWidget(toolchangexy_lbl, 7, 0)
grid_lay.addWidget(self.toolchange_xy_entry, 7, 1, 1, 2) grid_lay.addWidget(self.toolchange_xy_entry, 7, 1, 1, 2)

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner from AppGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner, RadioSet from AppGUI.GUIElements import FCDoubleSpinner, RadioSet
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner, RadioSet from AppGUI.GUIElements import FCDoubleSpinner, RadioSet
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCSpinner from AppGUI.GUIElements import FCSpinner
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,18 +1,18 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.preferences.tools.Tools2InvertPrefGroupUI import Tools2InvertPrefGroupUI from AppGUI.preferences.tools.Tools2InvertPrefGroupUI import Tools2InvertPrefGroupUI
from flatcamGUI.preferences.tools.Tools2PunchGerberPrefGroupUI import Tools2PunchGerberPrefGroupUI from AppGUI.preferences.tools.Tools2PunchGerberPrefGroupUI import Tools2PunchGerberPrefGroupUI
from flatcamGUI.preferences.tools.Tools2EDrillsPrefGroupUI import Tools2EDrillsPrefGroupUI from AppGUI.preferences.tools.Tools2EDrillsPrefGroupUI import Tools2EDrillsPrefGroupUI
from flatcamGUI.preferences.tools.Tools2CalPrefGroupUI import Tools2CalPrefGroupUI from AppGUI.preferences.tools.Tools2CalPrefGroupUI import Tools2CalPrefGroupUI
from flatcamGUI.preferences.tools.Tools2FiducialsPrefGroupUI import Tools2FiducialsPrefGroupUI from AppGUI.preferences.tools.Tools2FiducialsPrefGroupUI import Tools2FiducialsPrefGroupUI
from flatcamGUI.preferences.tools.Tools2CThievingPrefGroupUI import Tools2CThievingPrefGroupUI from AppGUI.preferences.tools.Tools2CThievingPrefGroupUI import Tools2CThievingPrefGroupUI
from flatcamGUI.preferences.tools.Tools2QRCodePrefGroupUI import Tools2QRCodePrefGroupUI from AppGUI.preferences.tools.Tools2QRCodePrefGroupUI import Tools2QRCodePrefGroupUI
from flatcamGUI.preferences.tools.Tools2OptimalPrefGroupUI import Tools2OptimalPrefGroupUI from AppGUI.preferences.tools.Tools2OptimalPrefGroupUI import Tools2OptimalPrefGroupUI
from flatcamGUI.preferences.tools.Tools2RulesCheckPrefGroupUI import Tools2RulesCheckPrefGroupUI from AppGUI.preferences.tools.Tools2RulesCheckPrefGroupUI import Tools2RulesCheckPrefGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner from AppGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtCore from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt, QSettings from PyQt5.QtCore import Qt, QSettings
from flatcamGUI.GUIElements import FCSpinner, RadioSet, FCTextArea, FCEntry from AppGUI.GUIElements import FCSpinner, RadioSet, FCTextArea, FCEntry, FCColorEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -153,42 +153,20 @@ class Tools2QRCodePrefGroupUI(OptionsGroupUI):
self.fill_color_label.setToolTip( self.fill_color_label.setToolTip(
_("Set the QRCode fill color (squares color).") _("Set the QRCode fill color (squares color).")
) )
self.fill_color_entry = FCEntry() self.fill_color_entry = FCColorEntry()
self.fill_color_button = QtWidgets.QPushButton()
self.fill_color_button.setFixedSize(15, 15)
fill_lay_child = QtWidgets.QHBoxLayout()
fill_lay_child.setContentsMargins(0, 0, 0, 0)
fill_lay_child.addWidget(self.fill_color_entry)
fill_lay_child.addWidget(self.fill_color_button, alignment=Qt.AlignRight)
fill_lay_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
fill_color_widget = QtWidgets.QWidget()
fill_color_widget.setLayout(fill_lay_child)
grid_lay.addWidget(self.fill_color_label, 9, 0) grid_lay.addWidget(self.fill_color_label, 9, 0)
grid_lay.addWidget(fill_color_widget, 9, 1) grid_lay.addWidget(self.fill_color_entry, 9, 1)
# BACK COLOR # # BACK COLOR #
self.back_color_label = QtWidgets.QLabel('%s:' % _('Back Color')) self.back_color_label = QtWidgets.QLabel('%s:' % _('Back Color'))
self.back_color_label.setToolTip( self.back_color_label.setToolTip(
_("Set the QRCode background color.") _("Set the QRCode background color.")
) )
self.back_color_entry = FCEntry() self.back_color_entry = FCColorEntry()
self.back_color_button = QtWidgets.QPushButton()
self.back_color_button.setFixedSize(15, 15)
back_lay_child = QtWidgets.QHBoxLayout()
back_lay_child.setContentsMargins(0, 0, 0, 0)
back_lay_child.addWidget(self.back_color_entry)
back_lay_child.addWidget(self.back_color_button, alignment=Qt.AlignRight)
back_lay_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
back_color_widget = QtWidgets.QWidget()
back_color_widget.setLayout(back_lay_child)
grid_lay.addWidget(self.back_color_label, 10, 0) grid_lay.addWidget(self.back_color_label, 10, 0)
grid_lay.addWidget(back_color_widget, 10, 1) grid_lay.addWidget(self.back_color_entry, 10, 1)
# Selection Limit # Selection Limit
self.sel_limit_label = QtWidgets.QLabel('%s:' % _("Selection limit")) self.sel_limit_label = QtWidgets.QLabel('%s:' % _("Selection limit"))
@@ -205,3 +183,13 @@ class Tools2QRCodePrefGroupUI(OptionsGroupUI):
grid_lay.addWidget(self.sel_limit_label, 11, 0) grid_lay.addWidget(self.sel_limit_label, 11, 0)
grid_lay.addWidget(self.sel_limit_entry, 11, 1) grid_lay.addWidget(self.sel_limit_entry, 11, 1)
# self.layout.addStretch() # self.layout.addStretch()
# QRCode Tool
self.fill_color_entry.editingFinished.connect(self.on_qrcode_fill_color_entry)
self.back_color_entry.editingFinished.connect(self.on_qrcode_back_color_entry)
def on_qrcode_fill_color_entry(self):
self.app.defaults['tools_qrcode_fill_color'] = self.fill_color_entry.get_value()
def on_qrcode_back_color_entry(self):
self.app.defaults['tools_qrcode_back_color'] = self.back_color_entry.get_value()

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCCheckBox, FCDoubleSpinner from AppGUI.GUIElements import FCCheckBox, FCDoubleSpinner
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner, RadioSet from AppGUI.GUIElements import FCDoubleSpinner, RadioSet
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner from AppGUI.GUIElements import FCDoubleSpinner
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -0,0 +1,81 @@
from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings
from AppGUI.GUIElements import FCDoubleSpinner
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext
import AppTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
settings = QSettings("Open Source", "FlatCAM")
if settings.contains("machinist"):
machinist_setting = settings.value('machinist', type=int)
else:
machinist_setting = 0
class ToolsCornersPrefGroupUI(OptionsGroupUI):
def __init__(self, decimals=4, parent=None):
# OptionsGroupUI.__init__(self, "Calculators Tool Options", parent=parent)
super(ToolsCornersPrefGroupUI, self).__init__(self, parent=parent)
self.setTitle(str(_("Corner Markers Options")))
self.decimals = decimals
grid0 = QtWidgets.QGridLayout()
grid0.setColumnStretch(0, 0)
grid0.setColumnStretch(1, 1)
self.layout.addLayout(grid0)
self.param_label = QtWidgets.QLabel('<b>%s:</b>' % _('Parameters'))
self.param_label.setToolTip(
_("Parameters used for this tool.")
)
grid0.addWidget(self.param_label, 0, 0, 1, 2)
# Thickness #
self.thick_label = QtWidgets.QLabel('%s:' % _("Thickness"))
self.thick_label.setToolTip(
_("The thickness of the line that makes the corner marker.")
)
self.thick_entry = FCDoubleSpinner()
self.thick_entry.set_range(0.0000, 9.9999)
self.thick_entry.set_precision(self.decimals)
self.thick_entry.setWrapping(True)
self.thick_entry.setSingleStep(10 ** -self.decimals)
grid0.addWidget(self.thick_label, 1, 0)
grid0.addWidget(self.thick_entry, 1, 1)
# Length #
self.l_label = QtWidgets.QLabel('%s:' % _("Length"))
self.l_label.setToolTip(
_("The length of the line that makes the corner marker.")
)
self.l_entry = FCDoubleSpinner()
self.l_entry.set_range(-9999.9999, 9999.9999)
self.l_entry.set_precision(self.decimals)
self.l_entry.setSingleStep(10 ** -self.decimals)
# Margin #
self.margin_label = QtWidgets.QLabel('%s:' % _("Margin"))
self.margin_label.setToolTip(
_("Bounding box margin.")
)
self.margin_entry = FCDoubleSpinner()
self.margin_entry.set_range(-9999.9999, 9999.9999)
self.margin_entry.set_precision(self.decimals)
self.margin_entry.setSingleStep(0.1)
grid0.addWidget(self.margin_label, 2, 0)
grid0.addWidget(self.margin_entry, 2, 1)
grid0.addWidget(self.l_label, 4, 0)
grid0.addWidget(self.l_entry, 4, 1)
self.layout.addStretch()

View File

@@ -1,12 +1,12 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, RadioSet, FCComboBox from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, RadioSet, FCComboBox
from flatcamGUI.preferences import machinist_setting from AppGUI.preferences import machinist_setting
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtCore from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt, QSettings from PyQt5.QtCore import Qt, QSettings
from flatcamGUI.GUIElements import RadioSet, FCEntry, FCDoubleSpinner, FCCheckBox, FCComboBox from AppGUI.GUIElements import RadioSet, FCEntry, FCDoubleSpinner, FCCheckBox, FCComboBox, FCColorEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -30,8 +30,7 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
# ## Parameters # ## Parameters
self.film_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters")) self.film_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
self.film_label.setToolTip( self.film_label.setToolTip(
_("Create a PCB film from a Gerber or Geometry\n" _("Create a PCB film from a Gerber or Geometry object.\n"
"FlatCAM object.\n"
"The file is saved in SVG format.") "The file is saved in SVG format.")
) )
self.layout.addWidget(self.film_label) self.layout.addWidget(self.film_label)
@@ -58,20 +57,10 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
self.film_color_label.setToolTip( self.film_color_label.setToolTip(
_("Set the film color when positive film is selected.") _("Set the film color when positive film is selected.")
) )
self.film_color_entry = FCEntry() self.film_color_entry = FCColorEntry()
self.film_color_button = QtWidgets.QPushButton()
self.film_color_button.setFixedSize(15, 15)
self.form_box_child = QtWidgets.QHBoxLayout()
self.form_box_child.setContentsMargins(0, 0, 0, 0)
self.form_box_child.addWidget(self.film_color_entry)
self.form_box_child.addWidget(self.film_color_button, alignment=Qt.AlignRight)
self.form_box_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
film_color_widget = QtWidgets.QWidget()
film_color_widget.setLayout(self.form_box_child)
grid0.addWidget(self.film_color_label, 1, 0) grid0.addWidget(self.film_color_label, 1, 0)
grid0.addWidget(film_color_widget, 1, 1) grid0.addWidget(self.film_color_entry, 1, 1)
# Film Border # Film Border
self.film_boundary_entry = FCDoubleSpinner() self.film_boundary_entry = FCDoubleSpinner()
@@ -314,3 +303,9 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
grid0.addWidget(self.pagesize_combo, 17, 1) grid0.addWidget(self.pagesize_combo, 17, 1)
self.layout.addStretch() self.layout.addStretch()
# Film Tool
self.film_color_entry.editingFinished.connect(self.on_film_color_entry)
def on_film_color_entry(self):
self.app.defaults['tools_film_color'] = self.film_color_entry.get_value()

View File

@@ -0,0 +1,320 @@
from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings
from AppGUI.GUIElements import RadioSet, FCDoubleSpinner, FCComboBox, FCCheckBox, FCSpinner, NumericalEvalTupleEntry
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext
import AppTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
settings = QSettings("Open Source", "FlatCAM")
if settings.contains("machinist"):
machinist_setting = settings.value('machinist', type=int)
else:
machinist_setting = 0
class ToolsISOPrefGroupUI(OptionsGroupUI):
def __init__(self, decimals=4, parent=None):
super(ToolsISOPrefGroupUI, self).__init__(self, parent=parent)
self.setTitle(str(_("Isolation Tool Options")))
self.decimals = decimals
# ## Clear non-copper regions
self.iso_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
self.iso_label.setToolTip(
_("Create a Geometry object with\n"
"toolpaths to cut around polygons.")
)
self.layout.addWidget(self.iso_label)
grid0 = QtWidgets.QGridLayout()
self.layout.addLayout(grid0)
# Tool Dias
isotdlabel = QtWidgets.QLabel('<b><font color="green">%s:</font></b>' % _('Tools Dia'))
isotdlabel.setToolTip(
_("Diameters of the tools, separated by comma.\n"
"The value of the diameter has to use the dot decimals separator.\n"
"Valid values: 0.3, 1.0")
)
self.tool_dia_entry = NumericalEvalTupleEntry(border_color='#0069A9')
self.tool_dia_entry.setPlaceholderText(_("Comma separated values"))
grid0.addWidget(isotdlabel, 0, 0)
grid0.addWidget(self.tool_dia_entry, 0, 1, 1, 2)
# Tool order Radio Button
self.order_label = QtWidgets.QLabel('%s:' % _('Tool order'))
self.order_label.setToolTip(_("This set the way that the tools in the tools table are used.\n"
"'No' --> means that the used order is the one in the tool table\n"
"'Forward' --> means that the tools will be ordered from small to big\n"
"'Reverse' --> means that the tools will ordered from big to small\n\n"
"WARNING: using rest machining will automatically set the order\n"
"in reverse and disable this control."))
self.order_radio = RadioSet([{'label': _('No'), 'value': 'no'},
{'label': _('Forward'), 'value': 'fwd'},
{'label': _('Reverse'), 'value': 'rev'}])
grid0.addWidget(self.order_label, 1, 0)
grid0.addWidget(self.order_radio, 1, 1, 1, 2)
# Tool Type Radio Button
self.tool_type_label = QtWidgets.QLabel('%s:' % _('Tool Type'))
self.tool_type_label.setToolTip(
_("Default tool type:\n"
"- 'V-shape'\n"
"- Circular")
)
self.tool_type_radio = RadioSet([{'label': _('V-shape'), 'value': 'V'},
{'label': _('Circular'), 'value': 'C1'}])
self.tool_type_radio.setToolTip(
_("Default tool type:\n"
"- 'V-shape'\n"
"- Circular")
)
grid0.addWidget(self.tool_type_label, 2, 0)
grid0.addWidget(self.tool_type_radio, 2, 1, 1, 2)
# Tip Dia
self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia'))
self.tipdialabel.setToolTip(
_("The tip diameter for V-Shape Tool"))
self.tipdia_entry = FCDoubleSpinner()
self.tipdia_entry.set_precision(self.decimals)
self.tipdia_entry.set_range(0, 1000)
self.tipdia_entry.setSingleStep(0.1)
grid0.addWidget(self.tipdialabel, 3, 0)
grid0.addWidget(self.tipdia_entry, 3, 1, 1, 2)
# Tip Angle
self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle'))
self.tipanglelabel.setToolTip(
_("The tip angle for V-Shape Tool.\n"
"In degrees."))
self.tipangle_entry = FCDoubleSpinner()
self.tipangle_entry.set_precision(self.decimals)
self.tipangle_entry.set_range(1, 180)
self.tipangle_entry.setSingleStep(5)
self.tipangle_entry.setWrapping(True)
grid0.addWidget(self.tipanglelabel, 4, 0)
grid0.addWidget(self.tipangle_entry, 4, 1, 1, 2)
# Cut Z entry
cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
cutzlabel.setToolTip(
_("Depth of cut into material. Negative value.\n"
"In FlatCAM units.")
)
self.cutz_entry = FCDoubleSpinner()
self.cutz_entry.set_precision(self.decimals)
self.cutz_entry.set_range(-9999.9999, 0.0000)
self.cutz_entry.setSingleStep(0.1)
self.cutz_entry.setToolTip(
_("Depth of cut into material. Negative value.\n"
"In FlatCAM units.")
)
grid0.addWidget(cutzlabel, 5, 0)
grid0.addWidget(self.cutz_entry, 5, 1, 1, 2)
# New Diameter
self.newdialabel = QtWidgets.QLabel('%s:' % _('New Dia'))
self.newdialabel.setToolTip(
_("Diameter for the new tool to add in the Tool Table.\n"
"If the tool is V-shape type then this value is automatically\n"
"calculated from the other parameters.")
)
self.newdia_entry = FCDoubleSpinner()
self.newdia_entry.set_precision(self.decimals)
self.newdia_entry.set_range(0.0001, 9999.9999)
self.newdia_entry.setSingleStep(0.1)
grid0.addWidget(self.newdialabel, 6, 0)
grid0.addWidget(self.newdia_entry, 6, 1, 1, 2)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid0.addWidget(separator_line, 7, 0, 1, 3)
# Passes
passlabel = QtWidgets.QLabel('%s:' % _('Passes'))
passlabel.setToolTip(
_("Width of the isolation gap in\n"
"number (integer) of tool widths.")
)
self.passes_entry = FCSpinner()
self.passes_entry.set_range(1, 999)
self.passes_entry.setObjectName("i_passes")
grid0.addWidget(passlabel, 8, 0)
grid0.addWidget(self.passes_entry, 8, 1, 1, 2)
# Overlap Entry
overlabel = QtWidgets.QLabel('%s:' % _('Overlap'))
overlabel.setToolTip(
_("How much (percentage) of the tool width to overlap each tool pass.")
)
self.overlap_entry = FCDoubleSpinner(suffix='%')
self.overlap_entry.set_precision(self.decimals)
self.overlap_entry.setWrapping(True)
self.overlap_entry.set_range(0.0000, 99.9999)
self.overlap_entry.setSingleStep(0.1)
self.overlap_entry.setObjectName("i_overlap")
grid0.addWidget(overlabel, 9, 0)
grid0.addWidget(self.overlap_entry, 9, 1, 1, 2)
# Milling Type Radio Button
self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
self.milling_type_label.setToolTip(
_("Milling type when the selected tool is of type: 'iso_op':\n"
"- climb / best for precision milling and to reduce tool usage\n"
"- conventional / useful when there is no backlash compensation")
)
self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
{'label': _('Conventional'), 'value': 'cv'}])
self.milling_type_radio.setToolTip(
_("Milling type when the selected tool is of type: 'iso_op':\n"
"- climb / best for precision milling and to reduce tool usage\n"
"- conventional / useful when there is no backlash compensation")
)
grid0.addWidget(self.milling_type_label, 10, 0)
grid0.addWidget(self.milling_type_radio, 10, 1, 1, 2)
# Follow
self.follow_label = QtWidgets.QLabel('%s:' % _('Follow'))
self.follow_label.setToolTip(
_("Generate a 'Follow' geometry.\n"
"This means that it will cut through\n"
"the middle of the trace.")
)
self.follow_cb = FCCheckBox()
self.follow_cb.setToolTip(_("Generate a 'Follow' geometry.\n"
"This means that it will cut through\n"
"the middle of the trace."))
self.follow_cb.setObjectName("i_follow")
grid0.addWidget(self.follow_label, 11, 0)
grid0.addWidget(self.follow_cb, 11, 1, 1, 2)
# Isolation Type
self.iso_type_label = QtWidgets.QLabel('%s:' % _('Isolation Type'))
self.iso_type_label.setToolTip(
_("Choose how the isolation will be executed:\n"
"- 'Full' -> complete isolation of polygons\n"
"- 'Ext' -> will isolate only on the outside\n"
"- 'Int' -> will isolate only on the inside\n"
"'Exterior' isolation is almost always possible\n"
"(with the right tool) but 'Interior'\n"
"isolation can be done only when there is an opening\n"
"inside of the polygon (e.g polygon is a 'doughnut' shape).")
)
self.iso_type_radio = RadioSet([{'label': _('Full'), 'value': 'full'},
{'label': _('Ext'), 'value': 'ext'},
{'label': _('Int'), 'value': 'int'}])
self.iso_type_radio.setObjectName("i_type")
grid0.addWidget(self.iso_type_label, 12, 0)
grid0.addWidget(self.iso_type_radio, 12, 1, 1, 2)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid0.addWidget(separator_line, 13, 0, 1, 3)
# Rest machining CheckBox
self.rest_cb = FCCheckBox('%s' % _("Rest"))
self.rest_cb.setObjectName("i_rest_machining")
self.rest_cb.setToolTip(
_("If checked, use 'rest machining'.\n"
"Basically it will isolate outside PCB features,\n"
"using the biggest tool and continue with the next tools,\n"
"from bigger to smaller, to isolate the copper features that\n"
"could not be cleared by previous tool, until there is\n"
"no more copper features to isolate or there are no more tools.\n"
"If not checked, use the standard algorithm.")
)
grid0.addWidget(self.rest_cb, 17, 0)
# Combine All Passes
self.combine_passes_cb = FCCheckBox(label=_('Combine'))
self.combine_passes_cb.setToolTip(
_("Combine all passes into one object")
)
self.combine_passes_cb.setObjectName("i_combine")
grid0.addWidget(self.combine_passes_cb, 17, 1)
# Exception Areas
self.except_cb = FCCheckBox(label=_('Except'))
self.except_cb.setToolTip(_("When the isolation geometry is generated,\n"
"by checking this, the area of the object below\n"
"will be subtracted from the isolation geometry."))
self.except_cb.setObjectName("i_except")
grid0.addWidget(self.except_cb, 17, 2)
# Isolation Scope
self.select_label = QtWidgets.QLabel('%s:' % _("Selection"))
self.select_label.setToolTip(
_("Isolation scope. Choose what to isolate:\n"
"- 'All' -> Isolate all the polygons in the object\n"
"- 'Area Selection' -> Isolate polygons within a selection area.\n"
"- 'Polygon Selection' -> Isolate a selection of polygons.\n"
"- 'Reference Object' - will process the area specified by another object.")
)
self.select_combo = FCComboBox()
self.select_combo.addItems(
[_("All"), _("Area Selection"), _("Polygon Selection"), _("Reference Object")]
)
self.select_combo.setObjectName("i_selection")
grid0.addWidget(self.select_label, 20, 0)
grid0.addWidget(self.select_combo, 20, 1, 1, 2)
# Area Shape
self.area_shape_label = QtWidgets.QLabel('%s:' % _("Shape"))
self.area_shape_label.setToolTip(
_("The kind of selection shape used for area selection.")
)
self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'},
{'label': _("Polygon"), 'value': 'polygon'}])
grid0.addWidget(self.area_shape_label, 21, 0)
grid0.addWidget(self.area_shape_radio, 21, 1, 1, 2)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid0.addWidget(separator_line, 22, 0, 1, 3)
# ## Plotting type
self.plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'},
{"label": _("Progressive"), "value": "progressive"}])
plotting_label = QtWidgets.QLabel('%s:' % _("Plotting"))
plotting_label.setToolTip(
_("- 'Normal' - normal plotting, done at the end of the job\n"
"- 'Progressive' - each shape is plotted after it is generated")
)
grid0.addWidget(plotting_label, 23, 0)
grid0.addWidget(self.plotting_radio, 23, 1, 1, 2)
self.layout.addStretch()

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCEntry, RadioSet, FCDoubleSpinner, FCComboBox, FCCheckBox from AppGUI.GUIElements import RadioSet, FCDoubleSpinner, FCComboBox, FCCheckBox, NumericalEvalTupleEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -45,7 +45,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
"Valid values: 0.3, 1.0") "Valid values: 0.3, 1.0")
) )
grid0.addWidget(ncctdlabel, 0, 0) grid0.addWidget(ncctdlabel, 0, 0)
self.ncc_tool_dia_entry = FCEntry(border_color='#0069A9') self.ncc_tool_dia_entry = NumericalEvalTupleEntry(border_color='#0069A9')
self.ncc_tool_dia_entry.setPlaceholderText(_("Comma separated values")) self.ncc_tool_dia_entry.setPlaceholderText(_("Comma separated values"))
grid0.addWidget(self.ncc_tool_dia_entry, 0, 1) grid0.addWidget(self.ncc_tool_dia_entry, 0, 1)
@@ -227,7 +227,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
# ], orientation='vertical', stretch=False) # ], orientation='vertical', stretch=False)
self.ncc_method_combo = FCComboBox() self.ncc_method_combo = FCComboBox()
self.ncc_method_combo.addItems( self.ncc_method_combo.addItems(
[_("Standard"), _("Seed"), _("Lines")] [_("Standard"), _("Seed"), _("Lines"), _("Combo")]
) )
grid0.addWidget(methodlabel, 12, 0) grid0.addWidget(methodlabel, 12, 0)
@@ -285,7 +285,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
grid0.addWidget(separator_line, 16, 0, 1, 2) grid0.addWidget(separator_line, 16, 0, 1, 2)
# Rest machining CheckBox # Rest machining CheckBox
self.ncc_rest_cb = FCCheckBox('%s' % _("Rest Machining")) self.ncc_rest_cb = FCCheckBox('%s' % _("Rest"))
self.ncc_rest_cb.setToolTip( self.ncc_rest_cb.setToolTip(
_("If checked, use 'rest machining'.\n" _("If checked, use 'rest machining'.\n"
"Basically it will clear copper outside PCB features,\n" "Basically it will clear copper outside PCB features,\n"
@@ -336,14 +336,14 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
grid0.addWidget(separator_line, 20, 0, 1, 2) grid0.addWidget(separator_line, 20, 0, 1, 2)
# ## Plotting type # ## Plotting type
self.ncc_plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'}, self.plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'},
{"label": _("Progressive"), "value": "progressive"}]) {"label": _("Progressive"), "value": "progressive"}])
plotting_label = QtWidgets.QLabel('%s:' % _("NCC Plotting")) plotting_label = QtWidgets.QLabel('%s:' % _("Plotting"))
plotting_label.setToolTip( plotting_label.setToolTip(
_("- 'Normal' - normal plotting, done at the end of the NCC job\n" _("- 'Normal' - normal plotting, done at the end of the job\n"
"- 'Progressive' - after each shape is generated it will be plotted.") "- 'Progressive' - each shape is plotted after it is generated")
) )
grid0.addWidget(plotting_label, 21, 0) grid0.addWidget(plotting_label, 21, 0)
grid0.addWidget(self.ncc_plotting_radio, 21, 1) grid0.addWidget(self.plotting_radio, 21, 1)
self.layout.addStretch() self.layout.addStretch()

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCEntry, RadioSet, FCDoubleSpinner, FCComboBox, FCCheckBox from AppGUI.GUIElements import RadioSet, FCDoubleSpinner, FCComboBox, FCCheckBox, NumericalEvalTupleEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -53,7 +53,7 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
) )
grid0.addWidget(ptdlabel, 0, 0) grid0.addWidget(ptdlabel, 0, 0)
self.painttooldia_entry = FCEntry(border_color='#0069A9') self.painttooldia_entry = NumericalEvalTupleEntry(border_color='#0069A9')
self.painttooldia_entry.setPlaceholderText(_("Comma separated values")) self.painttooldia_entry.setPlaceholderText(_("Comma separated values"))
grid0.addWidget(self.painttooldia_entry, 0, 1) grid0.addWidget(self.painttooldia_entry, 0, 1)
@@ -105,7 +105,7 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z')) cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
cutzlabel.setToolTip( cutzlabel.setToolTip(
_("Depth of cut into material. Negative value.\n" _("Depth of cut into material. Negative value.\n"
"In FlatCAM units.") "In application units.")
) )
self.cutz_entry = FCDoubleSpinner() self.cutz_entry = FCDoubleSpinner()
self.cutz_entry.set_precision(self.decimals) self.cutz_entry.set_precision(self.decimals)
@@ -114,7 +114,7 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
self.cutz_entry.setToolTip( self.cutz_entry.setToolTip(
_("Depth of cut into material. Negative value.\n" _("Depth of cut into material. Negative value.\n"
"In FlatCAM units.") "In application units.")
) )
grid0.addWidget(cutzlabel, 4, 0) grid0.addWidget(cutzlabel, 4, 0)
grid0.addWidget(self.cutz_entry, 4, 1) grid0.addWidget(self.cutz_entry, 4, 1)
@@ -241,8 +241,8 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
grid0.addWidget(separator_line, 13, 0, 1, 2) grid0.addWidget(separator_line, 13, 0, 1, 2)
self.rest_cb = FCCheckBox('%s' % _("Rest Machining")) self.rest_cb = FCCheckBox('%s' % _("Rest"))
self.rest_cb.setObjectName(_("Rest Machining")) self.rest_cb.setObjectName(_("Rest"))
self.rest_cb.setToolTip( self.rest_cb.setToolTip(
_("If checked, use 'rest machining'.\n" _("If checked, use 'rest machining'.\n"
"Basically it will clear copper outside PCB features,\n" "Basically it will clear copper outside PCB features,\n"
@@ -277,7 +277,7 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
# ) # )
self.selectmethod_combo = FCComboBox() self.selectmethod_combo = FCComboBox()
self.selectmethod_combo.addItems( self.selectmethod_combo.addItems(
[_("Polygon Selection"), _("Area Selection"), _("All Polygons"), _("Reference Object")] [_("Polygon Selection"), _("Area Selection"), _("All"), _("Reference Object")]
) )
grid0.addWidget(selectlabel, 15, 0) grid0.addWidget(selectlabel, 15, 0)
@@ -302,10 +302,10 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
# ## Plotting type # ## Plotting type
self.paint_plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'}, self.paint_plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'},
{"label": _("Progressive"), "value": "progressive"}]) {"label": _("Progressive"), "value": "progressive"}])
plotting_label = QtWidgets.QLabel('%s:' % _("Paint Plotting")) plotting_label = QtWidgets.QLabel('%s:' % _("Plotting"))
plotting_label.setToolTip( plotting_label.setToolTip(
_("- 'Normal' - normal plotting, done at the end of the Paint job\n" _("- 'Normal' - normal plotting, done at the end of the job\n"
"- 'Progressive' - after each shape is generated it will be plotted.") "- 'Progressive' - each shape is plotted after it is generated")
) )
grid0.addWidget(plotting_label, 20, 0) grid0.addWidget(plotting_label, 20, 0)
grid0.addWidget(self.paint_plotting_radio, 20, 1) grid0.addWidget(self.paint_plotting_radio, 20, 1)

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner, FCSpinner, RadioSet, FCCheckBox from AppGUI.GUIElements import FCDoubleSpinner, FCSpinner, RadioSet, FCCheckBox
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,19 +1,22 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.preferences.tools.ToolsSubPrefGroupUI import ToolsSubPrefGroupUI from AppGUI.preferences.tools.ToolsSubPrefGroupUI import ToolsSubPrefGroupUI
from flatcamGUI.preferences.tools.ToolsSolderpastePrefGroupUI import ToolsSolderpastePrefGroupUI from AppGUI.preferences.tools.ToolsSolderpastePrefGroupUI import ToolsSolderpastePrefGroupUI
from flatcamGUI.preferences.tools.ToolsTransformPrefGroupUI import ToolsTransformPrefGroupUI from AppGUI.preferences.tools.ToolsCornersPrefGroupUI import ToolsCornersPrefGroupUI
from flatcamGUI.preferences.tools.ToolsCalculatorsPrefGroupUI import ToolsCalculatorsPrefGroupUI from AppGUI.preferences.tools.ToolsTransformPrefGroupUI import ToolsTransformPrefGroupUI
from flatcamGUI.preferences.tools.ToolsPanelizePrefGroupUI import ToolsPanelizePrefGroupUI from AppGUI.preferences.tools.ToolsCalculatorsPrefGroupUI import ToolsCalculatorsPrefGroupUI
from flatcamGUI.preferences.tools.ToolsFilmPrefGroupUI import ToolsFilmPrefGroupUI from AppGUI.preferences.tools.ToolsPanelizePrefGroupUI import ToolsPanelizePrefGroupUI
from flatcamGUI.preferences.tools.ToolsPaintPrefGroupUI import ToolsPaintPrefGroupUI from AppGUI.preferences.tools.ToolsFilmPrefGroupUI import ToolsFilmPrefGroupUI
from flatcamGUI.preferences.tools.Tools2sidedPrefGroupUI import Tools2sidedPrefGroupUI from AppGUI.preferences.tools.Tools2sidedPrefGroupUI import Tools2sidedPrefGroupUI
from flatcamGUI.preferences.tools.ToolsCutoutPrefGroupUI import ToolsCutoutPrefGroupUI
from flatcamGUI.preferences.tools.ToolsNCCPrefGroupUI import ToolsNCCPrefGroupUI from AppGUI.preferences.tools.ToolsCutoutPrefGroupUI import ToolsCutoutPrefGroupUI
from AppGUI.preferences.tools.ToolsNCCPrefGroupUI import ToolsNCCPrefGroupUI
from AppGUI.preferences.tools.ToolsPaintPrefGroupUI import ToolsPaintPrefGroupUI
from AppGUI.preferences.tools.ToolsISOPrefGroupUI import ToolsISOPrefGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -35,6 +38,9 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
self.setLayout(self.layout) self.setLayout(self.layout)
self.decimals = decimals self.decimals = decimals
self.tools_iso_group = ToolsISOPrefGroupUI(decimals=self.decimals)
self.tools_iso_group.setMinimumWidth(220)
self.tools_ncc_group = ToolsNCCPrefGroupUI(decimals=self.decimals) self.tools_ncc_group = ToolsNCCPrefGroupUI(decimals=self.decimals)
self.tools_ncc_group.setMinimumWidth(220) self.tools_ncc_group.setMinimumWidth(220)
@@ -62,6 +68,9 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
self.tools_solderpaste_group = ToolsSolderpastePrefGroupUI(decimals=self.decimals) self.tools_solderpaste_group = ToolsSolderpastePrefGroupUI(decimals=self.decimals)
self.tools_solderpaste_group.setMinimumWidth(200) self.tools_solderpaste_group.setMinimumWidth(200)
self.tools_corners_group = ToolsCornersPrefGroupUI(decimals=self.decimals)
self.tools_corners_group.setMinimumWidth(200)
self.tools_sub_group = ToolsSubPrefGroupUI(decimals=self.decimals) self.tools_sub_group = ToolsSubPrefGroupUI(decimals=self.decimals)
self.tools_sub_group.setMinimumWidth(200) self.tools_sub_group.setMinimumWidth(200)
@@ -71,7 +80,7 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
self.vlay1 = QtWidgets.QVBoxLayout() self.vlay1 = QtWidgets.QVBoxLayout()
self.vlay1.addWidget(self.tools_paint_group) self.vlay1.addWidget(self.tools_paint_group)
self.vlay1.addWidget(self.tools_panelize_group) self.vlay1.addWidget(self.tools_iso_group)
self.vlay2 = QtWidgets.QVBoxLayout() self.vlay2 = QtWidgets.QVBoxLayout()
self.vlay2.addWidget(self.tools_transform_group) self.vlay2.addWidget(self.tools_transform_group)
@@ -84,6 +93,8 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
self.vlay4 = QtWidgets.QVBoxLayout() self.vlay4 = QtWidgets.QVBoxLayout()
self.vlay4.addWidget(self.tools_solderpaste_group) self.vlay4.addWidget(self.tools_solderpaste_group)
self.vlay4.addWidget(self.tools_corners_group)
self.vlay4.addWidget(self.tools_panelize_group)
self.layout.addLayout(self.vlay) self.layout.addLayout(self.vlay)
self.layout.addLayout(self.vlay1) self.layout.addLayout(self.vlay1)

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCEntry, FCDoubleSpinner, FCSpinner, FCComboBox from AppGUI.GUIElements import FCDoubleSpinner, FCSpinner, FCComboBox, NumericalEvalTupleEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -45,7 +45,7 @@ class ToolsSolderpastePrefGroupUI(OptionsGroupUI):
"The value of the diameter has to use the dot decimals separator.\n" "The value of the diameter has to use the dot decimals separator.\n"
"Valid values: 0.3, 1.0") "Valid values: 0.3, 1.0")
) )
self.nozzle_tool_dia_entry = FCEntry() self.nozzle_tool_dia_entry = NumericalEvalTupleEntry(border_color='#0069A9')
grid0.addWidget(nozzletdlabel, 0, 0) grid0.addWidget(nozzletdlabel, 0, 0)
grid0.addWidget(self.nozzle_tool_dia_entry, 0, 1) grid0.addWidget(self.nozzle_tool_dia_entry, 0, 1)
@@ -130,7 +130,7 @@ class ToolsSolderpastePrefGroupUI(OptionsGroupUI):
grid0.addWidget(self.z_toolchange_entry, 6, 1) grid0.addWidget(self.z_toolchange_entry, 6, 1)
# X,Y Toolchange location # X,Y Toolchange location
self.xy_toolchange_entry = FCEntry() self.xy_toolchange_entry = NumericalEvalTupleEntry(border_color='#0069A9')
self.xy_toolchange_label = QtWidgets.QLabel('%s:' % _("Toolchange X-Y")) self.xy_toolchange_label = QtWidgets.QLabel('%s:' % _("Toolchange X-Y"))
self.xy_toolchange_label.setToolTip( self.xy_toolchange_label.setToolTip(
_("The X,Y location for tool (nozzle) change.\n" _("The X,Y location for tool (nozzle) change.\n"

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCCheckBox from AppGUI.GUIElements import FCCheckBox
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCEntry from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, NumericalEvalTupleEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -31,7 +31,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
self.transform_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters")) self.transform_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
self.transform_label.setToolTip( self.transform_label.setToolTip(
_("Various transformations that can be applied\n" _("Various transformations that can be applied\n"
"on a FlatCAM object.") "on a application object.")
) )
self.layout.addWidget(self.transform_label) self.layout.addWidget(self.transform_label)
@@ -191,7 +191,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
"The 'x' in (x, y) will be used when using Flip on X and\n" "The 'x' in (x, y) will be used when using Flip on X and\n"
"the 'y' in (x, y) will be used when using Flip on Y and") "the 'y' in (x, y) will be used when using Flip on Y and")
) )
self.flip_ref_entry = FCEntry() self.flip_ref_entry = NumericalEvalTupleEntry(border_color='#0069A9')
grid0.addWidget(self.flip_ref_label, 14, 0, 1, 2) grid0.addWidget(self.flip_ref_label, 14, 0, 1, 2)
grid0.addWidget(self.flip_ref_entry, 15, 0, 1, 2) grid0.addWidget(self.flip_ref_entry, 15, 0, 1, 2)

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtGui from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCButton, FCTextArea, FCEntry from AppGUI.GUIElements import FCButton, FCTextArea, FCEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtGui from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import VerticalScrollArea, FCButton, FCTextArea, FCEntry from AppGUI.GUIElements import VerticalScrollArea, FCButton, FCTextArea, FCEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtGui from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCButton, FCTextArea, FCEntry from AppGUI.GUIElements import FCButton, FCTextArea, FCEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,11 +1,11 @@
from PyQt5 import QtWidgets, QtGui from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCButton, FCTextArea, FCEntry from AppGUI.GUIElements import FCButton, FCTextArea, FCEntry
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

View File

@@ -1,9 +1,9 @@
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from flatcamGUI.preferences.utilities.AutoCompletePrefGroupUI import AutoCompletePrefGroupUI from AppGUI.preferences.utilities.AutoCompletePrefGroupUI import AutoCompletePrefGroupUI
from flatcamGUI.preferences.utilities.FAGrbPrefGroupUI import FAGrbPrefGroupUI from AppGUI.preferences.utilities.FAGrbPrefGroupUI import FAGrbPrefGroupUI
from flatcamGUI.preferences.utilities.FAGcoPrefGroupUI import FAGcoPrefGroupUI from AppGUI.preferences.utilities.FAGcoPrefGroupUI import FAGcoPrefGroupUI
from flatcamGUI.preferences.utilities.FAExcPrefGroupUI import FAExcPrefGroupUI from AppGUI.preferences.utilities.FAExcPrefGroupUI import FAExcPrefGroupUI
class UtilPreferencesUI(QtWidgets.QWidget): class UtilPreferencesUI(QtWidgets.QWidget):

394
AppObjects/AppObject.py Normal file
View File

@@ -0,0 +1,394 @@
# ###########################################################
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
# Modified by Marius Stanciu (2020) #
# ###########################################################
from PyQt5 import QtCore
from AppObjects.ObjectCollection import *
from AppObjects.FlatCAMCNCJob import CNCJobObject
from AppObjects.FlatCAMDocument import DocumentObject
from AppObjects.FlatCAMExcellon import ExcellonObject
from AppObjects.FlatCAMGeometry import GeometryObject
from AppObjects.FlatCAMGerber import GerberObject
from AppObjects.FlatCAMScript import ScriptObject
import time
import traceback
# FlatCAM Translation
import gettext
import AppTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
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)
# Emitted when a object has been changed (like scaled, mirrored)
object_changed = QtCore.pyqtSignal(object)
# Emitted after object has been plotted.
# Calls 'on_zoom_fit' method to fit object in scene view in main thread to prevent drawing glitches.
object_plotted = QtCore.pyqtSignal(object)
plots_updated = QtCore.pyqtSignal()
def __init__(self, app):
super(AppObject, self).__init__()
self.app = app
self.inform = app.inform
# signals that are emitted when object state changes
self.object_created.connect(self.on_object_created)
self.object_changed.connect(self.on_object_changed)
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):
"""
Creates a new specialized FlatCAMObj and attaches it to the application,
this is, updates the GUI accordingly, any other records and plots it.
This method is thread-safe.
Notes:
* If the name is in use, the self.collection will modify it
when appending it to the collection. There is no need to handle
name conflicts here.
:param kind: The kind of object to create. One of 'gerber', 'excellon', 'cncjob' and 'geometry'.
:type kind: str
:param name: Name for the object.
:type name: str
:param initialize: Function to run after creation of the object but before it is attached to the application.
The function is called with 2 parameters: the new object and the App instance.
:type initialize: function
: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
:return: None
:rtype: None
"""
log.debug("AppObject.new_object()")
obj_plot = plot
obj_autoselected = autoselected
t0 = time.time() # Debug
# ## Create object
classdict = {
"gerber": GerberObject,
"excellon": ExcellonObject,
"cncjob": CNCJobObject,
"geometry": GeometryObject,
"script": ScriptObject,
"document": DocumentObject
}
log.debug("Calling object constructor...")
# Object creation/instantiation
obj = classdict[kind](name)
obj.units = self.app.options["units"]
# IMPORTANT
# The key names in defaults and options dictionary's are not random:
# they have to have in name first the type of the object (geometry, excellon, cncjob and gerber) or how it's
# called here, the 'kind' followed by an underline. Above the App default values from self.defaults are
# copied to self.options. After that, below, depending on the type of
# object that is created, it will strip the name of the object and the underline (if the original key was
# let's say "excellon_toolchange", it will strip the excellon_) and to the obj.options the key will become
# "toolchange"
for option in self.app.options:
if option.find(kind + "_") == 0:
oname = option[len(kind) + 1:]
obj.options[oname] = self.app.options[option]
obj.isHovering = False
obj.notHovering = True
# Initialize as per user request
# User must take care to implement initialize
# in a thread-safe way as is is likely that we
# have been invoked in a separate thread.
t1 = time.time()
log.debug("%f seconds before initialize()." % (t1 - t0))
try:
return_value = initialize(obj, self.app)
except Exception as e:
msg = '[ERROR_NOTCL] %s' % _("An internal error has occurred. See shell.\n")
msg += _("Object ({kind}) failed because: {error} \n\n").format(kind=kind, error=str(e))
msg += traceback.format_exc()
self.app.inform.emit(msg)
return "fail"
t2 = time.time()
log.debug("%f seconds executing initialize()." % (t2 - t1))
if return_value == 'fail':
log.debug("Object (%s) parsing and/or geometry creation failed." % kind)
return "fail"
# Check units and convert if necessary
# This condition CAN be true because initialize() can change obj.units
if self.app.options["units"].upper() != obj.units.upper():
self.app.inform.emit('%s: %s' % (_("Converting units to "), self.app.options["units"]))
obj.convert_units(self.app.options["units"])
t3 = time.time()
log.debug("%f seconds converting units." % (t3 - t2))
# Create the bounding box for the object and then add the results to the obj.options
# But not for Scripts or for Documents
if kind != 'document' and kind != 'script':
try:
xmin, ymin, xmax, ymax = obj.bounds()
obj.options['xmin'] = xmin
obj.options['ymin'] = ymin
obj.options['xmax'] = xmax
obj.options['ymax'] = ymax
except Exception as e:
log.warning("AppObject.new_object() -> The object has no bounds properties. %s" % str(e))
return "fail"
try:
if kind == 'excellon':
obj.fill_color = self.app.defaults["excellon_plot_fill"]
obj.outline_color = self.app.defaults["excellon_plot_line"]
if kind == 'gerber':
obj.fill_color = self.app.defaults["gerber_plot_fill"]
obj.outline_color = self.app.defaults["gerber_plot_line"]
except Exception as e:
log.warning("AppObject.new_object() -> setting colors error. %s" % str(e))
# update the KeyWords list with the name of the file
self.app.myKeywords.append(obj.options['name'])
log.debug("Moving new object back to main thread.")
# 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)
return obj
def new_excellon_object(self):
"""
Creates a new, blank Excellon object.
:return: None
"""
self.new_object('excellon', 'new_exc', lambda x, y: None, plot=False)
def new_geometry_object(self):
"""
Creates a new, blank and single-tool Geometry object.
:return: None
"""
def initialize(obj, app):
obj.multitool = False
self.new_object('geometry', 'new_geo', initialize, plot=False)
def new_gerber_object(self):
"""
Creates a new, blank Gerber object.
:return: None
"""
def initialize(grb_obj, app):
grb_obj.multitool = False
grb_obj.source_file = []
grb_obj.multigeo = False
grb_obj.follow = False
grb_obj.apertures = {}
grb_obj.solid_geometry = []
try:
grb_obj.options['xmin'] = 0
grb_obj.options['ymin'] = 0
grb_obj.options['xmax'] = 0
grb_obj.options['ymax'] = 0
except KeyError:
pass
self.new_object('gerber', 'new_grb', initialize, plot=False)
def new_script_object(self):
"""
Creates a new, blank TCL Script object.
:return: None
"""
# commands_list = "# AddCircle, AddPolygon, AddPolyline, AddRectangle, AlignDrill, " \
# "AlignDrillGrid, Bbox, Bounds, ClearShell, CopperClear,\n" \
# "# Cncjob, Cutout, Delete, Drillcncjob, ExportDXF, ExportExcellon, ExportGcode,\n" \
# "# ExportGerber, ExportSVG, Exteriors, Follow, GeoCutout, GeoUnion, GetNames,\n" \
# "# GetSys, ImportSvg, Interiors, Isolate, JoinExcellon, JoinGeometry, " \
# "ListSys, MillDrills,\n" \
# "# MillSlots, Mirror, New, NewExcellon, NewGeometry, NewGerber, Nregions, " \
# "Offset, OpenExcellon, OpenGCode, OpenGerber, OpenProject,\n" \
# "# Options, Paint, Panelize, PlotAl, PlotObjects, SaveProject, " \
# "SaveSys, Scale, SetActive, SetSys, SetOrigin, Skew, SubtractPoly,\n" \
# "# SubtractRectangle, Version, WriteGCode\n"
new_source_file = '# %s\n' % _('CREATE A NEW FLATCAM TCL SCRIPT') + \
'# %s:\n' % _('TCL Tutorial is here') + \
'# https://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html\n' + '\n\n' + \
'# %s:\n' % _("FlatCAM commands list")
new_source_file += '# %s\n\n' % _("Type >help< followed by Run Code for a list of FlatCAM Tcl Commands "
"(displayed in Tcl Shell).")
def initialize(obj, app):
obj.source_file = deepcopy(new_source_file)
outname = 'new_script'
self.new_object('script', outname, initialize, plot=False)
def new_document_object(self):
"""
Creates a new, blank Document object.
:return: None
"""
def initialize(obj, app):
obj.source_file = ""
self.new_object('document', 'new_document', initialize, plot=False)
def on_object_created(self, obj, plot, auto_select):
"""
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
"""
t0 = time.time() # DEBUG
log.debug("on_object_created()")
# The Collection might change the name if there is a collision
self.app.collection.append(obj)
# after adding the object to the collection always update the list of objects that are in the collection
self.app.all_objects_list = self.app.collection.get_list()
# self.app.inform.emit('[selected] %s created & selected: %s' %
# (str(obj.kind).capitalize(), str(obj.options['name'])))
if obj.kind == 'gerber':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='green',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'excellon':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='brown',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'cncjob':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='blue',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'geometry':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='red',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'script':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='orange',
name=str(obj.options['name']), tx=_("created/selected"))
)
elif obj.kind == 'document':
self.app.inform.emit('[selected] {kind} {tx}: <span style="color:{color};">{name}</span>'.format(
kind=obj.kind.capitalize(),
color='darkCyan',
name=str(obj.options['name']), tx=_("created/selected"))
)
# update the SHELL auto-completer model with the name of the new object
self.app.shell._edit.set_model_data(self.app.myKeywords)
if auto_select:
# select the just opened object but deselect the previous ones
self.app.collection.set_all_inactive()
self.app.collection.set_active(obj.options["name"])
else:
self.app.collection.set_all_inactive()
# here it is done the object plotting
def 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"])
else:
t_obj.plot()
t1 = time.time() # DEBUG
log.debug("%f seconds adding object and plotting." % (t1 - t0))
self.object_plotted.emit(t_obj)
# Send to worker
# self.worker.add_task(worker_task, [self])
if plot is True:
self.app.worker_task.emit({'fcn': task, 'params': [obj]})
def on_object_changed(self, obj):
"""
Called whenever the geometry of the object was changed in some way.
This require the update of it's bounding values so it can be the selected on canvas.
Update the bounding box data from obj.options
:param obj: the object that was changed
:return: None
"""
try:
xmin, ymin, xmax, ymax = obj.bounds()
except TypeError:
return
obj.options['xmin'] = xmin
obj.options['ymin'] = ymin
obj.options['xmax'] = xmax
obj.options['ymax'] = ymax
log.debug("Object changed, updating the bounding box data on self.options")
# delete the old selection shape
self.app.delete_selection_shape()
self.app.should_we_save = True
def on_object_plotted(self):
"""
Callback called whenever the plotted object needs to be fit into the viewport (canvas)
:return: None
"""
self.app.on_zoom_fit()

View File

@@ -14,8 +14,8 @@ from copy import deepcopy
from io import StringIO from io import StringIO
from datetime import datetime from datetime import datetime
from flatcamEditors.FlatCAMTextEditor import TextEditor from AppEditors.FlatCAMTextEditor import TextEditor
from flatcamObjects.FlatCAMObj import * from AppObjects.FlatCAMObj import *
from camlib import CNCjob from camlib import CNCjob
@@ -24,7 +24,7 @@ import sys
import math import math
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -504,17 +504,17 @@ class CNCJobObject(FlatCAMObj, CNCjob):
try: try:
dir_file_to_save = self.app.get_last_save_folder() + '/' + str(name) dir_file_to_save = self.app.get_last_save_folder() + '/' + str(name)
filename, _f = FCFileSaveDialog.get_saved_filename( filename, _f = FCFileSaveDialog.get_saved_filename(
caption=_("Export Machine Code ..."), caption=_("Export Code ..."),
directory=dir_file_to_save, directory=dir_file_to_save,
filter=_filter_ ext_filter=_filter_
) )
except TypeError: except TypeError:
filename, _f = FCFileSaveDialog.get_saved_filename(caption=_("Export Machine Code ..."), filter=_filter_) filename, _f = FCFileSaveDialog.get_saved_filename(caption=_("Export Code ..."), ext_filter=_filter_)
filename = str(filename) filename = str(filename)
if filename == '': if filename == '':
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export Machine Code cancelled ...")) self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export cancelled ..."))
return return
else: else:
if save_gcode is True: if save_gcode is True:
@@ -535,7 +535,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
if self.app.defaults["global_open_style"] is False: if self.app.defaults["global_open_style"] is False:
self.app.file_opened.emit("gcode", filename) self.app.file_opened.emit("gcode", filename)
self.app.file_saved.emit("gcode", filename) self.app.file_saved.emit("gcode", filename)
self.app.inform.emit('[success] %s: %s' % (_("Machine Code file saved to"), filename)) self.app.inform.emit('[success] %s: %s' % (_("File saved to"), filename))
def on_edit_code_click(self, *args): def on_edit_code_click(self, *args):
""" """
@@ -564,7 +564,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
# delete the absolute and relative position and messages in the infobar # delete the absolute and relative position and messages in the infobar
self.app.ui.position_label.setText("") self.app.ui.position_label.setText("")
self.app.ui.rel_position_label.setText("") # self.app.ui.rel_position_label.setText("")
# first clear previous text in text editor (if any) # first clear previous text in text editor (if any)
self.gcode_editor_tab.code_editor.clear() self.gcode_editor_tab.code_editor.clear()
@@ -989,7 +989,6 @@ class CNCJobObject(FlatCAMObj, CNCjob):
for key in self.cnc_tools: for key in self.cnc_tools:
ppg = self.cnc_tools[key]['data']['ppname_g'] ppg = self.cnc_tools[key]['data']['ppname_g']
if 'toolchange_custom' not in str(ppg).lower(): if 'toolchange_custom' not in str(ppg).lower():
print(ppg)
if self.ui.toolchange_cb.get_value(): if self.ui.toolchange_cb.get_value():
self.ui.toolchange_cb.set_value(False) self.ui.toolchange_cb.set_value(False)
self.app.inform.emit('[WARNING_NOTCL] %s' % self.app.inform.emit('[WARNING_NOTCL] %s' %
@@ -1107,7 +1106,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
except ValueError: except ValueError:
# we may have a tuple with only one element and a comma # we may have a tuple with only one element and a comma
dia_plot = [float(el) for el in self.options["tooldia"].split(',') if el != ''][0] dia_plot = [float(el) for el in self.options["tooldia"].split(',') if el != ''][0]
self.plot2(dia_plot, obj=self, visible=visible, kind=kind) self.plot2(tooldia=dia_plot, obj=self, visible=visible, kind=kind)
else: else:
# multiple tools usage # multiple tools usage
if self.cnc_tools: if self.cnc_tools:
@@ -1117,12 +1116,16 @@ class CNCJobObject(FlatCAMObj, CNCjob):
self.plot2(tooldia=tooldia, obj=self, visible=visible, gcode_parsed=gcode_parsed, kind=kind) self.plot2(tooldia=tooldia, obj=self, visible=visible, gcode_parsed=gcode_parsed, kind=kind)
# TODO: until the gcode parsed will be stored on each Excellon tool this will not get executed # TODO: until the gcode parsed will be stored on each Excellon tool this will not get executed
if self.exc_cnc_tools: # I do this so the travel lines thickness will reflect the tool diameter
for tooldia_key in self.exc_cnc_tools: # may work only for objects created within the app and not Gcode imported from elsewhere for which we
tooldia = float('%.*f' % (self.decimals, float(tooldia_key))) # don't know the origin
# gcode_parsed = self.cnc_tools[tooldia_key]['gcode_parsed'] if self.origin_kind == "excellon":
gcode_parsed = self.gcode_parsed if self.exc_cnc_tools:
self.plot2(tooldia=tooldia, obj=self, visible=visible, gcode_parsed=gcode_parsed, kind=kind) for tooldia_key in self.exc_cnc_tools:
tooldia = float('%.*f' % (self.decimals, float(tooldia_key)))
# gcode_parsed = self.exc_cnc_tools[tooldia_key]['gcode_parsed']
gcode_parsed = self.gcode_parsed
self.plot2(tooldia=tooldia, obj=self, visible=visible, gcode_parsed=gcode_parsed, kind=kind)
self.shapes.redraw() self.shapes.redraw()
except (ObjectDeleted, AttributeError): except (ObjectDeleted, AttributeError):

View File

@@ -10,11 +10,11 @@
# File modified by: Marius Stanciu # # File modified by: Marius Stanciu #
# ########################################################## # ##########################################################
from flatcamEditors.FlatCAMTextEditor import TextEditor from AppEditors.FlatCAMTextEditor import TextEditor
from flatcamObjects.FlatCAMObj import * from AppObjects.FlatCAMObj import *
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -284,6 +284,27 @@ class DocumentObject(FlatCAMObj):
self.ui.sel_color_entry.set_value(new_val) self.ui.sel_color_entry.set_value(new_val)
self.app.defaults['document_sel_color'] = new_val self.app.defaults['document_sel_color'] = new_val
def mirror(self, axis, point):
pass
def offset(self, vect):
pass
def rotate(self, angle, point):
pass
def scale(self, xfactor, yfactor=None, point=None):
pass
def skew(self, angle_x, angle_y, point):
pass
def buffer(self, distance, join, factor=None):
pass
def bounds(self, flatten=False):
return None, None, None, None
def to_dict(self): def to_dict(self):
""" """
Returns a representation of the object as a dictionary. Returns a representation of the object as a dictionary.

View File

@@ -15,13 +15,14 @@ from shapely.geometry import Point, LineString
from copy import deepcopy from copy import deepcopy
from flatcamParsers.ParseExcellon import Excellon from AppParsers.ParseExcellon import Excellon
from flatcamObjects.FlatCAMObj import * from AppObjects.FlatCAMObj import *
import itertools import itertools
import numpy as np
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -31,7 +32,7 @@ if '_' not in builtins.__dict__:
class ExcellonObject(FlatCAMObj, Excellon): class ExcellonObject(FlatCAMObj, Excellon):
""" """
Represents Excellon/Drill code. Represents Excellon/Drill code. An object stored in the FlatCAM objects collection (a dict)
""" """
ui_type = ExcellonObjectUI ui_type = ExcellonObjectUI
@@ -50,6 +51,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.options.update({ self.options.update({
"plot": True, "plot": True,
"solid": False, "solid": False,
"multicolored": False,
"operation": "drill", "operation": "drill",
"milling_type": "drills", "milling_type": "drills",
@@ -146,9 +148,11 @@ class ExcellonObject(FlatCAMObj, Excellon):
If only one object is in exc_list parameter then this function will copy that object in the exc_final If only one object is in exc_list parameter then this function will copy that object in the exc_final
:param exc_list: List or one object of ExcellonObject Objects to join. :param exc_list: List or one object of ExcellonObject Objects to join.
:param exc_final: Destination ExcellonObject object. :type exc_list: list
:return: None :param exc_final: Destination ExcellonObject object.
:type exc_final: class
:return: None
""" """
if decimals is None: if decimals is None:
@@ -316,6 +320,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
exc_final.create_geometry() exc_final.create_geometry()
def build_ui(self): def build_ui(self):
"""
Will (re)build the Excellon UI updating it (the tool table)
:return: None
:rtype:
"""
FlatCAMObj.build_ui(self) FlatCAMObj.build_ui(self)
# Area Exception - exclusion shape added signal # Area Exception - exclusion shape added signal
@@ -586,9 +596,9 @@ class ExcellonObject(FlatCAMObj, Excellon):
Configures the user interface for this object. Configures the user interface for this object.
Connects options to form fields. Connects options to form fields.
:param ui: User interface object. :param ui: User interface object.
:type ui: ExcellonObjectUI :type ui: ExcellonObjectUI
:return: None :return: None
""" """
FlatCAMObj.set_ui(self, ui) FlatCAMObj.set_ui(self, ui)
@@ -599,6 +609,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.form_fields.update({ self.form_fields.update({
"plot": self.ui.plot_cb, "plot": self.ui.plot_cb,
"solid": self.ui.solid_cb, "solid": self.ui.solid_cb,
"multicolored": self.ui.multicolored_cb,
"operation": self.ui.operation_radio, "operation": self.ui.operation_radio,
"milling_type": self.ui.milling_type_radio, "milling_type": self.ui.milling_type_radio,
@@ -700,6 +711,8 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click) self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
self.ui.solid_cb.stateChanged.connect(self.on_solid_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.ui.generate_cnc_button.clicked.connect(self.on_create_cncjob_button_click) self.ui.generate_cnc_button.clicked.connect(self.on_create_cncjob_button_click)
self.ui.generate_milling_button.clicked.connect(self.on_generate_milling_button_click) 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) self.ui.generate_milling_slots_button.clicked.connect(self.on_generate_milling_slots_button_click)
@@ -729,6 +742,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.ui.operation_radio.setEnabled(False) self.ui.operation_radio.setEnabled(False)
def ui_connect(self): def ui_connect(self):
"""
Will connect all signals in the Excellon UI that needs to be connected
:return: None
:rtype:
"""
# selective plotting # selective plotting
for row in range(self.ui.tools_table.rowCount() - 2): for row in range(self.ui.tools_table.rowCount() - 2):
@@ -751,6 +770,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
current_widget.returnPressed.connect(self.form_to_storage) current_widget.returnPressed.connect(self.form_to_storage)
def ui_disconnect(self): def ui_disconnect(self):
"""
Will disconnect all signals in the Excellon UI that needs to be disconnected
:return: None
:rtype:
"""
# selective plotting # selective plotting
for row in range(self.ui.tools_table.rowCount()): for row in range(self.ui.tools_table.rowCount()):
try: try:
@@ -793,6 +818,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
pass pass
def on_row_selection_change(self): def on_row_selection_change(self):
"""
Called when the user clicks on a row in Tools Table
:return: None
:rtype:
"""
self.ui_disconnect() self.ui_disconnect()
sel_rows = [] sel_rows = []
@@ -843,6 +874,14 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.ui_connect() self.ui_connect()
def storage_to_form(self, dict_storage): def storage_to_form(self, dict_storage):
"""
Will update the GUI with data from the "storage" in this case the dict self.tools
:param dict_storage: A dictionary holding the data relevant for gnerating Gcode from Excellon
:type dict_storage: dict
:return: None
:rtype:
"""
for form_key in self.form_fields: for form_key in self.form_fields:
for storage_key in dict_storage: for storage_key in dict_storage:
if form_key == storage_key and form_key not in \ if form_key == storage_key and form_key not in \
@@ -854,6 +893,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
pass pass
def form_to_storage(self): def form_to_storage(self):
"""
Will update the 'storage' attribute which is the dict self.tools with data collected from GUI
:return: None
:rtype:
"""
if self.ui.tools_table.rowCount() == 0: if self.ui.tools_table.rowCount() == 0:
# there is no tool in tool table so we can't save the GUI elements values to storage # there is no tool in tool table so we can't save the GUI elements values to storage
return return
@@ -882,6 +927,14 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.ui_connect() self.ui_connect()
def on_operation_type(self, val): def on_operation_type(self, val):
"""
Called by a RadioSet activated_custom signal
:param val: Parameter passes by the signal that called this method
:type val: str
:return: None
:rtype:
"""
if val == 'mill': if val == 'mill':
self.ui.mill_type_label.show() self.ui.mill_type_label.show()
self.ui.milling_type_radio.show() self.ui.milling_type_radio.show()
@@ -910,10 +963,10 @@ class ExcellonObject(FlatCAMObj, Excellon):
def get_selected_tools_list(self): def get_selected_tools_list(self):
""" """
Returns the keys to the self.tools dictionary corresponding Returns the keys to the self.tools dictionary corresponding
to the selections on the tool list in the GUI. to the selections on the tool list in the AppGUI.
:return: List of tools. :return: List of tools.
:rtype: list :rtype: list
""" """
return [str(x.text()) for x in self.ui.tools_table.selectedItems()] return [str(x.text()) for x in self.ui.tools_table.selectedItems()]
@@ -922,8 +975,8 @@ class ExcellonObject(FlatCAMObj, Excellon):
""" """
Returns a list of lists, each list in the list is made out of row elements Returns a list of lists, each list in the list is made out of row elements
:return: List of table_tools items. :return: List of table_tools items.
:rtype: list :rtype: list
""" """
table_tools_items = [] table_tools_items = []
for x in self.ui.tools_table.selectedItems(): for x in self.ui.tools_table.selectedItems():
@@ -951,7 +1004,21 @@ class ExcellonObject(FlatCAMObj, Excellon):
def export_excellon(self, whole, fract, e_zeros=None, form='dec', factor=1, slot_type='routing'): def export_excellon(self, whole, fract, e_zeros=None, form='dec', factor=1, slot_type='routing'):
""" """
Returns two values, first is a boolean , if 1 then the file has slots and second contain the Excellon code Returns two values, first is a boolean , if 1 then the file has slots and second contain the Excellon code
:return: has_slots and Excellon_code
:param whole: Integer part digits
:type whole: int
:param fract: Fractional part digits
:type fract: int
:param e_zeros: Excellon zeros suppression: LZ or TZ
:type e_zeros: str
:param form: Excellon format: 'dec',
:type form: str
:param factor: Conversion factor
:type factor: float
:param slot_type: How to treat slots: "routing" or "drilling"
:type slot_type: str
:return: A tuple: (has_slots, Excellon_code) -> (bool, str)
:rtype: tuple
""" """
excellon_code = '' excellon_code = ''
@@ -1118,13 +1185,25 @@ class ExcellonObject(FlatCAMObj, Excellon):
def generate_milling_drills(self, tools=None, outname=None, tooldia=None, plot=False, use_thread=False): def generate_milling_drills(self, tools=None, outname=None, tooldia=None, plot=False, use_thread=False):
""" """
Will generate an Geometry Object allowing to cut a drill hole instead of drilling it.
Note: This method is a good template for generic operations as Note: This method is a good template for generic operations as
it takes it's options from parameters or otherwise from the it takes it's options from parameters or otherwise from the
object's options and returns a (success, msg) tuple as feedback object's options and returns a (success, msg) tuple as feedback
for shell operations. for shell operations.
:return: Success/failure condition tuple (bool, str). :param tools: A list of tools where the drills are to be milled or a string: "all"
:rtype: tuple :type tools:
:param outname: the name of the resulting Geometry object
:type outname: str
:param tooldia: the tool diameter to be used in creation of the milling path (Geometry Object)
:type tooldia: float
:param plot: if to plot the resulting object
:type plot: bool
:param use_thread: if to use threading for creation of the Geometry object
:type use_thread: bool
:return: Success/failure condition tuple (bool, str).
:rtype: tuple
""" """
# Get the tools from the list. These are keys # Get the tools from the list. These are keys
@@ -1167,6 +1246,15 @@ class ExcellonObject(FlatCAMObj, Excellon):
return False, "Error: Milling tool is larger than hole." return False, "Error: Milling tool is larger than hole."
def geo_init(geo_obj, app_obj): def geo_init(geo_obj, app_obj):
"""
:param geo_obj: New object
:type geo_obj: GeometryObject
:param app_obj: App
:type app_obj: FlatCAMApp.App
:return:
:rtype:
"""
assert geo_obj.kind == 'geometry', "Initializer expected a GeometryObject, got %s" % type(geo_obj) assert geo_obj.kind == 'geometry', "Initializer expected a GeometryObject, got %s" % type(geo_obj)
# ## Add properties to the object # ## Add properties to the object
@@ -1179,7 +1267,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
geo_obj.options['Tools_in_use'] = tool_table_items geo_obj.options['Tools_in_use'] = tool_table_items
geo_obj.options['type'] = 'Excellon Geometry' geo_obj.options['type'] = 'Excellon Geometry'
geo_obj.options["cnctooldia"] = str(tooldia) geo_obj.options["cnctooldia"] = str(tooldia)
geo_obj.options["multidepth"] = self.options["multidepth"]
geo_obj.solid_geometry = [] geo_obj.solid_geometry = []
# in case that the tool used has the same diameter with the hole, and since the maximum resolution # in case that the tool used has the same diameter with the hole, and since the maximum resolution
@@ -1196,8 +1284,8 @@ class ExcellonObject(FlatCAMObj, Excellon):
Point(hole['point']).buffer(buffer_value).exterior) Point(hole['point']).buffer(buffer_value).exterior)
if use_thread: if use_thread:
def geo_thread(app_obj): def geo_thread(a_obj):
app_obj.new_object("geometry", outname, geo_init, plot=plot) a_obj.app_obj.new_object("geometry", outname, geo_init, plot=plot)
# Create a promise with the new name # Create a promise with the new name
self.app.collection.promise(outname) self.app.collection.promise(outname)
@@ -1205,19 +1293,31 @@ class ExcellonObject(FlatCAMObj, Excellon):
# Send to worker # Send to worker
self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]}) self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
else: else:
self.app.new_object("geometry", outname, geo_init, plot=plot) self.app.app_obj.new_object("geometry", outname, geo_init, plot=plot)
return True, "" return True, ""
def generate_milling_slots(self, tools=None, outname=None, tooldia=None, plot=True, use_thread=False): def generate_milling_slots(self, tools=None, outname=None, tooldia=None, plot=False, use_thread=False):
""" """
Will generate an Geometry Object allowing to cut/mill a slot hole.
Note: This method is a good template for generic operations as Note: This method is a good template for generic operations as
it takes it's options from parameters or otherwise from the it takes it's options from parameters or otherwise from the
object's options and returns a (success, msg) tuple as feedback object's options and returns a (success, msg) tuple as feedback
for shell operations. for shell operations.
:return: Success/failure condition tuple (bool, str). :param tools: A list of tools where the drills are to be milled or a string: "all"
:rtype: tuple :type tools:
:param outname: the name of the resulting Geometry object
:type outname: str
:param tooldia: the tool diameter to be used in creation of the milling path (Geometry Object)
:type tooldia: float
:param plot: if to plot the resulting object
:type plot: bool
:param use_thread: if to use threading for creation of the Geometry object
:type use_thread: bool
:return: Success/failure condition tuple (bool, str).
:rtype: tuple
""" """
# Get the tools from the list. These are keys # Get the tools from the list. These are keys
@@ -1258,7 +1358,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
return False, "Error: Milling tool is larger than hole." return False, "Error: Milling tool is larger than hole."
def geo_init(geo_obj, app_obj): def geo_init(geo_obj, app_obj):
assert geo_obj.kind == 'geometry' "Initializer expected a GeometryObject, got %s" % type(geo_obj) assert geo_obj.kind == 'geometry', "Initializer expected a GeometryObject, got %s" % type(geo_obj)
# ## Add properties to the object # ## Add properties to the object
@@ -1270,7 +1370,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
geo_obj.options['Tools_in_use'] = tool_table_items geo_obj.options['Tools_in_use'] = tool_table_items
geo_obj.options['type'] = 'Excellon Geometry' geo_obj.options['type'] = 'Excellon Geometry'
geo_obj.options["cnctooldia"] = str(tooldia) geo_obj.options["cnctooldia"] = str(tooldia)
geo_obj.options["multidepth"] = self.options["multidepth"]
geo_obj.solid_geometry = [] geo_obj.solid_geometry = []
# in case that the tool used has the same diameter with the hole, and since the maximum resolution # in case that the tool used has the same diameter with the hole, and since the maximum resolution
@@ -1300,8 +1400,8 @@ class ExcellonObject(FlatCAMObj, Excellon):
geo_obj.solid_geometry.append(poly) geo_obj.solid_geometry.append(poly)
if use_thread: if use_thread:
def geo_thread(app_obj): def geo_thread(a_obj):
app_obj.new_object("geometry", outname + '_slot', geo_init, plot=plot) a_obj.app_obj.new_object("geometry", outname + '_slot', geo_init, plot=plot)
# Create a promise with the new name # Create a promise with the new name
self.app.collection.promise(outname) self.app.collection.promise(outname)
@@ -1309,7 +1409,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
# Send to worker # Send to worker
self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]}) self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
else: else:
self.app.new_object("geometry", outname + '_slot', geo_init, plot=plot) self.app.app_obj.new_object("geometry", outname + '_slot', geo_init, plot=plot)
return True, "" return True, ""
@@ -1317,13 +1417,13 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.app.defaults.report_usage("excellon_on_create_milling_drills button") self.app.defaults.report_usage("excellon_on_create_milling_drills button")
self.read_form() self.read_form()
self.generate_milling_drills(use_thread=False) self.generate_milling_drills(use_thread=False, plot=True)
def on_generate_milling_slots_button_click(self, *args): def on_generate_milling_slots_button_click(self, *args):
self.app.defaults.report_usage("excellon_on_create_milling_slots_button") self.app.defaults.report_usage("excellon_on_create_milling_slots_button")
self.read_form() self.read_form()
self.generate_milling_slots(use_thread=False) self.generate_milling_slots(use_thread=False, plot=True)
def on_pp_changed(self): def on_pp_changed(self):
current_pp = self.ui.pp_excellon_name_cb.get_value() current_pp = self.ui.pp_excellon_name_cb.get_value()
@@ -1443,7 +1543,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
job_name = self.options["name"] + "_cnc" job_name = self.options["name"] + "_cnc"
pp_excellon_name = self.options["ppname_e"] pp_excellon_name = self.options["ppname_e"]
# Object initialization function for app.new_object() # Object initialization function for app.app_obj.new_object()
def job_init(job_obj, app_obj): def job_init(job_obj, app_obj):
assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj) assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj)
@@ -1506,9 +1606,9 @@ class ExcellonObject(FlatCAMObj, Excellon):
job_obj.create_geometry() job_obj.create_geometry()
# To be run in separate thread # To be run in separate thread
def job_thread(app_obj): def job_thread(a_obj):
with self.app.proc_container.new(_("Generating CNC Code")): with self.app.proc_container.new(_("Generating CNC Code")):
app_obj.new_object("cncjob", job_name, job_init) a_obj.app_obj.new_object("cncjob", job_name, job_init)
# Create promise for the new name. # Create promise for the new name.
self.app.collection.promise(job_name) self.app.collection.promise(job_name)
@@ -1656,6 +1756,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
self.read_form_item('solid') self.read_form_item('solid')
self.plot() self.plot()
def on_multicolored_cb_click(self, *args):
if self.muted_ui:
return
self.read_form_item('multicolored')
self.plot()
def on_plot_cb_click(self, *args): def on_plot_cb_click(self, *args):
if self.muted_ui: if self.muted_ui:
return return
@@ -1729,6 +1835,27 @@ class ExcellonObject(FlatCAMObj, Excellon):
if not FlatCAMObj.plot(self): if not FlatCAMObj.plot(self):
return return
if self.app.is_legacy is False:
def random_color():
r_color = np.random.rand(4)
r_color[3] = 1
return r_color
else:
def random_color():
while True:
r_color = np.random.rand(4)
r_color[3] = 1
new_color = '#'
for idx in range(len(r_color)):
new_color += '%x' % int(r_color[idx] * 255)
# do it until a valid color is generated
# a valid color has the # symbol, another 6 chars for the color and the last 2 chars for alpha
# for a total of 9 chars
if len(new_color) == 9:
break
return new_color
# try: # try:
# # Plot Excellon (All polygons?) # # Plot Excellon (All polygons?)
# if self.options["solid"]: # if self.options["solid"]:
@@ -1760,12 +1887,26 @@ class ExcellonObject(FlatCAMObj, Excellon):
try: try:
# Plot Excellon (All polygons?) # Plot Excellon (All polygons?)
if self.options["solid"]: if self.options["solid"]:
for geo in self.solid_geometry: # for geo in self.solid_geometry:
self.add_shape(shape=geo, # self.add_shape(shape=geo,
color=self.outline_color, # color=self.outline_color,
face_color=self.fill_color, # face_color=random_color() if self.options['multicolored'] else self.fill_color,
visible=visible, # visible=visible,
layer=2) # layer=2)
# plot polygons for each tool separately
for tool in self.tools:
# set the color here so we have one color for each tool
geo_color = random_color()
# tool is a dict also
for geo in self.tools[tool]["solid_geometry"]:
self.add_shape(shape=geo,
color=geo_color if self.options['multicolored'] else self.outline_color,
face_color=geo_color if self.options['multicolored'] else self.fill_color,
visible=visible,
layer=2)
else: else:
for geo in self.solid_geometry: for geo in self.solid_geometry:
self.add_shape(shape=geo.exterior, color='red', visible=visible) self.add_shape(shape=geo.exterior, color='red', visible=visible)

View File

@@ -15,7 +15,7 @@ import shapely.affinity as affinity
from camlib import Geometry from camlib import Geometry
from flatcamObjects.FlatCAMObj import * from AppObjects.FlatCAMObj import *
import ezdxf import ezdxf
import math import math
@@ -24,7 +24,7 @@ from copy import deepcopy
import traceback import traceback
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -52,6 +52,7 @@ class GeometryObject(FlatCAMObj, Geometry):
self.options.update({ self.options.update({
"plot": True, "plot": True,
"multicolored": False,
"cutz": -0.002, "cutz": -0.002,
"vtipdia": 0.1, "vtipdia": 0.1,
"vtipangle": 30, "vtipangle": 30,
@@ -304,25 +305,9 @@ class GeometryObject(FlatCAMObj, Geometry):
self.set_tool_offset_visibility(selected_row) self.set_tool_offset_visibility(selected_row)
# HACK: for whatever reasons the name in Selected tab is reverted to the original one after a successful rename # -----------------------------
# done in the collection view but only for Geometry objects. Perhaps some references remains. Should be fixed.
self.ui.name_entry.set_value(self.options['name'])
self.ui_connect()
self.ui.e_cut_entry.setDisabled(False) if self.ui.extracut_cb.get_value() else \
self.ui.e_cut_entry.setDisabled(True)
# set the text on tool_data_label after loading the object
sel_rows = []
sel_items = self.ui.geo_tools_table.selectedItems()
for it in sel_items:
sel_rows.append(it.row())
if len(sel_rows) > 1:
self.ui.tool_data_label.setText(
"<b>%s: <font color='#0000FF'>%s</font></b>" % (_('Parameters for'), _("Multiple Tools"))
)
# Build Exclusion Areas section # Build Exclusion Areas section
# -----------------------------
e_len = len(self.app.exc_areas.exclusion_areas_storage) e_len = len(self.app.exc_areas.exclusion_areas_storage)
self.ui.exclusion_table.setRowCount(e_len) self.ui.exclusion_table.setRowCount(e_len)
@@ -374,6 +359,27 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui.exclusion_table.setMinimumHeight(self.ui.exclusion_table.getHeight()) self.ui.exclusion_table.setMinimumHeight(self.ui.exclusion_table.getHeight())
self.ui.exclusion_table.setMaximumHeight(self.ui.exclusion_table.getHeight()) self.ui.exclusion_table.setMaximumHeight(self.ui.exclusion_table.getHeight())
# End Build Exclusion Areas
# -----------------------------
# HACK: for whatever reasons the name in Selected tab is reverted to the original one after a successful rename
# done in the collection view but only for Geometry objects. Perhaps some references remains. Should be fixed.
self.ui.name_entry.set_value(self.options['name'])
self.ui_connect()
self.ui.e_cut_entry.setDisabled(False) if self.ui.extracut_cb.get_value() else \
self.ui.e_cut_entry.setDisabled(True)
# set the text on tool_data_label after loading the object
sel_rows = []
sel_items = self.ui.geo_tools_table.selectedItems()
for it in sel_items:
sel_rows.append(it.row())
if len(sel_rows) > 1:
self.ui.tool_data_label.setText(
"<b>%s: <font color='#0000FF'>%s</font></b>" % (_('Parameters for'), _("Multiple Tools"))
)
def set_ui(self, ui): def set_ui(self, ui):
FlatCAMObj.set_ui(self, ui) FlatCAMObj.set_ui(self, ui)
@@ -391,6 +397,7 @@ class GeometryObject(FlatCAMObj, Geometry):
self.form_fields.update({ self.form_fields.update({
"plot": self.ui.plot_cb, "plot": self.ui.plot_cb,
"multicolored": self.ui.multicolored_cb,
"cutz": self.ui.cutz_entry, "cutz": self.ui.cutz_entry,
"vtipdia": self.ui.tipdia_entry, "vtipdia": self.ui.tipdia_entry,
"vtipangle": self.ui.tipangle_entry, "vtipangle": self.ui.tipangle_entry,
@@ -586,6 +593,8 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui.extracut_cb.toggled.connect(lambda state: self.ui.e_cut_entry.setDisabled(not state)) self.ui.extracut_cb.toggled.connect(lambda state: self.ui.e_cut_entry.setDisabled(not state))
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click) self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
self.ui.multicolored_cb.stateChanged.connect(self.on_multicolored_cb_click)
self.ui.generate_cnc_button.clicked.connect(self.on_generatecnc_button_click) self.ui.generate_cnc_button.clicked.connect(self.on_generatecnc_button_click)
self.ui.paint_tool_button.clicked.connect(lambda: self.app.paint_tool.run(toggle=False)) self.ui.paint_tool_button.clicked.connect(lambda: self.app.paint_tool.run(toggle=False))
self.ui.generate_ncc_button.clicked.connect(lambda: self.app.ncclear_tool.run(toggle=False)) self.ui.generate_ncc_button.clicked.connect(lambda: self.app.ncclear_tool.run(toggle=False))
@@ -652,8 +661,7 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui.tool_offset_entry.get_value().replace(',', '.') self.ui.tool_offset_entry.get_value().replace(',', '.')
) )
except ValueError: except ValueError:
self.app.inform.emit('[ERROR_NOTCL] %s' % self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number."))
_("Wrong value format entered, use a number."))
return return
def ui_connect(self): def ui_connect(self):
@@ -661,6 +669,7 @@ class GeometryObject(FlatCAMObj, Geometry):
# changes in geometry UI # changes in geometry UI
for i in self.param_fields: for i in self.param_fields:
current_widget = self.param_fields[i] current_widget = self.param_fields[i]
if isinstance(current_widget, FCCheckBox): if isinstance(current_widget, FCCheckBox):
current_widget.stateChanged.connect(self.gui_form_to_storage) current_widget.stateChanged.connect(self.gui_form_to_storage)
elif isinstance(current_widget, FCComboBox): elif isinstance(current_widget, FCComboBox):
@@ -931,7 +940,7 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui_connect() self.ui_connect()
self.build_ui() self.build_ui()
# if there is no tool left in the Tools Table, enable the parameters GUI # if there is no tool left in the Tools Table, enable the parameters AppGUI
if self.ui.geo_tools_table.rowCount() != 0: if self.ui.geo_tools_table.rowCount() != 0:
self.ui.geo_param_frame.setDisabled(False) self.ui.geo_param_frame.setDisabled(False)
@@ -1007,7 +1016,7 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui_connect() self.ui_connect()
self.build_ui() self.build_ui()
# if there is no tool left in the Tools Table, enable the parameters GUI # if there is no tool left in the Tools Table, enable the parameters AppGUI
if self.ui.geo_tools_table.rowCount() != 0: if self.ui.geo_tools_table.rowCount() != 0:
self.ui.geo_param_frame.setDisabled(False) self.ui.geo_param_frame.setDisabled(False)
@@ -1188,7 +1197,7 @@ class GeometryObject(FlatCAMObj, Geometry):
obj_active.options['xmax'] = 0 obj_active.options['xmax'] = 0
obj_active.options['ymax'] = 0 obj_active.options['ymax'] = 0
# if there is no tool left in the Tools Table, disable the parameters GUI # if there is no tool left in the Tools Table, disable the parameters AppGUI
if self.ui.geo_tools_table.rowCount() == 0: if self.ui.geo_tools_table.rowCount() == 0:
self.ui.geo_param_frame.setDisabled(True) self.ui.geo_param_frame.setDisabled(True)
@@ -1382,16 +1391,18 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui_connect() self.ui_connect()
def gui_form_to_storage(self): def gui_form_to_storage(self):
self.ui_disconnect()
if self.ui.geo_tools_table.rowCount() == 0: if self.ui.geo_tools_table.rowCount() == 0:
# there is no tool in tool table so we can't save the GUI elements values to storage # there is no tool in tool table so we can't save the GUI elements values to storage
log.debug("GeometryObject.gui_form_to_storage() --> no tool in Tools Table, aborting.") log.debug("GeometryObject.gui_form_to_storage() --> no tool in Tools Table, aborting.")
return return
self.ui_disconnect()
widget_changed = self.sender() widget_changed = self.sender()
try: try:
widget_idx = self.ui.grid3.indexOf(widget_changed) widget_idx = self.ui.grid3.indexOf(widget_changed)
except Exception: except Exception as e:
log.debug("GeometryObject.gui_form_to_storage() -- wdg index -> %s" % str(e))
return return
# those are the indexes for the V-Tip Dia and V-Tip Angle, if edited calculate the new Cut Z # those are the indexes for the V-Tip Dia and V-Tip Angle, if edited calculate the new Cut Z
@@ -1748,7 +1759,7 @@ class GeometryObject(FlatCAMObj, Geometry):
:param tools_dict: a dictionary that holds the whole data needed to create the Gcode :param tools_dict: a dictionary that holds the whole data needed to create the Gcode
(including the solid_geometry) (including the solid_geometry)
:param tools_in_use: the tools that are used, needed by some preprocessors :param tools_in_use: the tools that are used, needed by some preprocessors
:type tools_in_use list of lists, each list in the list is made out of row elements of tools table from GUI :type tools_in_use list of lists, each list in the list is made out of row elements of tools table from AppGUI
:param segx: number of segments on the X axis, for auto-levelling :param segx: number of segments on the X axis, for auto-levelling
:param segy: number of segments on the Y axis, for auto-levelling :param segy: number of segments on the Y axis, for auto-levelling
:param plot: if True the generated object will be plotted; if False will not be plotted :param plot: if True the generated object will be plotted; if False will not be plotted
@@ -1778,7 +1789,7 @@ class GeometryObject(FlatCAMObj, Geometry):
self.app.inform.emit(msg) self.app.inform.emit(msg)
return return
# Object initialization function for app.new_object() # Object initialization function for app.app_obj.new_object()
# RUNNING ON SEPARATE THREAD! # RUNNING ON SEPARATE THREAD!
def job_init_single_geometry(job_obj, app_obj): def job_init_single_geometry(job_obj, app_obj):
log.debug("Creating a CNCJob out of a single-geometry") log.debug("Creating a CNCJob out of a single-geometry")
@@ -1918,7 +1929,7 @@ class GeometryObject(FlatCAMObj, Geometry):
}) })
dia_cnc_dict.clear() dia_cnc_dict.clear()
# Object initialization function for app.new_object() # Object initialization function for app.app_obj.new_object()
# RUNNING ON SEPARATE THREAD! # RUNNING ON SEPARATE THREAD!
def job_init_multi_geometry(job_obj, app_obj): def job_init_multi_geometry(job_obj, app_obj):
log.debug("Creating a CNCJob out of a multi-geometry") log.debug("Creating a CNCJob out of a multi-geometry")
@@ -2072,15 +2083,15 @@ class GeometryObject(FlatCAMObj, Geometry):
if use_thread: if use_thread:
# To be run in separate thread # To be run in separate thread
def job_thread(app_obj): def job_thread(a_obj):
if self.multigeo is False: if self.multigeo is False:
with self.app.proc_container.new(_("Generating CNC Code")): with self.app.proc_container.new(_("Generating CNC Code")):
if app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot) != 'fail': if a_obj.app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot) != 'fail':
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname)) a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
else: else:
with self.app.proc_container.new(_("Generating CNC Code")): with self.app.proc_container.new(_("Generating CNC Code")):
if app_obj.new_object("cncjob", outname, job_init_multi_geometry) != 'fail': if a_obj.app_obj.new_object("cncjob", outname, job_init_multi_geometry) != 'fail':
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname)) a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
# Create a promise with the name # Create a promise with the name
self.app.collection.promise(outname) self.app.collection.promise(outname)
@@ -2088,23 +2099,15 @@ class GeometryObject(FlatCAMObj, Geometry):
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]}) self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
else: else:
if self.solid_geometry: if self.solid_geometry:
self.app.new_object("cncjob", outname, job_init_single_geometry, plot=plot) self.app.app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot)
else: else:
self.app.new_object("cncjob", outname, job_init_multi_geometry, plot=plot) self.app.app_obj.new_object("cncjob", outname, job_init_multi_geometry, plot=plot)
def generatecncjob( def generatecncjob(self, outname=None, dia=None, offset=None, z_cut=None, z_move=None,
self, outname=None, feedrate=None, feedrate_z=None, feedrate_rapid=None, spindlespeed=None, dwell=None, dwelltime=None,
dia=None, offset=None, multidepth=None, dpp=None, toolchange=None, toolchangez=None, toolchangexy=None,
z_cut=None, z_move=None, extracut=None, extracut_length=None, startz=None, endz=None, endxy=None, pp=None, segx=None, segy=None,
feedrate=None, feedrate_z=None, feedrate_rapid=None, use_thread=True, plot=True):
spindlespeed=None, dwell=None, dwelltime=None,
multidepth=None, depthperpass=None,
toolchange=None, toolchangez=None, toolchangexy=None,
extracut=None, extracut_length=None, startz=None, endz=None,
pp=None,
segx=None, segy=None,
use_thread=True,
plot=True):
""" """
Only used by the TCL Command Cncjob. Only used by the TCL Command Cncjob.
Creates a CNCJob out of this Geometry object. The actual Creates a CNCJob out of this Geometry object. The actual
@@ -2123,14 +2126,17 @@ class GeometryObject(FlatCAMObj, Geometry):
:param dwell: :param dwell:
:param dwelltime: :param dwelltime:
:param multidepth: :param multidepth:
:param depthperpass: :param dpp: Depth for each pass when multidepth parameter is True
:param toolchange: :param toolchange:
:param toolchangez: :param toolchangez:
:param toolchangexy: :param toolchangexy: A sequence ox X,Y coordinates: a 2-length tuple or a string.
Coordinates in X,Y plane for the Toolchange event
:param extracut: :param extracut:
:param extracut_length: :param extracut_length:
:param startz: :param startz:
:param endz: :param endz:
:param endxy: A sequence ox X,Y coordinates: a 2-length tuple or a string.
Coordinates in X, Y plane for the last move after ending the job.
:param pp: Name of the preprocessor :param pp: Name of the preprocessor
:param segx: :param segx:
:param segy: :param segy:
@@ -2150,7 +2156,7 @@ class GeometryObject(FlatCAMObj, Geometry):
feedrate_rapid = feedrate_rapid if feedrate_rapid is not None else float(self.options["feedrate_rapid"]) feedrate_rapid = feedrate_rapid if feedrate_rapid is not None else float(self.options["feedrate_rapid"])
multidepth = multidepth if multidepth is not None else self.options["multidepth"] multidepth = multidepth if multidepth is not None else self.options["multidepth"]
depthperpass = depthperpass if depthperpass is not None else float(self.options["depthperpass"]) depthperpass = dpp if dpp is not None else float(self.options["depthperpass"])
segx = segx if segx is not None else float(self.app.defaults['geometry_segx']) segx = segx if segx is not None else float(self.app.defaults['geometry_segx'])
segy = segy if segy is not None else float(self.app.defaults['geometry_segy']) segy = segy if segy is not None else float(self.app.defaults['geometry_segy'])
@@ -2160,10 +2166,21 @@ class GeometryObject(FlatCAMObj, Geometry):
startz = startz if startz is not None else self.options["startz"] startz = startz if startz is not None else self.options["startz"]
endz = endz if endz is not None else float(self.options["endz"]) endz = endz if endz is not None else float(self.options["endz"])
endxy = self.options["endxy"]
endxy = endxy if endxy else self.options["endxy"]
if isinstance(endxy, str):
endxy = re.sub('[()\[\]]', '', endxy)
if endxy and endxy != '':
endxy = [float(eval(a)) for a in endxy.split(",")]
toolchangez = toolchangez if toolchangez else float(self.options["toolchangez"]) toolchangez = toolchangez if toolchangez else float(self.options["toolchangez"])
toolchangexy = toolchangexy if toolchangexy else self.options["toolchangexy"] toolchangexy = toolchangexy if toolchangexy else self.options["toolchangexy"]
if isinstance(toolchangexy, str):
toolchangexy = re.sub('[()\[\]]', '', toolchangexy)
if toolchangexy and toolchangexy != '':
toolchangexy = [float(eval(a)) for a in toolchangexy.split(",")]
toolchange = toolchange if toolchange else self.options["toolchange"] toolchange = toolchange if toolchange else self.options["toolchange"]
offset = offset if offset else 0.0 offset = offset if offset else 0.0
@@ -2175,7 +2192,7 @@ class GeometryObject(FlatCAMObj, Geometry):
ppname_g = pp if pp else self.options["ppname_g"] ppname_g = pp if pp else self.options["ppname_g"]
# Object initialization function for app.new_object() # Object initialization function for app.app_obj.new_object()
# RUNNING ON SEPARATE THREAD! # RUNNING ON SEPARATE THREAD!
def job_init(job_obj, app_obj): def job_init(job_obj, app_obj):
assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj) assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj)
@@ -2224,7 +2241,7 @@ class GeometryObject(FlatCAMObj, Geometry):
# To be run in separate thread # To be run in separate thread
def job_thread(app_obj): def job_thread(app_obj):
with self.app.proc_container.new(_("Generating CNC Code")): with self.app.proc_container.new(_("Generating CNC Code")):
app_obj.new_object("cncjob", outname, job_init, plot=plot) app_obj.app_obj.new_object("cncjob", outname, job_init, plot=plot)
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created")), outname) app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created")), outname)
# Create a promise with the name # Create a promise with the name
@@ -2232,7 +2249,7 @@ class GeometryObject(FlatCAMObj, Geometry):
# Send to worker # Send to worker
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]}) self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
else: else:
self.app.new_object("cncjob", outname, job_init, plot=plot) self.app.app_obj.new_object("cncjob", outname, job_init, plot=plot)
# def on_plot_cb_click(self, *args): # def on_plot_cb_click(self, *args):
# if self.muted_ui: # if self.muted_ui:
@@ -2652,6 +2669,27 @@ class GeometryObject(FlatCAMObj, Geometry):
if not FlatCAMObj.plot(self): if not FlatCAMObj.plot(self):
return return
if self.app.is_legacy is False:
def random_color():
r_color = np.random.rand(4)
r_color[3] = 1
return r_color
else:
def random_color():
while True:
r_color = np.random.rand(4)
r_color[3] = 1
new_color = '#'
for idx in range(len(r_color)):
new_color += '%x' % int(r_color[idx] * 255)
# do it until a valid color is generated
# a valid color has the # symbol, another 6 chars for the color and the last 2 chars for alpha
# for a total of 9 chars
if len(new_color) == 9:
break
return new_color
try: try:
# plot solid geometries found as members of self.tools attribute dict # plot solid geometries found as members of self.tools attribute dict
# for MultiGeo # for MultiGeo
@@ -2659,7 +2697,8 @@ class GeometryObject(FlatCAMObj, Geometry):
for tooluid_key in self.tools: for tooluid_key in self.tools:
solid_geometry = self.tools[tooluid_key]['solid_geometry'] solid_geometry = self.tools[tooluid_key]['solid_geometry']
self.plot_element(solid_geometry, visible=visible, self.plot_element(solid_geometry, visible=visible,
color=self.app.defaults["geometry_plot_line"]) color=random_color() if self.options['multicolored']
else self.app.defaults["geometry_plot_line"])
else: else:
# plot solid geometry that may be an direct attribute of the geometry object # plot solid geometry that may be an direct attribute of the geometry object
# for SingleGeo # for SingleGeo
@@ -2727,6 +2766,12 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui.plot_cb.setChecked(True) self.ui.plot_cb.setChecked(True)
self.ui_connect() self.ui_connect()
def on_multicolored_cb_click(self, *args):
if self.muted_ui:
return
self.read_form_item('multicolored')
self.plot()
@staticmethod @staticmethod
def merge(geo_list, geo_final, multigeo=None): def merge(geo_list, geo_final, multigeo=None):
""" """

View File

@@ -14,15 +14,15 @@
from shapely.geometry import Point, Polygon, MultiPolygon, MultiLineString, LineString, LinearRing from shapely.geometry import Point, Polygon, MultiPolygon, MultiLineString, LineString, LinearRing
from shapely.ops import cascaded_union from shapely.ops import cascaded_union
from flatcamParsers.ParseGerber import Gerber from AppParsers.ParseGerber import Gerber
from flatcamObjects.FlatCAMObj import * from AppObjects.FlatCAMObj import *
import math import math
import numpy as np import numpy as np
from copy import deepcopy from copy import deepcopy
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -115,23 +115,13 @@ class GerberObject(FlatCAMObj, Gerber):
"plot": True, "plot": True,
"multicolored": False, "multicolored": False,
"solid": False, "solid": False,
"tool_type": 'circular',
"vtipdia": 0.1,
"vtipangle": 30,
"vcutz": -0.05,
"isotooldia": 0.016,
"isopasses": 1,
"isooverlap": 15,
"milling_type": "cl",
"combine_passes": True,
"noncoppermargin": 0.0, "noncoppermargin": 0.0,
"noncopperrounded": False, "noncopperrounded": False,
"bboxmargin": 0.0, "bboxmargin": 0.0,
"bboxrounded": False, "bboxrounded": False,
"aperture_display": False, "aperture_display": False,
"follow": False, "follow": False,
"iso_scope": 'all', "milling_type": 'cl',
"iso_type": 'full'
}) })
# type of isolation: 0 = exteriors, 1 = interiors, 2 = complete isolation (both interiors and exteriors) # type of isolation: 0 = exteriors, 1 = interiors, 2 = complete isolation (both interiors and exteriors)
@@ -197,88 +187,44 @@ class GerberObject(FlatCAMObj, Gerber):
"plot": self.ui.plot_cb, "plot": self.ui.plot_cb,
"multicolored": self.ui.multicolored_cb, "multicolored": self.ui.multicolored_cb,
"solid": self.ui.solid_cb, "solid": self.ui.solid_cb,
"tool_type": self.ui.tool_type_radio,
"vtipdia": self.ui.tipdia_spinner,
"vtipangle": self.ui.tipangle_spinner,
"vcutz": self.ui.cutz_spinner,
"isotooldia": self.ui.iso_tool_dia_entry,
"isopasses": self.ui.iso_width_entry,
"isooverlap": self.ui.iso_overlap_entry,
"milling_type": self.ui.milling_type_radio,
"combine_passes": self.ui.combine_passes_cb,
"noncoppermargin": self.ui.noncopper_margin_entry, "noncoppermargin": self.ui.noncopper_margin_entry,
"noncopperrounded": self.ui.noncopper_rounded_cb, "noncopperrounded": self.ui.noncopper_rounded_cb,
"bboxmargin": self.ui.bbmargin_entry, "bboxmargin": self.ui.bbmargin_entry,
"bboxrounded": self.ui.bbrounded_cb, "bboxrounded": self.ui.bbrounded_cb,
"aperture_display": self.ui.aperture_table_visibility_cb, "aperture_display": self.ui.aperture_table_visibility_cb,
"follow": self.ui.follow_cb, "follow": self.ui.follow_cb
"iso_scope": self.ui.iso_scope_radio,
"iso_type": self.ui.iso_type_radio
}) })
# Fill form fields only on object create # Fill form fields only on object create
self.to_form() self.to_form()
assert isinstance(self.ui, GerberObjectUI) assert isinstance(self.ui, GerberObjectUI)
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click) self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
self.ui.solid_cb.stateChanged.connect(self.on_solid_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.ui.multicolored_cb.stateChanged.connect(self.on_multicolored_cb_click)
self.ui.generate_iso_button.clicked.connect(self.on_iso_button_click)
# Tools
self.ui.iso_button.clicked.connect(self.app.isolation_tool.run)
self.ui.generate_ncc_button.clicked.connect(self.app.ncclear_tool.run) self.ui.generate_ncc_button.clicked.connect(self.app.ncclear_tool.run)
self.ui.generate_cutout_button.clicked.connect(self.app.cutout_tool.run) self.ui.generate_cutout_button.clicked.connect(self.app.cutout_tool.run)
self.ui.generate_bb_button.clicked.connect(self.on_generatebb_button_click) self.ui.generate_bb_button.clicked.connect(self.on_generatebb_button_click)
self.ui.generate_noncopper_button.clicked.connect(self.on_generatenoncopper_button_click) self.ui.generate_noncopper_button.clicked.connect(self.on_generatenoncopper_button_click)
self.ui.aperture_table_visibility_cb.stateChanged.connect(self.on_aperture_table_visibility_change) self.ui.aperture_table_visibility_cb.stateChanged.connect(self.on_aperture_table_visibility_change)
self.ui.follow_cb.stateChanged.connect(self.on_follow_cb_click) self.ui.follow_cb.stateChanged.connect(self.on_follow_cb_click)
# set the model for the Area Exception comboboxes
self.ui.obj_combo.setModel(self.app.collection)
self.ui.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
self.ui.obj_combo.is_last = True
self.ui.obj_combo.obj_type = {
_("Gerber"): "Gerber", _("Geometry"): "Geometry"
}[self.ui.type_obj_combo.get_value()]
self.on_type_obj_index_changed()
self.ui.type_obj_combo.currentIndexChanged.connect(self.on_type_obj_index_changed)
self.ui.tool_type_radio.activated_custom.connect(self.on_tool_type_change)
# establish visibility for the GUI elements found in the slot function
self.ui.tool_type_radio.activated_custom.emit(self.options['tool_type'])
# Show/Hide Advanced Options # Show/Hide Advanced Options
if self.app.defaults["global_app_level"] == 'b': if self.app.defaults["global_app_level"] == 'b':
self.ui.level.setText('<span style="color:green;"><b>%s</b></span>' % _('Basic')) self.ui.level.setText('<span style="color:green;"><b>%s</b></span>' % _('Basic'))
self.options['tool_type'] = 'circular'
self.ui.tool_type_label.hide()
self.ui.tool_type_radio.hide()
# override the Preferences Value; in Basic mode the Tool Type is always Circular ('C1')
self.ui.tool_type_radio.set_value('circular')
self.ui.tipdialabel.hide()
self.ui.tipdia_spinner.hide()
self.ui.tipanglelabel.hide()
self.ui.tipangle_spinner.hide()
self.ui.cutzlabel.hide()
self.ui.cutz_spinner.hide()
self.ui.apertures_table_label.hide() self.ui.apertures_table_label.hide()
self.ui.aperture_table_visibility_cb.hide() self.ui.aperture_table_visibility_cb.hide()
self.ui.milling_type_label.hide()
self.ui.milling_type_radio.hide()
self.ui.iso_type_label.hide()
self.ui.iso_type_radio.hide()
self.ui.follow_cb.hide() self.ui.follow_cb.hide()
self.ui.except_cb.setChecked(False)
self.ui.except_cb.hide()
else: else:
self.ui.level.setText('<span style="color:red;"><b>%s</b></span>' % _('Advanced')) self.ui.level.setText('<span style="color:red;"><b>%s</b></span>' % _('Advanced'))
self.ui.tipdia_spinner.valueChanged.connect(self.on_calculate_tooldia)
self.ui.tipangle_spinner.valueChanged.connect(self.on_calculate_tooldia)
self.ui.cutz_spinner.valueChanged.connect(self.on_calculate_tooldia)
if self.app.defaults["gerber_buffering"] == 'no': if self.app.defaults["gerber_buffering"] == 'no':
self.ui.create_buffer_button.show() self.ui.create_buffer_button.show()
@@ -296,58 +242,6 @@ class GerberObject(FlatCAMObj, Gerber):
self.build_ui() self.build_ui()
self.units_found = self.app.defaults['units'] self.units_found = self.app.defaults['units']
def on_calculate_tooldia(self):
try:
tdia = float(self.ui.tipdia_spinner.get_value())
except Exception:
return
try:
dang = float(self.ui.tipangle_spinner.get_value())
except Exception:
return
try:
cutz = float(self.ui.cutz_spinner.get_value())
except Exception:
return
cutz *= -1
if cutz < 0:
cutz *= -1
half_tip_angle = dang / 2
tool_diameter = tdia + (2 * cutz * math.tan(math.radians(half_tip_angle)))
self.ui.iso_tool_dia_entry.set_value(tool_diameter)
def on_type_obj_index_changed(self):
val = self.ui.type_obj_combo.get_value()
obj_type = {"Gerber": 0, "Geometry": 2}[val]
self.ui.obj_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
self.ui.obj_combo.setCurrentIndex(0)
self.ui.obj_combo.obj_type = {_("Gerber"): "Gerber", _("Geometry"): "Geometry"}[val]
def on_tool_type_change(self, state):
if state == 'circular':
self.ui.tipdialabel.hide()
self.ui.tipdia_spinner.hide()
self.ui.tipanglelabel.hide()
self.ui.tipangle_spinner.hide()
self.ui.cutzlabel.hide()
self.ui.cutz_spinner.hide()
self.ui.iso_tool_dia_entry.setDisabled(False)
# update the value in the self.iso_tool_dia_entry once this is selected
self.ui.iso_tool_dia_entry.set_value(self.options['isotooldia'])
else:
self.ui.tipdialabel.show()
self.ui.tipdia_spinner.show()
self.ui.tipanglelabel.show()
self.ui.tipangle_spinner.show()
self.ui.cutzlabel.show()
self.ui.cutz_spinner.show()
self.ui.iso_tool_dia_entry.setDisabled(True)
# update the value in the self.iso_tool_dia_entry once this is selected
self.on_calculate_tooldia()
def build_ui(self): def build_ui(self):
FlatCAMObj.build_ui(self) FlatCAMObj.build_ui(self)
@@ -530,7 +424,7 @@ class GerberObject(FlatCAMObj, Gerber):
return "fail" return "fail"
geo_obj.solid_geometry = non_copper geo_obj.solid_geometry = non_copper
self.app.new_object("geometry", name, geo_init) self.app.app_obj.new_object("geometry", name, geo_init)
def on_generatebb_button_click(self, *args): def on_generatebb_button_click(self, *args):
self.app.defaults.report_usage("gerber_on_generatebb_button") self.app.defaults.report_usage("gerber_on_generatebb_button")
@@ -556,244 +450,24 @@ class GerberObject(FlatCAMObj, Gerber):
return "fail" return "fail"
geo_obj.solid_geometry = bounding_box geo_obj.solid_geometry = bounding_box
self.app.new_object("geometry", name, geo_init) self.app.app_obj.new_object("geometry", name, geo_init)
def on_iso_button_click(self, *args):
obj = self.app.collection.get_active()
self.iso_type = 2
if self.ui.iso_type_radio.get_value() == 'ext':
self.iso_type = 0
if self.ui.iso_type_radio.get_value() == 'int':
self.iso_type = 1
def worker_task(iso_obj, app_obj):
with self.app.proc_container.new(_("Isolating...")):
if self.ui.follow_cb.get_value() is True:
iso_obj.follow_geo()
# in the end toggle the visibility of the origin object so we can see the generated Geometry
iso_obj.ui.plot_cb.toggle()
else:
app_obj.defaults.report_usage("gerber_on_iso_button")
self.read_form()
iso_scope = 'all' if self.ui.iso_scope_radio.get_value() == 'all' else 'single'
self.isolate_handler(iso_type=self.iso_type, iso_scope=iso_scope)
self.app.worker_task.emit({'fcn': worker_task, 'params': [obj, self.app]})
def follow_geo(self, outname=None):
"""
Creates a geometry object "following" the gerber paths.
:return: None
"""
# default_name = self.options["name"] + "_follow"
# follow_name = outname or default_name
if outname is None:
follow_name = self.options["name"] + "_follow"
else:
follow_name = outname
def follow_init(follow_obj, app):
# Propagate options
follow_obj.options["cnctooldia"] = str(self.options["isotooldia"])
follow_obj.solid_geometry = self.follow_geometry
# TODO: Do something if this is None. Offer changing name?
try:
self.app.new_object("geometry", follow_name, follow_init)
except Exception as e:
return "Operation failed: %s" % str(e)
def isolate_handler(self, iso_type, iso_scope):
if iso_scope == 'all':
self.isolate(iso_type=iso_type)
else:
# disengage the grid snapping since it may be hard to click on polygons with grid snapping on
if self.app.ui.grid_snap_btn.isChecked():
self.grid_status_memory = True
self.app.ui.grid_snap_btn.trigger()
else:
self.grid_status_memory = False
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_click_release)
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
else:
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click on a polygon to isolate it."))
def on_mouse_click_release(self, event):
if self.app.is_legacy is False:
event_pos = event.pos
right_button = 2
self.app.event_is_dragging = self.app.event_is_dragging
else:
event_pos = (event.xdata, event.ydata)
right_button = 3
self.app.event_is_dragging = self.app.ui.popMenu.mouse_is_panning
try:
x = float(event_pos[0])
y = float(event_pos[1])
except TypeError:
return
event_pos = (x, y)
curr_pos = self.app.plotcanvas.translate_coords(event_pos)
if self.app.grid_status():
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
else:
curr_pos = (curr_pos[0], curr_pos[1])
if event.button == 1:
clicked_poly = self.find_polygon(point=(curr_pos[0], curr_pos[1]))
if self.app.selection_type is not None:
self.selection_area_handler(self.app.pos, curr_pos, self.app.selection_type)
self.app.selection_type = None
elif clicked_poly:
if clicked_poly not in self.poly_dict.values():
shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0, shape=clicked_poly,
color=self.app.defaults['global_sel_draw_color'] + 'AF',
face_color=self.app.defaults['global_sel_draw_color'] + 'AF',
visible=True)
self.poly_dict[shape_id] = clicked_poly
self.app.inform.emit(
'%s: %d. %s' % (_("Added polygon"), int(len(self.poly_dict)),
_("Click to add next polygon or right click to start isolation."))
)
else:
try:
for k, v in list(self.poly_dict.items()):
if v == clicked_poly:
self.app.tool_shapes.remove(k)
self.poly_dict.pop(k)
break
except TypeError:
return
self.app.inform.emit(
'%s. %s' % (_("Removed polygon"),
_("Click to add/remove next polygon or right click to start isolation."))
)
self.app.tool_shapes.redraw()
else:
self.app.inform.emit(_("No polygon detected under click position."))
elif event.button == right_button and self.app.event_is_dragging is False:
# restore the Grid snapping if it was active before
if self.grid_status_memory is True:
self.app.ui.grid_snap_btn.trigger()
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release)
else:
self.app.plotcanvas.graph_event_disconnect(self.mr)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot)
self.app.tool_shapes.clear(update=True)
if self.poly_dict:
poly_list = deepcopy(list(self.poly_dict.values()))
self.isolate(iso_type=self.iso_type, geometry=poly_list)
self.poly_dict.clear()
else:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("List of single polygons is empty. Aborting."))
def selection_area_handler(self, start_pos, end_pos, sel_type):
"""
:param start_pos: mouse position when the selection LMB click was done
:param end_pos: mouse position when the left mouse button is released
:param sel_type: if True it's a left to right selection (enclosure), if False it's a 'touch' selection
:return:
"""
poly_selection = Polygon([start_pos, (end_pos[0], start_pos[1]), end_pos, (start_pos[0], end_pos[1])])
# delete previous selection shape
self.app.delete_selection_shape()
added_poly_count = 0
try:
for geo in self.solid_geometry:
if geo not in self.poly_dict.values():
if sel_type is True:
if geo.within(poly_selection):
shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0,
shape=geo,
color=self.app.defaults['global_sel_draw_color'] + 'AF',
face_color=self.app.defaults[
'global_sel_draw_color'] + 'AF',
visible=True)
self.poly_dict[shape_id] = geo
added_poly_count += 1
else:
if poly_selection.intersects(geo):
shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0,
shape=geo,
color=self.app.defaults['global_sel_draw_color'] + 'AF',
face_color=self.app.defaults[
'global_sel_draw_color'] + 'AF',
visible=True)
self.poly_dict[shape_id] = geo
added_poly_count += 1
except TypeError:
if self.solid_geometry not in self.poly_dict.values():
if sel_type is True:
if self.solid_geometry.within(poly_selection):
shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0,
shape=self.solid_geometry,
color=self.app.defaults['global_sel_draw_color'] + 'AF',
face_color=self.app.defaults[
'global_sel_draw_color'] + 'AF',
visible=True)
self.poly_dict[shape_id] = self.solid_geometry
added_poly_count += 1
else:
if poly_selection.intersects(self.solid_geometry):
shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0,
shape=self.solid_geometry,
color=self.app.defaults['global_sel_draw_color'] + 'AF',
face_color=self.app.defaults[
'global_sel_draw_color'] + 'AF',
visible=True)
self.poly_dict[shape_id] = self.solid_geometry
added_poly_count += 1
if added_poly_count > 0:
self.app.tool_shapes.redraw()
self.app.inform.emit(
'%s: %d. %s' % (_("Added polygon"),
int(added_poly_count),
_("Click to add next polygon or right click to start isolation."))
)
else:
self.app.inform.emit(_("No polygon in selection."))
def isolate(self, iso_type=None, geometry=None, dia=None, passes=None, overlap=None, outname=None, combine=None, def isolate(self, iso_type=None, geometry=None, dia=None, passes=None, overlap=None, outname=None, combine=None,
milling_type=None, follow=None, plot=True): milling_type=None, follow=None, plot=True):
""" """
Creates an isolation routing geometry object in the project. Creates an isolation routing geometry object in the project.
:param iso_type: type of isolation to be done: 0 = exteriors, 1 = interiors and 2 = both :param iso_type: type of isolation to be done: 0 = exteriors, 1 = interiors and 2 = both
:param geometry: specific geometry to isolate :param geometry: specific geometry to isolate
:param dia: Tool diameter :param dia: Tool diameter
:param passes: Number of tool widths to cut :param passes: Number of tool widths to cut
:param overlap: Overlap between passes in fraction of tool diameter :param overlap: Overlap between passes in fraction of tool diameter
:param outname: Base name of the output object :param outname: Base name of the output object
:param combine: Boolean: if to combine passes in one resulting object in case of multiple passes :param combine: Boolean: if to combine passes in one resulting object in case of multiple passes
:param milling_type: type of milling: conventional or climbing :param milling_type: type of milling: conventional or climbing
:param follow: Boolean: if to generate a 'follow' geometry :param follow: Boolean: if to generate a 'follow' geometry
:param plot: Boolean: if to plot the resulting geometry object :param plot: Boolean: if to plot the resulting geometry object
:return: None :return: None
""" """
if geometry is None: if geometry is None:
@@ -802,20 +476,20 @@ class GerberObject(FlatCAMObj, Gerber):
work_geo = geometry work_geo = geometry
if dia is None: if dia is None:
dia = float(self.options["isotooldia"]) dia = float(self.app.defaults["tools_iso_tooldia"])
if passes is None: if passes is None:
passes = int(self.options["isopasses"]) passes = int(self.app.defaults["tools_iso_passes"])
if overlap is None: if overlap is None:
overlap = float(self.options["isooverlap"]) overlap = float(self.app.defaults["tools_iso_overlap"])
overlap /= 100.0 overlap /= 100.0
combine = self.options["combine_passes"] if combine is None else bool(combine) combine = self.app.defaults["tools_iso_combine_passes"] if combine is None else bool(combine)
if milling_type is None: if milling_type is None:
milling_type = self.options["milling_type"] milling_type = self.app.defaults["tools_iso_milling_type"]
if iso_type is None: if iso_type is None:
iso_t = 2 iso_t = 2
@@ -837,16 +511,16 @@ class GerberObject(FlatCAMObj, Gerber):
def iso_init(geo_obj, app_obj): def iso_init(geo_obj, app_obj):
# Propagate options # Propagate options
geo_obj.options["cnctooldia"] = str(self.options["isotooldia"]) geo_obj.options["cnctooldia"] = str(dia)
geo_obj.tool_type = self.ui.tool_type_radio.get_value().upper() geo_obj.tool_type = self.app.defaults["tools_iso_tool_type"]
geo_obj.solid_geometry = [] geo_obj.solid_geometry = []
# transfer the Cut Z and Vtip and VAngle values in case that we use the V-Shape tool in Gerber UI # transfer the Cut Z and Vtip and VAngle values in case that we use the V-Shape tool in Gerber UI
if self.ui.tool_type_radio.get_value() == 'v': if geo_obj.tool_type.lower() == 'v':
new_cutz = self.ui.cutz_spinner.get_value() new_cutz = self.app.defaults["tools_iso_tool_cutz"]
new_vtipdia = self.ui.tipdia_spinner.get_value() new_vtipdia = self.app.defaults["tools_iso_tool_vtipdia"]
new_vtipangle = self.ui.tipangle_spinner.get_value() new_vtipangle = self.app.defaults["tools_iso_tool_vtipangle"]
tool_type = 'V' tool_type = 'V'
else: else:
new_cutz = self.app.defaults['geometry_cutz'] new_cutz = self.app.defaults['geometry_cutz']
@@ -885,7 +559,7 @@ class GerberObject(FlatCAMObj, Gerber):
geo_obj.tools['1'] = {} geo_obj.tools['1'] = {}
geo_obj.tools.update({ geo_obj.tools.update({
'1': { '1': {
'tooldia': float(self.options["isotooldia"]), 'tooldia': dia,
'offset': 'Path', 'offset': 'Path',
'offset_value': 0.0, 'offset_value': 0.0,
'type': _('Rough'), 'type': _('Rough'),
@@ -937,12 +611,11 @@ class GerberObject(FlatCAMObj, Gerber):
# ############################################################ # ############################################################
# ########## AREA SUBTRACTION ################################ # ########## AREA SUBTRACTION ################################
# ############################################################ # ############################################################
if self.ui.except_cb.get_value(): # if self.app.defaults["tools_iso_except"]:
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo")) # self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry) # geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
# TODO: Do something if this is None. Offer changing name? self.app.app_obj.new_object("geometry", iso_name, iso_init, plot=plot)
self.app.new_object("geometry", iso_name, iso_init, plot=plot)
else: else:
for i in range(passes): for i in range(passes):
@@ -970,17 +643,13 @@ class GerberObject(FlatCAMObj, Gerber):
def iso_init(geo_obj, app_obj): def iso_init(geo_obj, app_obj):
# Propagate options # Propagate options
geo_obj.options["cnctooldia"] = str(self.options["isotooldia"]) geo_obj.options["cnctooldia"] = str(dia)
if self.ui.tool_type_radio.get_value() == 'v': geo_obj.tool_type = self.app.defaults["tools_iso_tool_type"]
geo_obj.tool_type = 'V'
else:
geo_obj.tool_type = 'C1'
# if milling type is climb then the move is counter-clockwise around features # if milling type is climb then the move is counter-clockwise around features
mill_dir = 1 if milling_type == 'cl' else 0 mill_dir = 1 if milling_type == 'cl' else 0
geom = self.generate_envelope(offset, mill_dir, geometry=work_geo, env_iso_type=iso_t, geom = self.generate_envelope(offset, mill_dir, geometry=work_geo, env_iso_type=iso_t,
follow=follow, follow=follow, nr_passes=i)
nr_passes=i)
if geom == 'fail': if geom == 'fail':
app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated.")) app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
@@ -991,10 +660,10 @@ class GerberObject(FlatCAMObj, Gerber):
# transfer the Cut Z and Vtip and VAngle values in case that we use the V-Shape tool in Gerber UI # transfer the Cut Z and Vtip and VAngle values in case that we use the V-Shape tool in Gerber UI
# even if the resulting geometry is not multigeo we add the tools dict which will hold the data # even if the resulting geometry is not multigeo we add the tools dict which will hold the data
# required to be transfered to the Geometry object # required to be transfered to the Geometry object
if self.ui.tool_type_radio.get_value() == 'v': if self.app.defaults["tools_iso_tool_type"].lower() == 'v':
new_cutz = self.ui.cutz_spinner.get_value() new_cutz = self.app.defaults["tools_iso_tool_cutz"]
new_vtipdia = self.ui.tipdia_spinner.get_value() new_vtipdia = self.app.defaults["tools_iso_tool_vtipdia"]
new_vtipangle = self.ui.tipangle_spinner.get_value() new_vtipangle = self.app.defaults["tools_iso_tool_vtipangle"]
tool_type = 'V' tool_type = 'V'
else: else:
new_cutz = self.app.defaults['geometry_cutz'] new_cutz = self.app.defaults['geometry_cutz']
@@ -1033,7 +702,7 @@ class GerberObject(FlatCAMObj, Gerber):
geo_obj.tools['1'] = {} geo_obj.tools['1'] = {}
geo_obj.tools.update({ geo_obj.tools.update({
'1': { '1': {
'tooldia': float(self.options["isotooldia"]), 'tooldia': dia,
'offset': 'Path', 'offset': 'Path',
'offset_value': 0.0, 'offset_value': 0.0,
'type': _('Rough'), 'type': _('Rough'),
@@ -1067,12 +736,11 @@ class GerberObject(FlatCAMObj, Gerber):
# ############################################################ # ############################################################
# ########## AREA SUBTRACTION ################################ # ########## AREA SUBTRACTION ################################
# ############################################################ # ############################################################
if self.ui.except_cb.get_value(): # if self.app.defaults["tools_iso_except"]:
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo")) # self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry) # geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
# TODO: Do something if this is None. Offer changing name? self.app.app_obj.new_object("geometry", iso_name, iso_init, plot=plot)
self.app.new_object("geometry", iso_name, iso_init, plot=plot)
def generate_envelope(self, offset, invert, geometry=None, env_iso_type=2, follow=None, nr_passes=0): def generate_envelope(self, offset, invert, geometry=None, env_iso_type=2, follow=None, nr_passes=0):
# isolation_geometry produces an envelope that is going on the left of the geometry # isolation_geometry produces an envelope that is going on the left of the geometry
@@ -1114,64 +782,28 @@ class GerberObject(FlatCAMObj, Gerber):
return 'fail' return 'fail'
return geom return geom
def area_subtraction(self, geo, subtractor_geo=None): def follow_geo(self, outname=None):
""" """
Subtracts the subtractor_geo (if present else self.solid_geometry) from the geo Creates a geometry object "following" the gerber paths.
:param geo: target geometry from which to subtract :return: None
:param subtractor_geo: geometry that acts as subtractor
:return:
""" """
new_geometry = []
target_geo = geo
if subtractor_geo: if outname is None:
sub_union = cascaded_union(subtractor_geo) follow_name = self.options["name"] + "_follow"
else: else:
name = self.ui.obj_combo.currentText() follow_name = outname
subtractor_obj = self.app.collection.get_by_name(name)
sub_union = cascaded_union(subtractor_obj.solid_geometry)
def follow_init(follow_obj, app):
# Propagate options
follow_obj.options["cnctooldia"] = str(self.app.defaults["tools_iso_tooldia"])
follow_obj.solid_geometry = self.follow_geometry
# TODO: Do something if this is None. Offer changing name?
try: try:
for geo_elem in target_geo: self.app.app_obj.new_object("geometry", follow_name, follow_init)
if isinstance(geo_elem, Polygon): except Exception as e:
for ring in self.poly2rings(geo_elem): return "Operation failed: %s" % str(e)
new_geo = ring.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiPolygon):
for poly in geo_elem:
for ring in self.poly2rings(poly):
new_geo = ring.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, LineString):
new_geo = geo_elem.difference(sub_union)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiLineString):
for line_elem in geo_elem:
new_geo = line_elem.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
except TypeError:
if isinstance(target_geo, Polygon):
for ring in self.poly2rings(target_geo):
new_geo = ring.difference(sub_union)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(target_geo, LineString):
new_geo = target_geo.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(target_geo, MultiLineString):
for line_elem in target_geo:
new_geo = line_elem.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
return new_geometry
def on_plot_cb_click(self, *args): def on_plot_cb_click(self, *args):
if self.muted_ui: if self.muted_ui:

View File

@@ -12,15 +12,15 @@
import inspect # TODO: For debugging only. import inspect # TODO: For debugging only.
from flatcamGUI.ObjectUI import * from AppGUI.ObjectUI import *
from FlatCAMCommon import LoudDict from Common import LoudDict
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy
import sys import sys
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -43,7 +43,7 @@ class ValidationError(Exception):
class FlatCAMObj(QtCore.QObject): class FlatCAMObj(QtCore.QObject):
""" """
Base type of objects handled in FlatCAM. These become interactive Base type of objects handled in FlatCAM. These become interactive
in the GUI, can be plotted, and their options can be modified in the AppGUI, can be plotted, and their options can be modified
by the user in their respective forms. by the user in their respective forms.
""" """
@@ -139,7 +139,7 @@ class FlatCAMObj(QtCore.QObject):
except KeyError: except KeyError:
log.debug("FlatCAMObj.from_dict() --> KeyError: %s. " log.debug("FlatCAMObj.from_dict() --> KeyError: %s. "
"Means that we are loading an old project that don't" "Means that we are loading an old project that don't"
"have all attributes in the latest FlatCAM." % str(attr)) "have all attributes in the latest application version." % str(attr))
pass pass
def on_options_change(self, key): def on_options_change(self, key):
@@ -182,6 +182,11 @@ class FlatCAMObj(QtCore.QObject):
except (TypeError, AttributeError): except (TypeError, AttributeError):
pass pass
try:
self.ui.transformations_button.clicked.connect(self.app.transform_tool.run)
except (TypeError, AttributeError):
pass
# self.ui.skew_button.clicked.connect(self.on_skew_button_click) # self.ui.skew_button.clicked.connect(self.on_skew_button_click)
def build_ui(self): def build_ui(self):
@@ -245,14 +250,14 @@ class FlatCAMObj(QtCore.QObject):
self.app.proc_container.update_view_text('') self.app.proc_container.update_view_text('')
with self.app.proc_container.new('%s...' % _("Plotting")): with self.app.proc_container.new('%s...' % _("Plotting")):
self.plot() self.plot()
self.app.object_changed.emit(self) self.app.app_obj.object_changed.emit(self)
self.app.worker_task.emit({'fcn': worker_task, 'params': []}) self.app.worker_task.emit({'fcn': worker_task, 'params': []})
def on_scale_button_click(self): def on_scale_button_click(self):
self.read_form() self.read_form()
try: try:
factor = float(eval(self.ui.scale_entry.get_value())) factor = float(self.ui.scale_entry.get_value())
except Exception as e: except Exception as e:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Scaling could not be executed.")) self.app.inform.emit('[ERROR_NOTCL] %s' % _("Scaling could not be executed."))
log.debug("FlatCAMObj.on_scale_button_click() -- %s" % str(e)) log.debug("FlatCAMObj.on_scale_button_click() -- %s" % str(e))
@@ -276,7 +281,7 @@ class FlatCAMObj(QtCore.QObject):
self.app.proc_container.update_view_text('') self.app.proc_container.update_view_text('')
with self.app.proc_container.new('%s...' % _("Plotting")): with self.app.proc_container.new('%s...' % _("Plotting")):
self.plot() self.plot()
self.app.object_changed.emit(self) self.app.app_obj.object_changed.emit(self)
self.app.worker_task.emit({'fcn': worker_task, 'params': []}) self.app.worker_task.emit({'fcn': worker_task, 'params': []})
@@ -292,7 +297,7 @@ class FlatCAMObj(QtCore.QObject):
self.app.proc_container.update_view_text('') self.app.proc_container.update_view_text('')
with self.app.proc_container.new('%s...' % _("Plotting")): with self.app.proc_container.new('%s...' % _("Plotting")):
self.plot() self.plot()
self.app.object_changed.emit(self) self.app.app_obj.object_changed.emit(self)
self.app.worker_task.emit({'fcn': worker_task, 'params': []}) self.app.worker_task.emit({'fcn': worker_task, 'params': []})
@@ -372,7 +377,7 @@ class FlatCAMObj(QtCore.QObject):
def plot_task(): def plot_task():
with self.app.proc_container.new('%s...' % _("Plotting")): with self.app.proc_container.new('%s...' % _("Plotting")):
self.plot() self.plot()
self.app.object_changed.emit(self) self.app.app_obj.object_changed.emit(self)
self.app.worker_task.emit({'fcn': plot_task, 'params': []}) self.app.worker_task.emit({'fcn': plot_task, 'params': []})
@@ -459,8 +464,16 @@ class FlatCAMObj(QtCore.QObject):
def visible(self, value, threaded=True): def visible(self, value, threaded=True):
log.debug("FlatCAMObj.visible()") log.debug("FlatCAMObj.visible()")
def worker_task(app_obj): current_visibility = self.shapes.visible
self.shapes.visible = value # self.shapes.visible = value # maybe this is slower in VisPy? use enabled property?
def task(current_visibility):
if current_visibility is True:
if value is False:
self.shapes.visible = False
else:
if value is True:
self.shapes.visible = True
if self.app.is_legacy is False: if self.app.is_legacy is False:
# Not all object types has annotations # Not all object types has annotations
@@ -469,10 +482,10 @@ class FlatCAMObj(QtCore.QObject):
except Exception: except Exception:
pass pass
if threaded is False: if threaded:
worker_task(app_obj=self.app) self.app.worker_task.emit({'fcn': task, 'params': [current_visibility]})
else: else:
self.app.worker_task.emit({'fcn': worker_task, 'params': [self]}) task(current_visibility)
@property @property
def drawing_tolerance(self): def drawing_tolerance(self):

View File

@@ -10,16 +10,16 @@
# File modified by: Marius Stanciu # # File modified by: Marius Stanciu #
# ########################################################## # ##########################################################
from flatcamEditors.FlatCAMTextEditor import TextEditor from AppEditors.FlatCAMTextEditor import TextEditor
from flatcamObjects.FlatCAMObj import * from AppObjects.FlatCAMObj import *
from flatcamGUI.ObjectUI import * from AppGUI.ObjectUI import *
import tkinter as tk import tkinter as tk
import sys import sys
from copy import deepcopy from copy import deepcopy
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -183,7 +183,13 @@ class ScriptObject(FlatCAMObj):
if self.app.ui.shell_dock.isHidden(): if self.app.ui.shell_dock.isHidden():
self.app.ui.shell_dock.show() self.app.ui.shell_dock.show()
self.script_code = deepcopy(self.script_editor_tab.code_editor.toPlainText()) self.app.shell.open_processing() # Disables input box.
# make sure that the pixmaps are not updated when running this as they will crash
# TODO find why the pixmaps load crash when run from this object (perhaps another thread?)
self.app.ui.fcinfo.lock_pmaps = True
self.script_code = self.script_editor_tab.code_editor.toPlainText()
old_line = '' old_line = ''
for tcl_command_line in self.script_code.splitlines(): for tcl_command_line in self.script_code.splitlines():
@@ -202,8 +208,6 @@ class ScriptObject(FlatCAMObj):
# execute the actual Tcl command # execute the actual Tcl command
try: try:
self.app.shell.open_processing() # Disables input box.
result = self.app.shell.tcl.eval(str(new_command)) result = self.app.shell.tcl.eval(str(new_command))
if result != 'None': if result != 'None':
self.app.shell.append_output(result + '\n') self.app.shell.append_output(result + '\n')
@@ -220,6 +224,7 @@ class ScriptObject(FlatCAMObj):
log.error("Exec command Exception: %s\n" % result) log.error("Exec command Exception: %s\n" % result)
self.app.shell.append_error('ERROR: %s\n '% result) self.app.shell.append_error('ERROR: %s\n '% result)
self.app.ui.fcinfo.lock_pmaps = False
self.app.shell.close_processing() self.app.shell.close_processing()
def on_autocomplete_changed(self, state): def on_autocomplete_changed(self, state):
@@ -228,6 +233,27 @@ class ScriptObject(FlatCAMObj):
else: else:
self.script_editor_tab.code_editor.completer_enable = False self.script_editor_tab.code_editor.completer_enable = False
def mirror(self, axis, point):
pass
def offset(self, vect):
pass
def rotate(self, angle, point):
pass
def scale(self, xfactor, yfactor=None, point=None):
pass
def skew(self, angle_x, angle_y, point):
pass
def buffer(self, distance, join, factor=None):
pass
def bounds(self, flatten=False):
return None, None, None, None
def to_dict(self): def to_dict(self):
""" """
Returns a representation of the object as a dictionary. Returns a representation of the object as a dictionary.

View File

@@ -16,13 +16,13 @@ from PyQt5.QtCore import Qt, QSettings
from PyQt5.QtGui import QColor from PyQt5.QtGui import QColor
# from PyQt5.QtCore import QModelIndex # from PyQt5.QtCore import QModelIndex
from flatcamObjects.FlatCAMObj import FlatCAMObj from AppObjects.FlatCAMObj import FlatCAMObj
from flatcamObjects.FlatCAMCNCJob import CNCJobObject from AppObjects.FlatCAMCNCJob import CNCJobObject
from flatcamObjects.FlatCAMDocument import DocumentObject from AppObjects.FlatCAMDocument import DocumentObject
from flatcamObjects.FlatCAMExcellon import ExcellonObject from AppObjects.FlatCAMExcellon import ExcellonObject
from flatcamObjects.FlatCAMGeometry import GeometryObject from AppObjects.FlatCAMGeometry import GeometryObject
from flatcamObjects.FlatCAMGerber import GerberObject from AppObjects.FlatCAMGerber import GerberObject
from flatcamObjects.FlatCAMScript import ScriptObject from AppObjects.FlatCAMScript import ScriptObject
import inspect # TODO: Remove import inspect # TODO: Remove
@@ -32,7 +32,7 @@ from copy import deepcopy
from numpy import Inf from numpy import Inf
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')
@@ -50,12 +50,13 @@ class KeySensitiveListView(QtWidgets.QTreeView):
def __init__(self, app, parent=None): def __init__(self, app, parent=None):
super(KeySensitiveListView, self).__init__(parent) super(KeySensitiveListView, self).__init__(parent)
self.setHeaderHidden(True) self.setHeaderHidden(True)
self.setEditTriggers(QtWidgets.QTreeView.SelectedClicked) # self.setEditTriggers(QtWidgets.QTreeView.SelectedClicked) # allow Edit on Tree
self.setEditTriggers(QtWidgets.QTreeView.NoEditTriggers)
# self.setRootIsDecorated(False) # self.setRootIsDecorated(False)
# self.setExpandsOnDoubleClick(False) # self.setExpandsOnDoubleClick(False)
# Enable dragging and dropping onto the GUI # Enable dragging and dropping onto the AppGUI
self.setAcceptDrops(True) self.setAcceptDrops(True)
self.filename = "" self.filename = ""
self.app = app self.app = app
@@ -334,6 +335,8 @@ class ObjectCollection(QtCore.QAbstractItemModel):
self.click_modifier = None self.click_modifier = None
self.update_list_signal.connect(self.on_update_list_signal) self.update_list_signal.connect(self.on_update_list_signal)
self.view.activated.connect(self.on_row_activated)
self.item_selected.connect(self.on_row_selected)
def promise(self, obj_name): def promise(self, obj_name):
log.debug("Object %s has been promised." % obj_name) log.debug("Object %s has been promised." % obj_name)
@@ -382,8 +385,9 @@ class ObjectCollection(QtCore.QAbstractItemModel):
if type(obj) != GeometryObject: if type(obj) != GeometryObject:
self.app.ui.menuprojectgeneratecnc.setVisible(False) self.app.ui.menuprojectgeneratecnc.setVisible(False)
if type(obj) != GeometryObject and type(obj) != ExcellonObject and type(obj) != GerberObject: # if type(obj) != GeometryObject and type(obj) != ExcellonObject and type(obj) != GerberObject or \
self.app.ui.menuprojectedit.setVisible(False) # type(obj) != CNCJobObject:
# self.app.ui.menuprojectedit.setVisible(False)
if type(obj) != GerberObject and type(obj) != ExcellonObject and type(obj) != CNCJobObject: if type(obj) != GerberObject and type(obj) != ExcellonObject and type(obj) != CNCJobObject:
self.app.ui.menuprojectviewsource.setVisible(False) self.app.ui.menuprojectviewsource.setVisible(False)
if type(obj) != GerberObject and type(obj) != GeometryObject and type(obj) != ExcellonObject and \ if type(obj) != GerberObject and type(obj) != GeometryObject and type(obj) != ExcellonObject and \
@@ -550,7 +554,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
while name in self.get_names(): while name in self.get_names():
# ## Create a new name # ## Create a new name
# Ends with number? # Ends with number?
log.debug("new_object(): Object name (%s) exists, changing." % name) log.debug("app_obj.new_object(): Object name (%s) exists, changing." % name)
match = re.search(r'(.*[^\d])?(\d+)$', name) match = re.search(r'(.*[^\d])?(\d+)$', name)
if match: # Yes: Increment the number! if match: # Yes: Increment the number!
base = match.group(1) or '' base = match.group(1) or ''
@@ -596,8 +600,8 @@ class ObjectCollection(QtCore.QAbstractItemModel):
""" """
Gets a list of the names of all objects in the collection. Gets a list of the names of all objects in the collection.
:return: List of names. :return: List of names.
:rtype: list :rtype: list
""" """
# log.debug(str(inspect.stack()[1][3]) + " --> OC.get_names()") # log.debug(str(inspect.stack()[1][3]) + " --> OC.get_names()")
@@ -985,7 +989,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
def get_list(self): def get_list(self):
""" """
Will return a list of all objects currently opened. Will return a list of all objects currently opened. Except FlatCAMScript and FlatCAMDocuments
:return: :return:
""" """
@@ -998,3 +1002,199 @@ class ObjectCollection(QtCore.QAbstractItemModel):
def update_view(self): def update_view(self):
self.dataChanged.emit(QtCore.QModelIndex(), QtCore.QModelIndex()) self.dataChanged.emit(QtCore.QModelIndex(), QtCore.QModelIndex())
def on_row_activated(self, index):
if index.isValid():
if index.internalPointer().parent_item != self.root_item:
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
self.on_item_activated(index)
def on_row_selected(self, obj_name):
"""
This is a special string; when received it will make all Menu -> Objects entries unchecked
It mean we clicked outside of the items and deselected all
:param obj_name:
:return:
"""
if obj_name == 'none':
for act in self.app.ui.menuobjects.actions():
act.setChecked(False)
return
# get the name of the selected objects and add them to a list
name_list = []
for obj in self.get_selected():
name_list.append(obj.options['name'])
# set all actions as unchecked but the ones selected make them checked
for act in self.app.ui.menuobjects.actions():
act.setChecked(False)
if act.text() in name_list:
act.setChecked(True)
def on_collection_updated(self, obj, state, old_name):
"""
Create a menu from the object loaded in the collection.
:param obj: object that was changed (added, deleted, renamed)
:param state: what was done with the object. Can be: added, deleted, delete_all, renamed
:param old_name: the old name of the object before the action that triggered this slot happened
:return: None
"""
icon_files = {
"gerber": self.app.resource_location + "/flatcam_icon16.png",
"excellon": self.app.resource_location + "/drill16.png",
"cncjob": self.app.resource_location + "/cnc16.png",
"geometry": self.app.resource_location + "/geometry16.png",
"script": self.app.resource_location + "/script_new16.png",
"document": self.app.resource_location + "/notes16_1.png"
}
if state == 'append':
for act in self.app.ui.menuobjects.actions():
try:
act.triggered.disconnect()
except TypeError:
pass
self.app.ui.menuobjects.clear()
gerber_list = []
exc_list = []
cncjob_list = []
geo_list = []
script_list = []
doc_list = []
for name in self.get_names():
obj_named = self.get_by_name(name)
if obj_named.kind == 'gerber':
gerber_list.append(name)
elif obj_named.kind == 'excellon':
exc_list.append(name)
elif obj_named.kind == 'cncjob':
cncjob_list.append(name)
elif obj_named.kind == 'geometry':
geo_list.append(name)
elif obj_named.kind == 'script':
script_list.append(name)
elif obj_named.kind == 'document':
doc_list.append(name)
def add_act(o_name):
obj_for_icon = self.get_by_name(o_name)
add_action = QtWidgets.QAction(parent=self.app.ui.menuobjects)
add_action.setCheckable(True)
add_action.setText(o_name)
add_action.setIcon(QtGui.QIcon(icon_files[obj_for_icon.kind]))
add_action.triggered.connect(
lambda: self.set_active(o_name) if add_action.isChecked() is True else
self.set_inactive(o_name))
self.app.ui.menuobjects.addAction(add_action)
for name in gerber_list:
add_act(name)
self.app.ui.menuobjects.addSeparator()
for name in exc_list:
add_act(name)
self.app.ui.menuobjects.addSeparator()
for name in cncjob_list:
add_act(name)
self.app.ui.menuobjects.addSeparator()
for name in geo_list:
add_act(name)
self.app.ui.menuobjects.addSeparator()
for name in script_list:
add_act(name)
self.app.ui.menuobjects.addSeparator()
for name in doc_list:
add_act(name)
self.app.ui.menuobjects.addSeparator()
self.app.ui.menuobjects_selall = self.app.ui.menuobjects.addAction(
QtGui.QIcon(self.app.resource_location + '/select_all.png'),
_('Select All')
)
self.app.ui.menuobjects_unselall = self.app.ui.menuobjects.addAction(
QtGui.QIcon(self.app.resource_location + '/deselect_all32.png'),
_('Deselect All')
)
self.app.ui.menuobjects_selall.triggered.connect(lambda: self.on_objects_selection(True))
self.app.ui.menuobjects_unselall.triggered.connect(lambda: self.on_objects_selection(False))
elif state == 'delete':
for act in self.app.ui.menuobjects.actions():
if act.text() == obj.options['name']:
try:
act.triggered.disconnect()
except TypeError:
pass
self.app.ui.menuobjects.removeAction(act)
break
elif state == 'rename':
for act in self.app.ui.menuobjects.actions():
if act.text() == old_name:
add_action = QtWidgets.QAction(parent=self.app.ui.menuobjects)
add_action.setText(obj.options['name'])
add_action.setIcon(QtGui.QIcon(icon_files[obj.kind]))
add_action.triggered.connect(
lambda: self.set_active(obj.options['name']) if add_action.isChecked() is True else
self.set_inactive(obj.options['name']))
self.app.ui.menuobjects.insertAction(act, add_action)
try:
act.triggered.disconnect()
except TypeError:
pass
self.app.ui.menuobjects.removeAction(act)
break
elif state == 'delete_all':
for act in self.app.ui.menuobjects.actions():
try:
act.triggered.disconnect()
except TypeError:
pass
self.app.ui.menuobjects.clear()
self.app.ui.menuobjects.addSeparator()
self.app.ui.menuobjects_selall = self.app.ui.menuobjects.addAction(
QtGui.QIcon(self.app.resource_location + '/select_all.png'),
_('Select All')
)
self.app.ui.menuobjects_unselall = self.app.ui.menuobjects.addAction(
QtGui.QIcon(self.app.resource_location + '/deselect_all32.png'),
_('Deselect All')
)
self.app.ui.menuobjects_selall.triggered.connect(lambda: self.on_objects_selection(True))
self.app.ui.menuobjects_unselall.triggered.connect(lambda: self.on_objects_selection(False))
def on_objects_selection(self, on_off):
obj_list = self.get_names()
if on_off is True:
self.set_all_active()
for act in self.app.ui.menuobjects.actions():
try:
act.setChecked(True)
except Exception:
pass
if obj_list:
self.app.inform[str, bool].emit('[selected] %s' % _("All objects are selected."), False)
else:
self.set_all_inactive()
for act in self.app.ui.menuobjects.actions():
try:
act.setChecked(False)
except Exception:
pass
if obj_list:
self.app.inform[str, bool].emit('%s' % _("Objects selection is cleared."), False)
else:
self.app.inform[str, bool].emit('', False)

View File

@@ -12,8 +12,8 @@ import logging
log = logging.getLogger('base2') log = logging.getLogger('base2')
from flatcamParsers.ParseFont import * from AppParsers.ParseFont import *
from flatcamParsers.ParseDXF_Spline import * from AppParsers.ParseDXF_Spline import *
def distance(pt1, pt2): def distance(pt1, pt2):

View File

@@ -6,7 +6,7 @@
# MIT Licence # # MIT Licence #
# ########################################################## ## # ########################################################## ##
from camlib import Geometry from camlib import Geometry, grace
import shapely.affinity as affinity import shapely.affinity as affinity
from shapely.geometry import Point, LineString from shapely.geometry import Point, LineString
@@ -17,8 +17,7 @@ import logging
import traceback import traceback
from copy import deepcopy from copy import deepcopy
import FlatCAMTranslation as fcTranslate # import AppTranslation as fcTranslate
from FlatCAMCommon import GracefulException as grace
import gettext import gettext
import builtins import builtins
@@ -967,7 +966,7 @@ class Excellon(Geometry):
:return: None :return: None
""" """
log.debug("flatcamParsers.ParseExcellon.Excellon.create_geometry()") log.debug("AppParsers.ParseExcellon.Excellon.create_geometry()")
self.solid_geometry = [] self.solid_geometry = []
try: try:
# clear the solid_geometry in self.tools # clear the solid_geometry in self.tools
@@ -982,7 +981,7 @@ class Excellon(Geometry):
_("Excellon.create_geometry() -> a drill location was skipped " _("Excellon.create_geometry() -> a drill location was skipped "
"due of not having a tool associated.\n" "due of not having a tool associated.\n"
"Check the resulting GCode.")) "Check the resulting GCode."))
log.debug("flatcamParsers.ParseExcellon.Excellon.create_geometry() -> a drill location was skipped " log.debug("AppParsers.ParseExcellon.Excellon.create_geometry() -> a drill location was skipped "
"due of not having a tool associated") "due of not having a tool associated")
continue continue
tooldia = self.tools[drill['tool']]['C'] tooldia = self.tools[drill['tool']]['C']
@@ -1006,7 +1005,7 @@ class Excellon(Geometry):
self.tools[tool_in_slots]['solid_geometry'].append(poly) self.tools[tool_in_slots]['solid_geometry'].append(poly)
self.tools[tool_in_slots]['data'] = deepcopy(self.default_data) self.tools[tool_in_slots]['data'] = deepcopy(self.default_data)
except Exception as e: except Exception as e:
log.debug("flatcamParsers.ParseExcellon.Excellon.create_geometry() -> " log.debug("AppParsers.ParseExcellon.Excellon.create_geometry() -> "
"Excellon geometry creation failed due of ERROR: %s" % str(e)) "Excellon geometry creation failed due of ERROR: %s" % str(e))
return "fail" return "fail"
@@ -1018,10 +1017,10 @@ class Excellon(Geometry):
:param flatten: No used :param flatten: No used
""" """
log.debug("flatcamParsers.ParseExcellon.Excellon.bounds()") log.debug("AppParsers.ParseExcellon.Excellon.bounds()")
if self.solid_geometry is None or not self.tools: if self.solid_geometry is None or not self.tools:
log.debug("flatcamParsers.ParseExcellon.Excellon -> solid_geometry is None") log.debug("AppParsers.ParseExcellon.Excellon -> solid_geometry is None")
return 0, 0, 0, 0 return 0, 0, 0, 0
def bounds_rec(obj): def bounds_rec(obj):
@@ -1069,7 +1068,7 @@ class Excellon(Geometry):
This function first convert to the the units found in the Excellon file but it converts tools that This function first convert to the the units found in the Excellon file but it converts tools that
are not there yet so it has no effect other than it signal that the units are the ones in the file. are not there yet so it has no effect other than it signal that the units are the ones in the file.
On object creation, in new_object(), true conversion is done because this is done at the end of the On object creation, in app_obj.new_object(), true conversion is done because this is done at the end of the
Excellon file parsing, the tools are inside and self.tools is really converted from the units found Excellon file parsing, the tools are inside and self.tools is really converted from the units found
inside the file to the FlatCAM units. inside the file to the FlatCAM units.
@@ -1092,7 +1091,7 @@ class Excellon(Geometry):
else: else:
log.error("Unsupported units: %s" % str(obj_units)) log.error("Unsupported units: %s" % str(obj_units))
factor = 1.0 factor = 1.0
log.debug("flatcamParsers.ParseExcellon.Excellon.convert_units() --> Factor: %s" % str(factor)) log.debug("AppParsers.ParseExcellon.Excellon.convert_units() --> Factor: %s" % str(factor))
self.units = obj_units self.units = obj_units
self.scale(factor, factor) self.scale(factor, factor)
@@ -1118,7 +1117,7 @@ class Excellon(Geometry):
:return: None :return: None
:rtype: None :rtype: None
""" """
log.debug("flatcamParsers.ParseExcellon.Excellon.scale()") log.debug("AppParsers.ParseExcellon.Excellon.scale()")
if yfactor is None: if yfactor is None:
yfactor = xfactor yfactor = xfactor
@@ -1183,7 +1182,7 @@ class Excellon(Geometry):
:type vect: tuple :type vect: tuple
:return: None :return: None
""" """
log.debug("flatcamParsers.ParseExcellon.Excellon.offset()") log.debug("AppParsers.ParseExcellon.Excellon.offset()")
dx, dy = vect dx, dy = vect
@@ -1243,7 +1242,7 @@ class Excellon(Geometry):
:type point: list :type point: list
:return: None :return: None
""" """
log.debug("flatcamParsers.ParseExcellon.Excellon.mirror()") log.debug("AppParsers.ParseExcellon.Excellon.mirror()")
px, py = point px, py = point
xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis] xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis]
@@ -1309,7 +1308,7 @@ class Excellon(Geometry):
See shapely manual for more information: See shapely manual for more information:
http://toblerity.org/shapely/manual.html#affine-transformations http://toblerity.org/shapely/manual.html#affine-transformations
""" """
log.debug("flatcamParsers.ParseExcellon.Excellon.skew()") log.debug("AppParsers.ParseExcellon.Excellon.skew()")
if angle_x is None: if angle_x is None:
angle_x = 0.0 angle_x = 0.0
@@ -1396,7 +1395,7 @@ class Excellon(Geometry):
:param point: tuple of coordinates (x, y) :param point: tuple of coordinates (x, y)
:return: None :return: None
""" """
log.debug("flatcamParsers.ParseExcellon.Excellon.rotate()") log.debug("AppParsers.ParseExcellon.Excellon.rotate()")
if angle == 0: if angle == 0:
return return
@@ -1479,7 +1478,7 @@ class Excellon(Geometry):
:param join: The type of line joint used by the shapely buffer method: round, square, bevel :param join: The type of line joint used by the shapely buffer method: round, square, bevel
:return: None :return: None
""" """
log.debug("flatcamParsers.ParseExcellon.Excellon.buffer()") log.debug("AppParsers.ParseExcellon.Excellon.buffer()")
if distance == 0: if distance == 0:
return return

View File

@@ -22,7 +22,7 @@ from fontTools import ttLib
import logging import logging
import gettext import gettext
import FlatCAMTranslation as fcTranslate import AppTranslation as fcTranslate
import builtins import builtins
fcTranslate.apply_language('strings') fcTranslate.apply_language('strings')

Some files were not shown because too many files have changed in this diff Show More