- maintenance_2
This commit is contained in:
parent
38fa25ed3d
commit
f5c84fdc49
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
from camlib import to_dict
|
||||
|
||||
|
@ -8,8 +8,10 @@ import json
|
|||
|
||||
from copy import deepcopy
|
||||
from datetime import datetime
|
||||
import math
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -117,7 +119,7 @@ class ToolsDB(QtWidgets.QWidget):
|
|||
)
|
||||
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(
|
||||
_("Add a new tool in the Tools Table of the\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."))
|
||||
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()
|
||||
|
||||
|
@ -655,7 +657,7 @@ class ToolsDB(QtWidgets.QWidget):
|
|||
l_save=str(self.app.get_last_save_folder()),
|
||||
n=_("Tools_Database"),
|
||||
date=date),
|
||||
filter=filter__)
|
||||
ext_filter=filter__)
|
||||
|
||||
filename = str(filename)
|
||||
|
||||
|
@ -724,7 +726,7 @@ class ToolsDB(QtWidgets.QWidget):
|
|||
self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
|
||||
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.callback_on_edited()
|
||||
|
||||
|
@ -1030,6 +1032,7 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
self.advanced_box.setTitle(_("Advanced Geo Parameters"))
|
||||
self.advanced_box.setFixedWidth(250)
|
||||
|
||||
# NCC TOOL BOX
|
||||
self.ncc_box = QtWidgets.QGroupBox()
|
||||
self.ncc_box.setStyleSheet("""
|
||||
QGroupBox
|
||||
|
@ -1042,6 +1045,7 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
self.ncc_box.setTitle(_("NCC Parameters"))
|
||||
self.ncc_box.setFixedWidth(250)
|
||||
|
||||
# PAINT TOOL BOX
|
||||
self.paint_box = QtWidgets.QGroupBox()
|
||||
self.paint_box.setStyleSheet("""
|
||||
QGroupBox
|
||||
|
@ -1054,10 +1058,24 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
self.paint_box.setTitle(_("Paint Parameters"))
|
||||
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.advanced_box.setLayout(self.advanced_vlay)
|
||||
self.ncc_box.setLayout(self.ncc_vlay)
|
||||
self.paint_box.setLayout(self.paint_vlay)
|
||||
self.iso_box.setLayout(self.iso_vlay)
|
||||
|
||||
geo_vlay = QtWidgets.QVBoxLayout()
|
||||
geo_vlay.addWidget(self.basic_box)
|
||||
|
@ -1067,6 +1085,7 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
tools_vlay = QtWidgets.QVBoxLayout()
|
||||
tools_vlay.addWidget(self.ncc_box)
|
||||
tools_vlay.addWidget(self.paint_box)
|
||||
tools_vlay.addWidget(self.iso_box)
|
||||
tools_vlay.addStretch()
|
||||
|
||||
param_hlay.addLayout(geo_vlay)
|
||||
|
@ -1478,7 +1497,7 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
|
||||
self.ncc_method_combo = FCComboBox()
|
||||
self.ncc_method_combo.addItems(
|
||||
[_("Standard"), _("Seed"), _("Lines")]
|
||||
[_("Standard"), _("Seed"), _("Lines"), _("Combo")]
|
||||
)
|
||||
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.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
|
||||
|
@ -1678,12 +1792,19 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
)
|
||||
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(
|
||||
_("Add a new tool in the Tools Table of the\n"
|
||||
"active Geometry object after selecting a tool\n"
|
||||
_("Insert a new tool in the Tools Table of the\n"
|
||||
"object/application tool after selecting a tool\n"
|
||||
"in the Tools Database.")
|
||||
)
|
||||
self.add_tool_from_db.setStyleSheet("""
|
||||
QPushButton
|
||||
{
|
||||
font-weight: bold;
|
||||
color: green;
|
||||
}
|
||||
""")
|
||||
self.add_tool_from_db.hide()
|
||||
|
||||
self.cancel_tool_from_db = FCButton(_("Cancel"))
|
||||
|
@ -1693,7 +1814,7 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
tree_layout.addLayout(hlay)
|
||||
hlay.addWidget(self.add_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_pathconnect": self.pathconnect_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 = {
|
||||
|
@ -1787,6 +1915,13 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
'gdb_p_method': "tools_paintmethod",
|
||||
'gdb_p_connect': "tools_pathconnect",
|
||||
'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
|
||||
|
@ -1887,7 +2022,7 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
self.blockSignals(False)
|
||||
|
||||
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
|
||||
try:
|
||||
|
@ -1906,7 +2041,7 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
|
||||
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()
|
||||
|
||||
|
@ -1939,21 +2074,23 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
if self.db_tool_dict:
|
||||
self.storage_to_form(self.db_tool_dict['1'])
|
||||
|
||||
# Enable GUI
|
||||
# Enable AppGUI
|
||||
self.basic_box.setEnabled(True)
|
||||
self.advanced_box.setEnabled(True)
|
||||
self.ncc_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.setFocus()
|
||||
|
||||
else:
|
||||
# Disable GUI
|
||||
# Disable AppGUI
|
||||
self.basic_box.setEnabled(False)
|
||||
self.advanced_box.setEnabled(False)
|
||||
self.ncc_box.setEnabled(False)
|
||||
self.paint_box.setEnabled(False)
|
||||
self.iso_box.setEnabled(False)
|
||||
else:
|
||||
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_pathconnect": self.app.defaults["tools_pathconnect"],
|
||||
"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['name'] = 'new_tool'
|
||||
dict_elem['name'] = new_name
|
||||
if type(self.app.defaults["geometry_cnctooldia"]) == float:
|
||||
dict_elem['tooldia'] = self.app.defaults["geometry_cnctooldia"]
|
||||
else:
|
||||
|
@ -2117,7 +2271,7 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
l_save=str(self.app.get_last_save_folder()),
|
||||
n=_("Tools_Database"),
|
||||
date=date),
|
||||
filter=filter__)
|
||||
ext_filter=filter__)
|
||||
|
||||
filename = str(filename)
|
||||
|
||||
|
@ -2186,7 +2340,7 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
|
||||
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.update_storage()
|
||||
|
||||
|
@ -2218,6 +2372,18 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
self.app.tools_db_changed_flag = False
|
||||
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):
|
||||
# make sure that we don't make multiple connections to the widgets
|
||||
self.ui_disconnect()
|
||||
|
@ -2247,12 +2413,40 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
if isinstance(wdg, FCSpinner) or isinstance(wdg, FCDoubleSpinner):
|
||||
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):
|
||||
try:
|
||||
self.name_entry.editingFinished.disconnect(self.update_tree_name)
|
||||
except (TypeError, AttributeError):
|
||||
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:
|
||||
wdg = self.form_fields[key]
|
||||
|
||||
|
@ -2398,6 +2592,18 @@ class ToolsDB2(QtWidgets.QWidget):
|
|||
elif wdg_name == "gdb_p_contour":
|
||||
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()
|
||||
|
||||
def on_tool_requested_from_app(self):
|
|
@ -9,9 +9,9 @@ from PyQt5 import QtGui, QtCore, QtWidgets
|
|||
from PyQt5.QtCore import Qt, QSettings
|
||||
|
||||
from camlib import distance, arc, FlatCAMRTreeStorage
|
||||
from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, RadioSet, FCSpinner
|
||||
from flatcamEditors.FlatCAMGeoEditor import FCShapeTool, DrawTool, DrawToolShape, DrawToolUtilityShape, FlatCAMGeoEditor
|
||||
from flatcamParsers.ParseExcellon import Excellon
|
||||
from AppGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, RadioSet, FCSpinner
|
||||
from AppEditors.FlatCAMGeoEditor import FCShapeTool, DrawTool, DrawToolShape, DrawToolUtilityShape, FlatCAMGeoEditor
|
||||
from AppParsers.ParseExcellon import Excellon
|
||||
|
||||
from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon, Point
|
||||
import shapely.affinity as affinity
|
||||
|
@ -26,7 +26,7 @@ import logging
|
|||
from copy import deepcopy
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -2123,7 +2123,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
else:
|
||||
self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1)
|
||||
else:
|
||||
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||
from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_exc_editor')
|
||||
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_exc_editor')
|
||||
|
||||
|
@ -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
|
||||
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):
|
||||
self.shapes.pool = pool
|
||||
|
@ -2312,7 +2312,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
tool_dia = float('%.*f' % (self.decimals, v['C']))
|
||||
self.tool2tooldia[int(k)] = tool_dia
|
||||
|
||||
# Init GUI
|
||||
# Init AppGUI
|
||||
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_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.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.snap_magnet.setVisible(True)
|
||||
|
||||
self.app.ui.exc_editor_menu.setDisabled(False)
|
||||
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.setVisible(True)
|
||||
# self.app.ui.snap_toolbar.setDisabled(False)
|
||||
# self.app.ui.status_toolbar.setDisabled(False)
|
||||
|
||||
# start with GRID toolbar activated
|
||||
if self.app.ui.grid_snap_btn.isChecked() is False:
|
||||
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.cmenu_newmenu.menuAction().setVisible(False)
|
||||
|
@ -2869,30 +2866,8 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
self.clear()
|
||||
self.app.ui.exc_edit_toolbar.setDisabled(True)
|
||||
|
||||
settings = QSettings("Open Source", "FlatCAM")
|
||||
if settings.contains("layout"):
|
||||
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)
|
||||
self.app.ui.corner_snap_btn.setVisible(False)
|
||||
self.app.ui.snap_magnet.setVisible(False)
|
||||
|
||||
# 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 \
|
||||
|
@ -3068,7 +3043,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
|
||||
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)
|
||||
|
||||
# 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.")):
|
||||
|
||||
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'],
|
||||
local_use=edited_obj,
|
||||
filename=None,
|
||||
use_thread=False)
|
||||
except Exception as e:
|
||||
self.deactivate()
|
||||
log.error("Error on Edited object creation: %s" % str(e))
|
||||
return
|
||||
|
||||
self.deactivate()
|
||||
self.app.inform.emit('[success] %s' % _("Excellon editing finished."))
|
||||
|
||||
def on_tool_select(self, tool):
|
||||
|
@ -3463,8 +3440,8 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
self.pos = (self.pos[0], self.pos[1])
|
||||
|
||||
if event.button == 1:
|
||||
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||
"%.4f " % (0, 0))
|
||||
# self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||
# "%.4f " % (0, 0))
|
||||
|
||||
# Selection with left mouse button
|
||||
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_y = y
|
||||
|
||||
# update the position label in the infobar since the APP mouse event handlers are disconnected
|
||||
self.app.ui.position_label.setText(" <b>X</b>: %.4f "
|
||||
"<b>Y</b>: %.4f" % (x, y))
|
||||
|
||||
if self.pos is None:
|
||||
self.pos = (0, 0)
|
||||
self.app.dx = x - self.pos[0]
|
||||
self.app.dy = y - self.pos[1]
|
||||
|
||||
# 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 <b>Dy</b>: "
|
||||
"%.4f " % (self.app.dx, self.app.dy))
|
||||
# # update the position label in the infobar since the APP mouse event handlers are disconnected
|
||||
self.app.ui.position_label.setText(" <b>X</b>: %.4f "
|
||||
"<b>Y</b>: %.4f " % (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 <b>Dy</b>: "
|
||||
# "%.4f " % (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)
|
||||
self.update_utility_geometry(data=(x, y))
|
||||
|
@ -4045,7 +4026,7 @@ class FlatCAMExcEditor(QtCore.QObject):
|
|||
|
||||
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.
|
||||
:return: None
|
|
@ -15,11 +15,10 @@ from PyQt5 import QtGui, QtCore, QtWidgets
|
|||
from PyQt5.QtCore import Qt, QSettings
|
||||
|
||||
from camlib import distance, arc, three_point_circle, Geometry, FlatCAMRTreeStorage
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
from flatcamGUI.ObjectUI import RadioSet
|
||||
from flatcamGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \
|
||||
FCTable, FCDoubleSpinner, FCButton, EvalEntry2, FCInputDialog, FCTree
|
||||
from flatcamParsers.ParseFont import *
|
||||
from AppTool import AppTool
|
||||
from AppGUI.GUIElements import OptionalInputSection, FCCheckBox, FCEntry, FCComboBox, FCTextAreaRich, \
|
||||
FCDoubleSpinner, FCButton, FCInputDialog, FCTree
|
||||
from AppParsers.ParseFont import *
|
||||
|
||||
from shapely.geometry import LineString, LinearRing, MultiLineString, Polygon, MultiPolygon
|
||||
from shapely.ops import cascaded_union, unary_union, linemerge
|
||||
|
@ -34,7 +33,7 @@ from rtree import index as rtindex
|
|||
from copy import deepcopy
|
||||
# from vispy.io import read_png
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -42,7 +41,7 @@ if '_' not in builtins.__dict__:
|
|||
_ = gettext.gettext
|
||||
|
||||
|
||||
class BufferSelectionTool(FlatCAMTool):
|
||||
class BufferSelectionTool(AppTool):
|
||||
"""
|
||||
Simple input for buffer distance.
|
||||
"""
|
||||
|
@ -50,7 +49,7 @@ class BufferSelectionTool(FlatCAMTool):
|
|||
toolName = "Buffer Selection"
|
||||
|
||||
def __init__(self, app, draw_app):
|
||||
FlatCAMTool.__init__(self, app)
|
||||
AppTool.__init__(self, app)
|
||||
|
||||
self.draw_app = draw_app
|
||||
self.decimals = app.decimals
|
||||
|
@ -118,12 +117,12 @@ class BufferSelectionTool(FlatCAMTool):
|
|||
self.buffer_int_button.clicked.connect(self.on_buffer_int)
|
||||
self.buffer_ext_button.clicked.connect(self.on_buffer_ext)
|
||||
|
||||
# Init GUI
|
||||
# Init AppGUI
|
||||
self.buffer_distance_entry.set_value(0.01)
|
||||
|
||||
def run(self):
|
||||
self.app.defaults.report_usage("Geo Editor ToolBuffer()")
|
||||
FlatCAMTool.run(self)
|
||||
AppTool.run(self)
|
||||
|
||||
# if the splitter us hidden, display it
|
||||
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)
|
||||
|
||||
|
||||
class TextInputTool(FlatCAMTool):
|
||||
class TextInputTool(AppTool):
|
||||
"""
|
||||
Simple input for buffer distance.
|
||||
"""
|
||||
|
@ -195,7 +194,7 @@ class TextInputTool(FlatCAMTool):
|
|||
toolName = "Text Input Tool"
|
||||
|
||||
def __init__(self, app):
|
||||
FlatCAMTool.__init__(self, app)
|
||||
AppTool.__init__(self, app)
|
||||
|
||||
self.app = app
|
||||
self.text_path = []
|
||||
|
@ -340,7 +339,7 @@ class TextInputTool(FlatCAMTool):
|
|||
|
||||
def run(self):
|
||||
self.app.defaults.report_usage("Geo Editor TextInputTool()")
|
||||
FlatCAMTool.run(self)
|
||||
AppTool.run(self)
|
||||
|
||||
# if the splitter us hidden, display it
|
||||
if self.app.ui.splitter.sizes()[0] == 0:
|
||||
|
@ -405,7 +404,7 @@ class TextInputTool(FlatCAMTool):
|
|||
self.app.ui.notebook.setTabText(2, _("Tool"))
|
||||
|
||||
|
||||
class PaintOptionsTool(FlatCAMTool):
|
||||
class PaintOptionsTool(AppTool):
|
||||
"""
|
||||
Inputs to specify how to paint the selected polygons.
|
||||
"""
|
||||
|
@ -413,7 +412,7 @@ class PaintOptionsTool(FlatCAMTool):
|
|||
toolName = "Paint Tool"
|
||||
|
||||
def __init__(self, app, fcdraw):
|
||||
FlatCAMTool.__init__(self, app)
|
||||
AppTool.__init__(self, app)
|
||||
|
||||
self.app = app
|
||||
self.fcdraw = fcdraw
|
||||
|
@ -538,7 +537,7 @@ class PaintOptionsTool(FlatCAMTool):
|
|||
|
||||
def run(self):
|
||||
self.app.defaults.report_usage("Geo Editor ToolPaint()")
|
||||
FlatCAMTool.run(self)
|
||||
AppTool.run(self)
|
||||
|
||||
# if the splitter us hidden, display it
|
||||
if self.app.ui.splitter.sizes()[0] == 0:
|
||||
|
@ -547,7 +546,7 @@ class PaintOptionsTool(FlatCAMTool):
|
|||
self.app.ui.notebook.setTabText(2, _("Paint Tool"))
|
||||
|
||||
def set_tool_ui(self):
|
||||
# Init GUI
|
||||
# Init AppGUI
|
||||
if self.app.defaults["tools_painttooldia"]:
|
||||
self.painttooldia_entry.set_value(self.app.defaults["tools_painttooldia"])
|
||||
else:
|
||||
|
@ -599,7 +598,7 @@ class PaintOptionsTool(FlatCAMTool):
|
|||
self.app.ui.splitter.setSizes([0, 1])
|
||||
|
||||
|
||||
class TransformEditorTool(FlatCAMTool):
|
||||
class TransformEditorTool(AppTool):
|
||||
"""
|
||||
Inputs to specify how to paint the selected polygons.
|
||||
"""
|
||||
|
@ -612,7 +611,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
offsetName = _("Offset")
|
||||
|
||||
def __init__(self, app, draw_app):
|
||||
FlatCAMTool.__init__(self, app)
|
||||
AppTool.__init__(self, app)
|
||||
|
||||
self.app = app
|
||||
self.draw_app = draw_app
|
||||
|
@ -981,7 +980,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
|
||||
def run(self):
|
||||
self.app.defaults.report_usage("Geo Editor Transform Tool()")
|
||||
FlatCAMTool.run(self)
|
||||
AppTool.run(self)
|
||||
self.set_tool_ui()
|
||||
|
||||
# if the splitter us hidden, display it
|
||||
|
@ -991,7 +990,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
self.app.ui.notebook.setTabText(2, _("Transform Tool"))
|
||||
|
||||
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):
|
||||
# Initialize form
|
||||
|
@ -3383,7 +3382,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
self.shapes = self.app.plotcanvas.new_shape_collection(layers=1)
|
||||
self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1)
|
||||
else:
|
||||
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||
from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_geo_editor')
|
||||
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_geo_editor')
|
||||
|
||||
|
@ -3467,22 +3466,32 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
:return:
|
||||
"""
|
||||
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:
|
||||
entry.set_value(self.app.defaults[opt])
|
||||
log.debug("FlatCAMGeoEditor.__init__().entry2option() --> %s" % str(e))
|
||||
return
|
||||
|
||||
def gridx_changed(goption, gentry):
|
||||
def grid_changed(goption, gentry):
|
||||
"""
|
||||
|
||||
:param goption: String. Can be either 'global_gridx' or 'global_gridy'
|
||||
:param gentry: A GUI element which text value is read and used
|
||||
:param goption: String. Can be either 'global_gridx' or 'global_gridy'
|
||||
:param gentry: A GUI element which text value is read and used
|
||||
:return:
|
||||
"""
|
||||
if goption not in ['global_gridx', 'global_gridy']:
|
||||
return
|
||||
|
||||
entry2option(opt=goption, entry=gentry)
|
||||
# if the grid link is checked copy the value in the GridX field to GridY
|
||||
try:
|
||||
val = float(gentry.get_value())
|
||||
text_value = gentry.text()
|
||||
if ',' in text_value:
|
||||
text_value = text_value.replace(',', '.')
|
||||
val = float(text_value)
|
||||
except ValueError:
|
||||
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.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.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
|
||||
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):
|
||||
self.shapes.pool = pool
|
||||
|
@ -3559,14 +3568,14 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
|
||||
# Remove anything else in the GUI Selected Tab
|
||||
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)
|
||||
# Switch notebook to Selected page
|
||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
||||
|
||||
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:
|
||||
"""
|
||||
|
@ -3644,10 +3653,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
self.tool_shape.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.snap_magnet.setVisible(True)
|
||||
|
||||
self.app.ui.geo_editor_menu.setDisabled(False)
|
||||
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.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.cmenu_newmenu.menuAction().setVisible(False)
|
||||
|
@ -3675,7 +3682,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
|
||||
self.item_selected.connect(self.on_geo_elem_selected)
|
||||
|
||||
# ## GUI Events
|
||||
# ## AppGUI Events
|
||||
self.tw.itemSelectionChanged.connect(self.on_tree_selection_change)
|
||||
# self.tw.keyPressed.connect(self.app.ui.keyPressEvent)
|
||||
# self.tw.customContextMenuRequested.connect(self.on_menu_request)
|
||||
|
@ -3703,27 +3710,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
self.app.ui.geo_edit_toolbar.setDisabled(True)
|
||||
|
||||
settings = QSettings("Open Source", "FlatCAM")
|
||||
if settings.contains("layout"):
|
||||
layout = settings.value('layout', type=str)
|
||||
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)
|
||||
self.app.ui.corner_snap_btn.setVisible(False)
|
||||
self.app.ui.snap_magnet.setVisible(False)
|
||||
|
||||
# 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 \
|
||||
|
@ -3757,7 +3745,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
pass
|
||||
|
||||
try:
|
||||
# ## GUI Events
|
||||
# ## AppGUI Events
|
||||
self.tw.itemSelectionChanged.disconnect(self.on_tree_selection_change)
|
||||
# self.tw.keyPressed.connect(self.app.ui.keyPressEvent)
|
||||
# self.tw.customContextMenuRequested.connect(self.on_menu_request)
|
||||
|
@ -4100,7 +4088,6 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
# start with GRID toolbar activated
|
||||
if self.app.ui.grid_snap_btn.isChecked() is False:
|
||||
self.app.ui.grid_snap_btn.trigger()
|
||||
self.app.ui.on_grid_snap_triggered(state=True)
|
||||
|
||||
def on_buffer_tool(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
|
||||
if self.options['grid_snap'] is True:
|
||||
self.app.inform[str, bool].emit(_("Grid Snap enabled."), False)
|
||||
self.app.app_cursor.enabled = True
|
||||
else:
|
||||
self.app.app_cursor.enabled = False
|
||||
self.app.inform[str, bool].emit(_("Grid Snap disabled."), False)
|
||||
|
||||
def on_canvas_click(self, event):
|
||||
"""
|
||||
|
@ -4173,8 +4162,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
self.pos = (self.pos[0], self.pos[1])
|
||||
|
||||
if event.button == 1:
|
||||
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||
"%.4f " % (0, 0))
|
||||
# self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||
# "%.4f " % (0, 0))
|
||||
|
||||
modifiers = QtWidgets.QApplication.keyboardModifiers()
|
||||
# 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.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(" <b>X</b>: %.4f "
|
||||
"<b>Y</b>: %.4f" % (x, y))
|
||||
|
||||
if self.pos is None:
|
||||
self.pos = (0, 0)
|
||||
self.app.dx = x - self.pos[0]
|
||||
self.app.dy = y - self.pos[1]
|
||||
|
||||
# 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 <b>Dy</b>: "
|
||||
"%.4f " % (self.app.dx, self.app.dy))
|
||||
# # update the position label in the infobar since the APP mouse event handlers are disconnected
|
||||
self.app.ui.position_label.setText(" <b>X</b>: %.4f "
|
||||
"<b>Y</b>: %.4f " % (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 <b>Dy</b>: "
|
||||
# "%.4f " % (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):
|
||||
pass
|
||||
|
@ -4665,7 +4659,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
|
||||
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.
|
||||
:return: None
|
||||
|
@ -4750,8 +4744,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
Transfers the geometry tool shape buffer to the selected geometry
|
||||
object. The geometry already in the object are removed.
|
||||
|
||||
:param fcgeometry: GeometryObject
|
||||
:return: None
|
||||
:param fcgeometry: GeometryObject
|
||||
:return: None
|
||||
"""
|
||||
if self.multigeo_tool:
|
||||
fcgeometry.tools[self.multigeo_tool]['solid_geometry'] = []
|
||||
|
@ -4776,6 +4770,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||
new_geo = linemerge(new_geo)
|
||||
fcgeometry.solid_geometry.append(new_geo)
|
||||
|
||||
self.deactivate()
|
||||
|
||||
def update_options(self, obj):
|
||||
if self.paint_tooldia:
|
||||
obj.options['cnctooldia'] = deepcopy(str(self.paint_tooldia))
|
|
@ -14,15 +14,13 @@ import shapely.affinity as affinity
|
|||
|
||||
from vispy.geometry import Rect
|
||||
|
||||
import threading
|
||||
import time
|
||||
from copy import copy, deepcopy
|
||||
import logging
|
||||
|
||||
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
|
||||
from FlatCAMTool import FlatCAMTool
|
||||
from AppTool import AppTool
|
||||
|
||||
import numpy as np
|
||||
from numpy.linalg import norm as numpy_norm
|
||||
|
@ -32,7 +30,7 @@ import math
|
|||
# import pngcanvas
|
||||
import traceback
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -1086,15 +1084,6 @@ class FCRegion(FCShapeTool):
|
|||
|
||||
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):
|
||||
# Jump to coords
|
||||
if key == QtCore.Qt.Key_J or key == 'J':
|
||||
|
@ -1160,16 +1149,36 @@ class FCRegion(FCShapeTool):
|
|||
|
||||
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
|
||||
"""
|
||||
def __init__(self, draw_app):
|
||||
FCRegion.__init__(self, draw_app)
|
||||
DrawTool.__init__(self, draw_app)
|
||||
self.name = 'track'
|
||||
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:
|
||||
QtGui.QGuiApplication.restoreOverrideCursor()
|
||||
except Exception as e:
|
||||
|
@ -1183,52 +1192,23 @@ class FCTrack(FCRegion):
|
|||
|
||||
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):
|
||||
self.draw_app.in_action = True
|
||||
try:
|
||||
if point != self.points[-1]:
|
||||
self.points.append(point)
|
||||
except IndexError:
|
||||
|
||||
if not self.points:
|
||||
self.points.append(point)
|
||||
elif point != self.points[-1]:
|
||||
self.points.append(point)
|
||||
else:
|
||||
return
|
||||
|
||||
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['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,
|
||||
resolution=int(self.steps_per_circle / 4))
|
||||
new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle))
|
||||
new_geo_el['follow'] = LineString(self.temp_points)
|
||||
|
||||
self.draw_app.add_gerber_shape(DrawToolShape(new_geo_el),
|
||||
|
@ -1241,23 +1221,25 @@ class FCTrack(FCRegion):
|
|||
|
||||
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):
|
||||
self.update_grid_info()
|
||||
new_geo_el = {}
|
||||
|
||||
if len(self.points) == 0:
|
||||
new_geo_el['solid'] = Point(data).buffer(self.buf_val,
|
||||
resolution=int(self.steps_per_circle / 4))
|
||||
|
||||
if not self.points:
|
||||
new_geo_el['solid'] = Point(data).buffer(self.buf_val, int(self.steps_per_circle))
|
||||
return DrawToolUtilityShape(new_geo_el)
|
||||
elif len(self.points) > 0:
|
||||
|
||||
self.temp_points = [self.points[-1]]
|
||||
else:
|
||||
old_x = self.points[-1][0]
|
||||
old_y = self.points[-1][1]
|
||||
x = data[0]
|
||||
y = data[1]
|
||||
|
||||
self.temp_points = [self.points[-1]]
|
||||
|
||||
mx = abs(round((x - old_x) / self.gridx_size))
|
||||
my = abs(round((y - old_y) / self.gridy_size))
|
||||
|
||||
|
@ -1305,14 +1287,30 @@ class FCTrack(FCRegion):
|
|||
|
||||
self.temp_points.append(data)
|
||||
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['solid'] = Point(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle))
|
||||
return DrawToolUtilityShape(new_geo_el)
|
||||
|
||||
new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val,
|
||||
resolution=int(self.steps_per_circle / 4))
|
||||
new_geo_el['solid'] = LineString(self.temp_points).buffer(self.buf_val, int(self.steps_per_circle))
|
||||
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):
|
||||
if key == 'Backspace' or key == QtCore.Qt.Key_Backspace:
|
||||
if len(self.points) > 0:
|
||||
|
@ -1405,6 +1403,15 @@ class FCTrack(FCRegion):
|
|||
|
||||
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):
|
||||
"""
|
||||
|
@ -2955,7 +2962,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
# this var will store the state of the toolbar before starting the editor
|
||||
self.toolbar_old_state = False
|
||||
|
||||
# Init GUI
|
||||
# Init AppGUI
|
||||
self.apdim_lbl.hide()
|
||||
self.apdim_entry.hide()
|
||||
self.gerber_obj = None
|
||||
|
@ -2967,7 +2974,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.tool_shape = self.canvas.new_shape_collection(layers=1)
|
||||
self.ma_annotation = self.canvas.new_text_group()
|
||||
else:
|
||||
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||
from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_grb_editor')
|
||||
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_grb_editor')
|
||||
self.ma_annotation = ShapeCollectionLegacy(
|
||||
|
@ -3110,7 +3117,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.complete = True
|
||||
|
||||
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):
|
||||
self.shapes.pool = pool
|
||||
|
@ -3139,7 +3146,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
tt_aperture = self.sorted_apcode[i]
|
||||
self.tid2apcode[i + 1] = tt_aperture
|
||||
|
||||
# Init GUI
|
||||
# Init AppGUI
|
||||
|
||||
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"])
|
||||
|
@ -3428,7 +3435,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
else:
|
||||
# deleted_tool_dia = float(self.apertures_table.item(self.apertures_table.currentRow(), 1).text())
|
||||
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
|
||||
|
||||
deleted_apcode_list = []
|
||||
|
@ -3685,10 +3692,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.shapes.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.snap_magnet.setVisible(True)
|
||||
|
||||
self.app.ui.grb_editor_menu.setDisabled(False)
|
||||
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.setVisible(True)
|
||||
# self.app.ui.snap_toolbar.setDisabled(False)
|
||||
# self.app.ui.status_toolbar.setDisabled(False)
|
||||
|
||||
# start with GRID toolbar activated
|
||||
if self.app.ui.grid_snap_btn.isChecked() is False:
|
||||
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
|
||||
self.app.ui.popmenu_edit.setVisible(False)
|
||||
|
@ -3736,29 +3740,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.app.ui.grb_edit_toolbar.setDisabled(True)
|
||||
|
||||
settings = QSettings("Open Source", "FlatCAM")
|
||||
if settings.contains("layout"):
|
||||
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)
|
||||
self.app.ui.corner_snap_btn.setVisible(False)
|
||||
self.app.ui.snap_magnet.setVisible(False)
|
||||
|
||||
# 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 \
|
||||
|
@ -4210,7 +4193,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
|
||||
def on_multiprocessing_finished(self):
|
||||
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.build_ui(first_run=True)
|
||||
self.plot_all()
|
||||
|
@ -4245,6 +4228,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
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.new_edited_gerber(new_grb_name, self.storage_dict)
|
||||
|
||||
@staticmethod
|
||||
def update_options(obj):
|
||||
|
@ -4266,9 +4250,10 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
"""
|
||||
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.
|
||||
:type outname: str
|
||||
:param aperture_storage: a dictionary that holds all the objects geometry
|
||||
:param outname: Name of the resulting object. None causes the name to be that of the file.
|
||||
:type outname: str
|
||||
:param aperture_storage: a dictionary that holds all the objects geometry
|
||||
:type aperture_storage: dict
|
||||
:return: None
|
||||
"""
|
||||
|
||||
|
@ -4360,26 +4345,27 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_("There are no Aperture definitions in the file. Aborting Gerber creation."))
|
||||
except Exception:
|
||||
msg = '[ERROR] %s' % \
|
||||
_("An internal error has occurred. See shell.\n")
|
||||
msg = '[ERROR] %s' % _("An internal error has occurred. See shell.\n")
|
||||
msg += traceback.format_exc()
|
||||
app_obj.inform.emit(msg)
|
||||
raise
|
||||
|
||||
grb_obj.source_file = self.app.export_gerber(obj_name=out_name, filename=None,
|
||||
local_use=grb_obj, use_thread=False)
|
||||
|
||||
with self.app.proc_container.new(_("Creating Gerber.")):
|
||||
try:
|
||||
self.app.new_object("gerber", outname, obj_init)
|
||||
self.app.app_obj.new_object("gerber", outname, obj_init)
|
||||
except Exception as e:
|
||||
log.error("Error on Edited object creation: %s" % str(e))
|
||||
# make sure to clean the previous results
|
||||
self.results = []
|
||||
return
|
||||
|
||||
self.app.inform.emit('[success] %s' % _("Done. Gerber editing finished."))
|
||||
# make sure to clean the previous results
|
||||
self.results = []
|
||||
self.deactivate_grb_editor()
|
||||
self.app.inform.emit('[success] %s' % _("Done. Gerber editing finished."))
|
||||
|
||||
def on_tool_select(self, tool):
|
||||
"""
|
||||
|
@ -4537,8 +4523,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.pos = (self.pos[0], self.pos[1])
|
||||
|
||||
if event.button == 1:
|
||||
self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||
"%.4f " % (0, 0))
|
||||
# self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
||||
# "%.4f " % (0, 0))
|
||||
|
||||
# Selection with left mouse button
|
||||
if self.active_tool is not None:
|
||||
|
@ -4550,8 +4536,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
self.app.defaults["global_point_clipboard_format"] %
|
||||
(self.decimals, self.pos[0], self.decimals, self.pos[1])
|
||||
)
|
||||
self.app.inform.emit('[success] %s' %
|
||||
_("Coordinates copied to clipboard."))
|
||||
self.app.inform.emit('[success] %s' % _("Coordinates copied to clipboard."))
|
||||
return
|
||||
|
||||
# Dispatch event to active_tool
|
||||
|
@ -4562,6 +4547,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
if self.current_storage is not None:
|
||||
self.on_grb_shape_complete(self.current_storage)
|
||||
self.build_ui()
|
||||
|
||||
# MS: always return to the Select Tool if modifier key is not pressed
|
||||
# else return to the current tool
|
||||
key_modifier = QtWidgets.QApplication.keyboardModifiers()
|
||||
|
@ -4569,6 +4555,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
modifier_to_use = Qt.ControlModifier
|
||||
else:
|
||||
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
|
||||
# in the selected list, we removed it. Therefore first click selects, second deselects.
|
||||
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)
|
||||
# right mouse click will finish the action
|
||||
if isinstance(self.active_tool, FCShapeTool):
|
||||
self.active_tool.click(self.app.geo_editor.snap(self.x, self.y))
|
||||
self.active_tool.make()
|
||||
if isinstance(self.active_tool, FCTrack):
|
||||
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:
|
||||
self.on_grb_shape_complete()
|
||||
self.app.inform.emit('[success] %s' %
|
||||
_("Done."))
|
||||
self.app.inform.emit('[success] %s' % _("Done."))
|
||||
|
||||
# MS: always return to the Select Tool if modifier key is not pressed
|
||||
# else return to the current tool but not for FCTrack
|
||||
|
@ -4774,18 +4763,23 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
|
||||
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(" <b>X</b>: %.4f "
|
||||
"<b>Y</b>: %.4f" % (x, y))
|
||||
|
||||
if self.pos is None:
|
||||
self.pos = (0, 0)
|
||||
self.app.dx = x - self.pos[0]
|
||||
self.app.dy = y - self.pos[1]
|
||||
|
||||
# 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 <b>Dy</b>: "
|
||||
"%.4f " % (self.app.dx, self.app.dy))
|
||||
# # update the position label in the infobar since the APP mouse event handlers are disconnected
|
||||
self.app.ui.position_label.setText(" <b>X</b>: %.4f "
|
||||
"<b>Y</b>: %.4f " % (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 <b>Dy</b>: "
|
||||
# "%.4f " % (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))
|
||||
|
||||
|
@ -5032,7 +5026,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
|
||||
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.
|
||||
:return: None
|
||||
|
@ -5298,7 +5292,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
|
|||
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.
|
||||
"""
|
||||
|
@ -5311,7 +5305,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||
offsetName = _("Offset")
|
||||
|
||||
def __init__(self, app, draw_app):
|
||||
FlatCAMTool.__init__(self, app)
|
||||
AppTool.__init__(self, app)
|
||||
|
||||
self.app = app
|
||||
self.draw_app = draw_app
|
||||
|
@ -5697,13 +5691,13 @@ class TransformEditorTool(FlatCAMTool):
|
|||
except AttributeError:
|
||||
pass
|
||||
|
||||
FlatCAMTool.run(self)
|
||||
AppTool.run(self)
|
||||
self.set_tool_ui()
|
||||
|
||||
self.app.ui.notebook.setTabText(2, _("Transform Tool"))
|
||||
|
||||
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):
|
||||
# Initialize form
|
|
@ -5,7 +5,7 @@
|
|||
# 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 reportlab.platypus import SimpleDocTemplate, Paragraph
|
||||
|
@ -15,7 +15,7 @@ from reportlab.lib.units import inch, mm
|
|||
# from io import StringIO
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -214,10 +214,10 @@ class TextEditor(QtWidgets.QWidget):
|
|||
filename = str(FCFileSaveDialog.get_saved_filename(
|
||||
caption=_("Export Code ..."),
|
||||
directory=self.app.defaults["global_last_folder"] + '/' + str(obj_name),
|
||||
filter=_filter_
|
||||
ext_filter=_filter_
|
||||
)[0])
|
||||
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 == "":
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
|
|
@ -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)
|
|
@ -23,7 +23,7 @@ import html
|
|||
import sys
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
log = logging.getLogger('base')
|
||||
|
@ -570,9 +570,13 @@ class FCEntry3(FCEntry):
|
|||
|
||||
|
||||
class EvalEntry(QtWidgets.QLineEdit):
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, border_color=None, parent=None):
|
||||
super(EvalEntry, self).__init__(parent)
|
||||
self.readyToEdit = True
|
||||
|
||||
if border_color:
|
||||
self.setStyleSheet("QLineEdit {border: 1px solid %s;}" % border_color)
|
||||
|
||||
self.editingFinished.connect(self.on_edit_finished)
|
||||
|
||||
def on_edit_finished(self):
|
||||
|
@ -599,7 +603,6 @@ class EvalEntry(QtWidgets.QLineEdit):
|
|||
|
||||
def get_value(self):
|
||||
raw = str(self.text()).strip(' ')
|
||||
evaled = 0.0
|
||||
try:
|
||||
evaled = eval(raw)
|
||||
except Exception as e:
|
||||
|
@ -639,7 +642,7 @@ class EvalEntry2(QtWidgets.QLineEdit):
|
|||
|
||||
def get_value(self):
|
||||
raw = str(self.text()).strip(' ')
|
||||
evaled = 0.0
|
||||
|
||||
try:
|
||||
evaled = eval(raw)
|
||||
except Exception as e:
|
||||
|
@ -656,6 +659,132 @@ class EvalEntry2(QtWidgets.QLineEdit):
|
|||
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):
|
||||
|
||||
returnPressed = QtCore.pyqtSignal()
|
||||
|
@ -684,6 +813,8 @@ class FCSpinner(QtWidgets.QSpinBox):
|
|||
self.setAlignment(align_val)
|
||||
|
||||
self.prev_readyToEdit = True
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Preferred)
|
||||
self.setSizePolicy(sizePolicy)
|
||||
|
||||
def eventFilter(self, object, event):
|
||||
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.prev_readyToEdit = True
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Preferred)
|
||||
self.setSizePolicy(sizePolicy)
|
||||
|
||||
def on_edit_finished(self):
|
||||
self.clearFocus()
|
||||
|
@ -2098,6 +2231,24 @@ class FCDetachableTab2(FCDetachableTab):
|
|||
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)
|
||||
|
||||
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):
|
||||
"""
|
||||
Slot connected to the tabCloseRequested signal
|
||||
|
@ -2196,11 +2347,14 @@ class OptionalHideInputSection:
|
|||
"""
|
||||
Associates the a checkbox with a set of inputs.
|
||||
|
||||
:param cb: Checkbox that enables the optional inputs.
|
||||
:param optinputs: List of widgets that are optional.
|
||||
: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
|
||||
:param cb: Checkbox that enables the optional inputs.
|
||||
:type cb: QtWidgets.QCheckBox
|
||||
:param optinputs: List of widgets that are optional.
|
||||
:type optinputs: list
|
||||
: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:
|
||||
"""
|
||||
assert isinstance(cb, FCCheckBox), \
|
||||
|
@ -2471,7 +2625,8 @@ class SpinBoxDelegate(QtWidgets.QItemDelegate):
|
|||
def updateEditorGeometry(self, editor, option, index):
|
||||
editor.setGeometry(option.rect)
|
||||
|
||||
def setDecimals(self, spinbox, digits):
|
||||
@staticmethod
|
||||
def setDecimals(spinbox, digits):
|
||||
spinbox.setDecimals(digits)
|
||||
|
||||
|
||||
|
@ -2519,7 +2674,7 @@ class DialogBoxRadio(QtWidgets.QDialog):
|
|||
:param title: string with the window title
|
||||
: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:
|
||||
self.location = str((0, 0))
|
||||
else:
|
||||
|
@ -2762,9 +2917,12 @@ class MyCompleter(QCompleter):
|
|||
insertText = QtCore.pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QCompleter.__init__(self)
|
||||
QCompleter.__init__(self, parent=parent)
|
||||
self.setCompletionMode(QCompleter.PopupCompletion)
|
||||
self.highlighted.connect(self.setHighlighted)
|
||||
|
||||
self.lastSelected = ''
|
||||
|
||||
# self.popup().installEventFilter(self)
|
||||
|
||||
# def eventFilter(self, obj, event):
|
||||
|
@ -2920,9 +3078,9 @@ class FCFileSaveDialog(QtWidgets.QFileDialog):
|
|||
super(FCFileSaveDialog, self).__init__(*args)
|
||||
|
||||
@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,
|
||||
directory=directory, filter=filter,
|
||||
directory=directory, filter=ext_filter,
|
||||
initialFilter=initialFilter)
|
||||
|
||||
filename = str(filename)
|
||||
|
@ -2938,6 +3096,225 @@ class FCFileSaveDialog(QtWidgets.QFileDialog):
|
|||
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):
|
||||
"""
|
||||
Credits go here:
|
File diff suppressed because it is too large
Load Diff
|
@ -11,11 +11,11 @@
|
|||
# Date: 3/10/2019 #
|
||||
# ##########################################################
|
||||
|
||||
from flatcamGUI.GUIElements import *
|
||||
from AppGUI.GUIElements import *
|
||||
import sys
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -35,7 +35,7 @@ class ObjectUI(QtWidgets.QWidget):
|
|||
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):
|
||||
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)
|
||||
|
||||
# ### Scale ####
|
||||
self.scale_entry = FCEntry()
|
||||
self.scale_entry = NumericalEvalEntry(border_color='#0069A9')
|
||||
self.scale_entry.set_value(1.0)
|
||||
self.scale_entry.setToolTip(
|
||||
_("Factor by which to multiply\n"
|
||||
|
@ -132,7 +132,7 @@ class ObjectUI(QtWidgets.QWidget):
|
|||
self.common_grid.addWidget(self.scale_button, 3, 1)
|
||||
|
||||
# ### Offset ####
|
||||
self.offsetvector_entry = EvalEntry2()
|
||||
self.offsetvector_entry = NumericalEvalTupleEntry(border_color='#0069A9')
|
||||
self.offsetvector_entry.setText("(0.0, 0.0)")
|
||||
self.offsetvector_entry.setToolTip(
|
||||
_("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.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()
|
||||
|
||||
def confirmation_message(self, accepted, minval, maxval):
|
||||
if accepted is False:
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s: [%.*f, %.*f]' %
|
||||
(_("Edited value is out of range"), self.decimals, minval, self.decimals, maxval))
|
||||
self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%.*f, %.*f]' % (_("Edited value is out of range"),
|
||||
self.decimals,
|
||||
minval,
|
||||
self.decimals,
|
||||
maxval), False)
|
||||
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):
|
||||
if accepted is False:
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s: [%d, %d]' %
|
||||
(_("Edited value is out of range"), minval, maxval))
|
||||
self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%d, %d]' %
|
||||
(_("Edited value is out of range"), minval, maxval), False)
|
||||
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):
|
||||
|
@ -205,27 +214,37 @@ class GerberObjectUI(ObjectUI):
|
|||
self.multicolored_cb.setMinimumWidth(55)
|
||||
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
|
||||
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"))
|
||||
self.name_entry = FCEntry()
|
||||
self.name_entry.setFocusPolicy(QtCore.Qt.StrongFocus)
|
||||
self.name_hlay.addWidget(name_label)
|
||||
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()
|
||||
self.custom_box.addLayout(hlay_plot)
|
||||
|
||||
# ### 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(
|
||||
_("Apertures Table for the Gerber Object.")
|
||||
)
|
||||
|
@ -282,254 +301,7 @@ class GerberObjectUI(ObjectUI):
|
|||
# start with apertures table hidden
|
||||
self.apertures_table.setVisible(False)
|
||||
|
||||
separator_line = QtWidgets.QFrame()
|
||||
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)
|
||||
|
||||
# Buffer Geometry
|
||||
self.create_buffer_button = QtWidgets.QPushButton(_('Buffer Solid Geometry'))
|
||||
self.create_buffer_button.setToolTip(
|
||||
_("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"
|
||||
"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(
|
||||
self.except_cb,
|
||||
[self.type_obj_combo, self.type_obj_combo_label, self.obj_combo, self.obj_label],
|
||||
logic=True
|
||||
)
|
||||
|
||||
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)
|
||||
separator_line = QtWidgets.QFrame()
|
||||
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
self.custom_box.addWidget(separator_line)
|
||||
|
||||
# ###########################################
|
||||
# ########## NEW GRID #######################
|
||||
|
@ -563,14 +328,21 @@ class GerberObjectUI(ObjectUI):
|
|||
self.tool_lbl = QtWidgets.QLabel('<b>%s</b>' % _("TOOLS"))
|
||||
grid2.addWidget(self.tool_lbl, 0, 0, 1, 2)
|
||||
|
||||
# ## Clear non-copper regions
|
||||
self.clearcopper_label = QtWidgets.QLabel("%s" % _("Clear N-copper"))
|
||||
self.clearcopper_label.setToolTip(
|
||||
# Isolation Tool - will create isolation paths around the copper features
|
||||
self.iso_button = QtWidgets.QPushButton(_('Isolation Routing'))
|
||||
self.iso_button.setToolTip(
|
||||
_("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.setToolTip(
|
||||
_("Create the Geometry Object\n"
|
||||
|
@ -582,17 +354,9 @@ class GerberObjectUI(ObjectUI):
|
|||
font-weight: bold;
|
||||
}
|
||||
""")
|
||||
grid2.addWidget(self.clearcopper_label, 1, 0)
|
||||
grid2.addWidget(self.generate_ncc_button, 1, 1)
|
||||
grid2.addWidget(self.generate_ncc_button, 2, 0, 1, 2)
|
||||
|
||||
# ## 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.setToolTip(
|
||||
_("Generate the geometry for\n"
|
||||
|
@ -604,13 +368,12 @@ class GerberObjectUI(ObjectUI):
|
|||
font-weight: bold;
|
||||
}
|
||||
""")
|
||||
grid2.addWidget(self.board_cutout_label, 2, 0)
|
||||
grid2.addWidget(self.generate_cutout_button, 2, 1)
|
||||
grid2.addWidget(self.generate_cutout_button, 3, 0, 1, 2)
|
||||
|
||||
separator_line = QtWidgets.QFrame()
|
||||
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
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
|
||||
self.noncopper_label = QtWidgets.QLabel("<b>%s</b>" % _("Non-copper regions"))
|
||||
|
@ -622,7 +385,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"copper from a specified region.")
|
||||
)
|
||||
|
||||
grid2.addWidget(self.noncopper_label, 4, 0, 1, 2)
|
||||
grid2.addWidget(self.noncopper_label, 5, 0, 1, 2)
|
||||
|
||||
# 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.setSingleStep(0.1)
|
||||
|
||||
grid2.addWidget(bmlabel, 5, 0)
|
||||
grid2.addWidget(self.noncopper_margin_entry, 5, 1)
|
||||
grid2.addWidget(bmlabel, 6, 0)
|
||||
grid2.addWidget(self.noncopper_margin_entry, 6, 1)
|
||||
|
||||
# Rounded corners
|
||||
self.noncopper_rounded_cb = FCCheckBox(label=_("Rounded Geo"))
|
||||
|
@ -649,13 +412,13 @@ class GerberObjectUI(ObjectUI):
|
|||
self.noncopper_rounded_cb.setMinimumWidth(90)
|
||||
|
||||
self.generate_noncopper_button = QtWidgets.QPushButton(_('Generate Geo'))
|
||||
grid2.addWidget(self.noncopper_rounded_cb, 6, 0)
|
||||
grid2.addWidget(self.generate_noncopper_button, 6, 1)
|
||||
grid2.addWidget(self.noncopper_rounded_cb, 7, 0)
|
||||
grid2.addWidget(self.generate_noncopper_button, 7, 1)
|
||||
|
||||
separator_line1 = QtWidgets.QFrame()
|
||||
separator_line1.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
separator_line1.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
grid2.addWidget(separator_line1, 7, 0, 1, 2)
|
||||
grid2.addWidget(separator_line1, 8, 0, 1, 2)
|
||||
|
||||
# ## Bounding box
|
||||
self.boundingbox_label = QtWidgets.QLabel('<b>%s</b>' % _('Bounding Box'))
|
||||
|
@ -664,7 +427,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"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.setToolTip(
|
||||
|
@ -677,8 +440,8 @@ class GerberObjectUI(ObjectUI):
|
|||
self.bbmargin_entry.set_precision(self.decimals)
|
||||
self.bbmargin_entry.setSingleStep(0.1)
|
||||
|
||||
grid2.addWidget(bbmargin, 9, 0)
|
||||
grid2.addWidget(self.bbmargin_entry, 9, 1)
|
||||
grid2.addWidget(bbmargin, 10, 0)
|
||||
grid2.addWidget(self.bbmargin_entry, 10, 1)
|
||||
|
||||
self.bbrounded_cb = FCCheckBox(label=_("Rounded Geo"))
|
||||
self.bbrounded_cb.setToolTip(
|
||||
|
@ -693,8 +456,8 @@ class GerberObjectUI(ObjectUI):
|
|||
self.generate_bb_button.setToolTip(
|
||||
_("Generate the Geometry object.")
|
||||
)
|
||||
grid2.addWidget(self.bbrounded_cb, 10, 0)
|
||||
grid2.addWidget(self.generate_bb_button, 10, 1)
|
||||
grid2.addWidget(self.bbrounded_cb, 11, 0)
|
||||
grid2.addWidget(self.generate_bb_button, 11, 1)
|
||||
|
||||
|
||||
class ExcellonObjectUI(ObjectUI):
|
||||
|
@ -723,22 +486,38 @@ class ExcellonObjectUI(ObjectUI):
|
|||
parent=parent,
|
||||
app=self.app)
|
||||
|
||||
# ### Plot options ####
|
||||
hlay_plot = QtWidgets.QHBoxLayout()
|
||||
self.custom_box.addLayout(hlay_plot)
|
||||
# Plot options
|
||||
grid_h = QtWidgets.QGridLayout()
|
||||
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.setMinimumWidth(90)
|
||||
|
||||
grid_h.addWidget(self.plot_options_label, 0, 0)
|
||||
|
||||
# Solid CB
|
||||
self.solid_cb = FCCheckBox(label=_('Solid'))
|
||||
self.solid_cb.setToolTip(
|
||||
_("Solid circles.")
|
||||
)
|
||||
hlay_plot.addWidget(self.plot_options_label)
|
||||
hlay_plot.addStretch()
|
||||
hlay_plot.addWidget(self.solid_cb)
|
||||
self.solid_cb.setMinimumWidth(50)
|
||||
grid_h.addWidget(self.solid_cb, 0, 1)
|
||||
|
||||
# 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
|
||||
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"))
|
||||
self.name_entry = FCEntry()
|
||||
self.name_entry.setFocusPolicy(QtCore.Qt.StrongFocus)
|
||||
|
@ -1525,12 +1304,28 @@ class GeometryObjectUI(ObjectUI):
|
|||
)
|
||||
|
||||
# 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.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
|
||||
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"))
|
||||
self.name_entry = FCEntry()
|
||||
|
@ -1694,19 +1489,24 @@ class GeometryObjectUI(ObjectUI):
|
|||
grid1.addWidget(self.addtool_entry_lbl, 3, 0)
|
||||
grid1.addWidget(self.addtool_entry, 3, 1)
|
||||
|
||||
bhlay = QtWidgets.QHBoxLayout()
|
||||
|
||||
self.addtool_btn = QtWidgets.QPushButton(_('Add'))
|
||||
self.addtool_btn.setToolTip(
|
||||
_("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.setToolTip(
|
||||
_("Add a new tool to the Tool Table\n"
|
||||
"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.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
|
@ -1754,10 +1554,10 @@ class GeometryObjectUI(ObjectUI):
|
|||
# ################# GRID LAYOUT 3 ###############################
|
||||
# #################################################################
|
||||
|
||||
grid3 = QtWidgets.QGridLayout()
|
||||
grid3.setColumnStretch(0, 0)
|
||||
grid3.setColumnStretch(1, 1)
|
||||
self.geo_param_box.addLayout(grid3)
|
||||
self.grid3 = QtWidgets.QGridLayout()
|
||||
self.grid3.setColumnStretch(0, 0)
|
||||
self.grid3.setColumnStretch(1, 1)
|
||||
self.geo_param_box.addLayout(self.grid3)
|
||||
|
||||
# ### Tools Data ## ##
|
||||
self.tool_data_label = QtWidgets.QLabel(
|
||||
|
@ -1768,7 +1568,7 @@ class GeometryObjectUI(ObjectUI):
|
|||
"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
|
||||
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.setSingleStep(0.1)
|
||||
|
||||
grid3.addWidget(self.tipdialabel, 1, 0)
|
||||
grid3.addWidget(self.tipdia_entry, 1, 1)
|
||||
self.grid3.addWidget(self.tipdialabel, 1, 0)
|
||||
self.grid3.addWidget(self.tipdia_entry, 1, 1)
|
||||
|
||||
# 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.setSingleStep(1)
|
||||
|
||||
grid3.addWidget(self.tipanglelabel, 2, 0)
|
||||
grid3.addWidget(self.tipangle_entry, 2, 1)
|
||||
self.grid3.addWidget(self.tipanglelabel, 2, 0)
|
||||
self.grid3.addWidget(self.tipangle_entry, 2, 1)
|
||||
|
||||
# Cut Z
|
||||
self.cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
|
||||
|
@ -1819,8 +1619,8 @@ class GeometryObjectUI(ObjectUI):
|
|||
|
||||
self.cutz_entry.setSingleStep(0.1)
|
||||
|
||||
grid3.addWidget(self.cutzlabel, 3, 0)
|
||||
grid3.addWidget(self.cutz_entry, 3, 1)
|
||||
self.grid3.addWidget(self.cutzlabel, 3, 0)
|
||||
self.grid3.addWidget(self.cutz_entry, 3, 1)
|
||||
|
||||
# Multi-pass
|
||||
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])
|
||||
|
||||
grid3.addWidget(self.mpass_cb, 4, 0)
|
||||
grid3.addWidget(self.maxdepth_entry, 4, 1)
|
||||
self.grid3.addWidget(self.mpass_cb, 4, 0)
|
||||
self.grid3.addWidget(self.maxdepth_entry, 4, 1)
|
||||
|
||||
# Travel Z
|
||||
self.travelzlabel = QtWidgets.QLabel('%s:' % _('Travel Z'))
|
||||
|
@ -1864,8 +1664,8 @@ class GeometryObjectUI(ObjectUI):
|
|||
|
||||
self.travelz_entry.setSingleStep(0.1)
|
||||
|
||||
grid3.addWidget(self.travelzlabel, 5, 0)
|
||||
grid3.addWidget(self.travelz_entry, 5, 1)
|
||||
self.grid3.addWidget(self.travelzlabel, 5, 0)
|
||||
self.grid3.addWidget(self.travelz_entry, 5, 1)
|
||||
|
||||
# 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.setSingleStep(0.1)
|
||||
|
||||
grid3.addWidget(self.frlabel, 10, 0)
|
||||
grid3.addWidget(self.cncfeedrate_entry, 10, 1)
|
||||
self.grid3.addWidget(self.frlabel, 10, 0)
|
||||
self.grid3.addWidget(self.cncfeedrate_entry, 10, 1)
|
||||
|
||||
# Feedrate Z (Plunge)
|
||||
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.setSingleStep(0.1)
|
||||
|
||||
grid3.addWidget(self.frzlabel, 11, 0)
|
||||
grid3.addWidget(self.feedrate_z_entry, 11, 1)
|
||||
self.grid3.addWidget(self.frzlabel, 11, 0)
|
||||
self.grid3.addWidget(self.feedrate_z_entry, 11, 1)
|
||||
|
||||
# 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.setSingleStep(0.1)
|
||||
|
||||
grid3.addWidget(self.fr_rapidlabel, 12, 0)
|
||||
grid3.addWidget(self.feedrate_rapid_entry, 12, 1)
|
||||
self.grid3.addWidget(self.fr_rapidlabel, 12, 0)
|
||||
self.grid3.addWidget(self.feedrate_rapid_entry, 12, 1)
|
||||
# default values is to hide
|
||||
self.fr_rapidlabel.hide()
|
||||
self.feedrate_rapid_entry.hide()
|
||||
|
@ -1936,8 +1736,8 @@ class GeometryObjectUI(ObjectUI):
|
|||
"meet with last cut, we generate an\n"
|
||||
"extended cut over the first cut section.")
|
||||
)
|
||||
grid3.addWidget(self.extracut_cb, 13, 0)
|
||||
grid3.addWidget(self.e_cut_entry, 13, 1)
|
||||
self.grid3.addWidget(self.extracut_cb, 13, 0)
|
||||
self.grid3.addWidget(self.e_cut_entry, 13, 1)
|
||||
|
||||
# Spindlespeed
|
||||
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_step(100)
|
||||
|
||||
grid3.addWidget(self.spindle_label, 14, 0)
|
||||
grid3.addWidget(self.cncspindlespeed_entry, 14, 1)
|
||||
self.grid3.addWidget(self.spindle_label, 14, 0)
|
||||
self.grid3.addWidget(self.cncspindlespeed_entry, 14, 1)
|
||||
|
||||
# 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])
|
||||
|
||||
grid3.addWidget(self.dwell_cb, 15, 0)
|
||||
grid3.addWidget(self.dwelltime_entry, 15, 1)
|
||||
self.grid3.addWidget(self.dwell_cb, 15, 0)
|
||||
self.grid3.addWidget(self.dwelltime_entry, 15, 1)
|
||||
|
||||
# Probe 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.setSingleStep(0.1)
|
||||
|
||||
grid3.addWidget(self.pdepth_label, 17, 0)
|
||||
grid3.addWidget(self.pdepth_entry, 17, 1)
|
||||
self.grid3.addWidget(self.pdepth_label, 17, 0)
|
||||
self.grid3.addWidget(self.pdepth_entry, 17, 1)
|
||||
|
||||
self.pdepth_label.hide()
|
||||
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.setSingleStep(0.1)
|
||||
|
||||
grid3.addWidget(self.feedrate_probe_label, 18, 0)
|
||||
grid3.addWidget(self.feedrate_probe_entry, 18, 1)
|
||||
self.grid3.addWidget(self.feedrate_probe_label, 18, 0)
|
||||
self.grid3.addWidget(self.feedrate_probe_entry, 18, 1)
|
||||
|
||||
self.feedrate_probe_label.hide()
|
||||
self.feedrate_probe_entry.setVisible(False)
|
|
@ -8,13 +8,21 @@
|
|||
from PyQt5 import QtCore
|
||||
|
||||
import logging
|
||||
from flatcamGUI.VisPyCanvas import VisPyCanvas, Color
|
||||
from flatcamGUI.VisPyVisuals import ShapeGroup, ShapeCollection, TextCollection, TextGroup, Cursor
|
||||
from vispy.scene.visuals import InfiniteLine, Line
|
||||
from AppGUI.VisPyCanvas import VisPyCanvas, Color
|
||||
from AppGUI.VisPyVisuals import ShapeGroup, ShapeCollection, TextCollection, TextGroup, Cursor
|
||||
from vispy.scene.visuals import InfiniteLine, Line, Rectangle, Text
|
||||
|
||||
import gettext
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
import numpy as np
|
||||
from vispy.geometry import Rect
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
_ = gettext.gettext
|
||||
|
||||
log = logging.getLogger('base')
|
||||
|
||||
|
||||
|
@ -54,8 +62,12 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
|
|||
|
||||
if theme == 'white':
|
||||
self.line_color = (0.3, 0.0, 0.0, 1.0)
|
||||
self.rect_hud_color = Color('#0000FF10')
|
||||
self.text_hud_color = 'black'
|
||||
else:
|
||||
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,
|
||||
# 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,
|
||||
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
|
||||
if self.fcapp.defaults["global_cursor_color_enabled"]:
|
||||
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,
|
||||
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_collection = self.new_shape_collection()
|
||||
self.fcapp.pool_recreated.connect(self.on_pool_recreated)
|
||||
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.c = None
|
||||
|
@ -163,6 +218,76 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas):
|
|||
|
||||
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):
|
||||
"""
|
||||
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])])
|
||||
|
||||
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),
|
||||
antialias=True, method='agg', parent=self.view.scene)
|
||||
else:
|
||||
self.workspace_line.parent = self.view.scene
|
||||
# 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),
|
||||
# antialias=True, method='agg', parent=self.view.scene)
|
||||
# else:
|
||||
# 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):
|
||||
try:
|
||||
self.workspace_line.parent = None
|
||||
except Exception:
|
||||
pass
|
||||
self.fcapp.ui.wplace_label.setStyleSheet("")
|
||||
|
||||
# redraw the workspace lines on the plot by re adding them to the parent view.scene
|
||||
def restore_workspace(self):
|
|
@ -19,8 +19,10 @@ from shapely.geometry import Polygon, LineString, LinearRing
|
|||
from copy import deepcopy
|
||||
import logging
|
||||
|
||||
import numpy as np
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
# Prevent conflict with Qt5 and above.
|
||||
|
@ -29,13 +31,13 @@ mpl_use("Qt5Agg")
|
|||
from matplotlib.figure import Figure
|
||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||||
from matplotlib.lines import Line2D
|
||||
from matplotlib.offsetbox import AnchoredText
|
||||
# from matplotlib.widgets import Cursor
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
log = logging.getLogger('base')
|
||||
|
||||
|
||||
|
@ -45,9 +47,9 @@ class CanvasCache(QtCore.QObject):
|
|||
Case story #1:
|
||||
|
||||
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
|
||||
(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
|
||||
app.collection.figure. Then plots on it.
|
||||
4) Plots on a cache-size canvas (in background).
|
||||
|
@ -113,7 +115,7 @@ class CanvasCache(QtCore.QObject):
|
|||
|
||||
# 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!")
|
||||
|
||||
|
@ -147,9 +149,13 @@ class PlotCanvasLegacy(QtCore.QObject):
|
|||
if self.app.defaults['global_theme'] == 'white':
|
||||
theme_color = '#FFFFFF'
|
||||
tick_color = '#000000'
|
||||
self.rect_hud_color = '#0000FF10'
|
||||
self.text_hud_color = '#000000'
|
||||
else:
|
||||
theme_color = '#000000'
|
||||
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,
|
||||
# which might decrease performance
|
||||
|
@ -295,14 +301,163 @@ class PlotCanvasLegacy(QtCore.QObject):
|
|||
# signal is the mouse is dragging
|
||||
self.is_dragging = False
|
||||
|
||||
self.mouse_press_pos = None
|
||||
|
||||
# signal if there is a doubleclick
|
||||
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
|
||||
# all CNC have a limited workspace
|
||||
if self.app.defaults['global_workspace'] is True:
|
||||
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):
|
||||
"""
|
||||
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.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):
|
||||
try:
|
||||
self.axes.lines.remove(self.workspace_line)
|
||||
self.canvas.draw()
|
||||
except Exception:
|
||||
pass
|
||||
self.fcapp.ui.wplace_label.setStyleSheet("")
|
||||
|
||||
def graph_event_connect(self, event_name, callback):
|
||||
"""
|
||||
|
@ -423,7 +589,7 @@ class PlotCanvasLegacy(QtCore.QObject):
|
|||
|
||||
if self.big_cursor is False:
|
||||
try:
|
||||
x, y = self.app.geo_editor.snap(x_pos, y_pos)
|
||||
x, y = self.snap(x_pos, y_pos)
|
||||
|
||||
# Pointer (snapped)
|
||||
# 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
|
||||
self.canvas.draw_idle()
|
||||
|
||||
self.canvas.blit(self.axes.bbox)
|
||||
self.canvas.blit(self.axes.bbox)
|
||||
|
||||
def clear_cursor(self, state):
|
||||
if state is True:
|
||||
|
@ -781,6 +947,7 @@ class PlotCanvasLegacy(QtCore.QObject):
|
|||
def on_mouse_press(self, event):
|
||||
|
||||
self.is_dragging = True
|
||||
self.mouse_press_pos = (event.x, event.y)
|
||||
|
||||
# Check for middle mouse button press
|
||||
if self.app.defaults["global_pan_button"] == '2':
|
||||
|
@ -806,7 +973,11 @@ class PlotCanvasLegacy(QtCore.QObject):
|
|||
|
||||
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 press
|
||||
|
@ -858,7 +1029,7 @@ class PlotCanvasLegacy(QtCore.QObject):
|
|||
self.canvas.draw_idle()
|
||||
|
||||
# #### 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:
|
||||
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
|
||||
|
||||
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):
|
||||
"""
|
|
@ -13,6 +13,7 @@ import numpy as np
|
|||
|
||||
import vispy.scene as scene
|
||||
from vispy.scene.cameras.base_camera import BaseCamera
|
||||
# from vispy.scene.widgets import Widget as VisPyWidget
|
||||
from vispy.color import Color
|
||||
|
||||
import time
|
|
@ -13,7 +13,7 @@ from vispy.color import Color
|
|||
from shapely.geometry import Polygon, LineString, LinearRing
|
||||
import threading
|
||||
import numpy as np
|
||||
from flatcamGUI.VisPyTesselators import GLUTess
|
||||
from AppGUI.VisPyTesselators import GLUTess
|
||||
|
||||
|
||||
class FlatCAMLineVisual(LineVisual):
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -5,7 +5,7 @@ from defaults import FlatCAMDefaults
|
|||
import logging
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -29,7 +29,7 @@ class PreferencesUIManager:
|
|||
|
||||
: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 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
|
||||
"""
|
||||
|
||||
|
@ -43,7 +43,7 @@ class PreferencesUIManager:
|
|||
self.preferences_changed_flag = False
|
||||
|
||||
# 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 = {
|
||||
# General App
|
||||
"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_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_plot_fill": self.ui.gerber_defaults_form.gerber_gen_group.pf_color_entry,
|
||||
"gerber_plot_line": self.ui.gerber_defaults_form.gerber_gen_group.pl_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.line_color_entry,
|
||||
|
||||
# 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_noncopperrounded": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_rounded_cb,
|
||||
"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_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_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_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,
|
||||
|
@ -180,6 +168,7 @@ class PreferencesUIManager:
|
|||
# Excellon General
|
||||
"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_multicolored": self.ui.excellon_defaults_form.excellon_gen_group.multicolored_cb,
|
||||
"excellon_format_upper_in":
|
||||
self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry,
|
||||
"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 Advanced Options
|
||||
"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_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_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_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_retract": self.ui.excellon_defaults_form.excellon_adv_opt_group.fretract_cb,
|
||||
"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_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_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_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_retract": self.ui.excellon_defaults_form.excellon_adv_opt_group.fretract_cb,
|
||||
|
||||
# Excellon Export
|
||||
"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_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_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_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_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_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 Editor
|
||||
"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_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_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_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_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_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_circ_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_dir_radio,
|
||||
"excellon_editor_circ_angle":
|
||||
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,
|
||||
|
||||
# Geometry General
|
||||
"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_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_plot": self.ui.geometry_defaults_form.geometry_gen_group.plot_cb,
|
||||
"geometry_multicolored": self.ui.geometry_defaults_form.geometry_gen_group.multicolored_cb,
|
||||
"geometry_circle_steps": self.ui.geometry_defaults_form.geometry_gen_group.circle_steps_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_cutz": self.ui.geometry_defaults_form.geometry_opt_group.cutz_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_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_dwell": self.ui.geometry_defaults_form.geometry_opt_group.dwell_cb,
|
||||
"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_toolchange": self.ui.geometry_defaults_form.geometry_opt_group.toolchange_cb,
|
||||
"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_endxy": self.ui.geometry_defaults_form.geometry_opt_group.endxy_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_cutz": self.ui.geometry_defaults_form.geometry_opt_group.cutz_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_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_dwell": self.ui.geometry_defaults_form.geometry_opt_group.dwell_cb,
|
||||
"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_toolchange": self.ui.geometry_defaults_form.geometry_opt_group.toolchange_cb,
|
||||
"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_endxy": self.ui.geometry_defaults_form.geometry_opt_group.endxy_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 Advanced Options
|
||||
"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_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_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_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_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_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_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_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_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_overz": self.ui.geometry_defaults_form.geometry_adv_opt_group.over_z_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_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_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_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_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 Editor
|
||||
"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_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,
|
||||
|
||||
# CNCJob General
|
||||
"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_annotation": self.ui.cncjob_defaults_form.cncjob_gen_group.annotation_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_annotation": self.ui.cncjob_defaults_form.cncjob_gen_group.annotation_cb,
|
||||
|
||||
"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_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_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_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_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_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_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_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_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_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,
|
||||
|
||||
# CNC Job Options
|
||||
"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_prepend": self.ui.cncjob_defaults_form.cncjob_opt_group.prepend_text,
|
||||
"cncjob_append": self.ui.cncjob_defaults_form.cncjob_opt_group.append_text,
|
||||
|
||||
# CNC Job Advanced Options
|
||||
"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_annotation_fontsize": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontsize_sp,
|
||||
"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_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,
|
||||
|
||||
# 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
|
||||
"tools_ncctools": self.ui.tools_defaults_form.tools_ncc_group.ncc_tool_dia_entry,
|
||||
"tools_nccorder": self.ui.tools_defaults_form.tools_ncc_group.ncc_order_radio,
|
||||
"tools_nccoverlap": self.ui.tools_defaults_form.tools_ncc_group.ncc_overlap_entry,
|
||||
"tools_nccmargin": self.ui.tools_defaults_form.tools_ncc_group.ncc_margin_entry,
|
||||
"tools_nccmethod": self.ui.tools_defaults_form.tools_ncc_group.ncc_method_combo,
|
||||
"tools_nccconnect": self.ui.tools_defaults_form.tools_ncc_group.ncc_connect_cb,
|
||||
"tools_ncccontour": self.ui.tools_defaults_form.tools_ncc_group.ncc_contour_cb,
|
||||
"tools_nccrest": self.ui.tools_defaults_form.tools_ncc_group.ncc_rest_cb,
|
||||
"tools_ncc_offset_choice": self.ui.tools_defaults_form.tools_ncc_group.ncc_choice_offset_cb,
|
||||
"tools_ncc_offset_value": self.ui.tools_defaults_form.tools_ncc_group.ncc_offset_spinner,
|
||||
"tools_nccref": self.ui.tools_defaults_form.tools_ncc_group.select_combo,
|
||||
"tools_ncc_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_ncctool_type": self.ui.tools_defaults_form.tools_ncc_group.tool_type_radio,
|
||||
"tools_ncccutz": self.ui.tools_defaults_form.tools_ncc_group.cutz_entry,
|
||||
"tools_ncctipdia": self.ui.tools_defaults_form.tools_ncc_group.tipdia_entry,
|
||||
"tools_ncctipangle": self.ui.tools_defaults_form.tools_ncc_group.tipangle_entry,
|
||||
"tools_nccnewdia": self.ui.tools_defaults_form.tools_ncc_group.newdia_entry,
|
||||
"tools_ncctools": self.ui.tools_defaults_form.tools_ncc_group.ncc_tool_dia_entry,
|
||||
"tools_nccorder": self.ui.tools_defaults_form.tools_ncc_group.ncc_order_radio,
|
||||
"tools_nccoverlap": self.ui.tools_defaults_form.tools_ncc_group.ncc_overlap_entry,
|
||||
"tools_nccmargin": self.ui.tools_defaults_form.tools_ncc_group.ncc_margin_entry,
|
||||
"tools_nccmethod": self.ui.tools_defaults_form.tools_ncc_group.ncc_method_combo,
|
||||
"tools_nccconnect": self.ui.tools_defaults_form.tools_ncc_group.ncc_connect_cb,
|
||||
"tools_ncccontour": self.ui.tools_defaults_form.tools_ncc_group.ncc_contour_cb,
|
||||
"tools_nccrest": self.ui.tools_defaults_form.tools_ncc_group.ncc_rest_cb,
|
||||
"tools_ncc_offset_choice": self.ui.tools_defaults_form.tools_ncc_group.ncc_choice_offset_cb,
|
||||
"tools_ncc_offset_value": self.ui.tools_defaults_form.tools_ncc_group.ncc_offset_spinner,
|
||||
"tools_nccref": self.ui.tools_defaults_form.tools_ncc_group.select_combo,
|
||||
"tools_ncc_area_shape": self.ui.tools_defaults_form.tools_ncc_group.area_shape_radio,
|
||||
"tools_nccmilling_type": self.ui.tools_defaults_form.tools_ncc_group.milling_type_radio,
|
||||
"tools_ncctool_type": self.ui.tools_defaults_form.tools_ncc_group.tool_type_radio,
|
||||
"tools_ncccutz": self.ui.tools_defaults_form.tools_ncc_group.cutz_entry,
|
||||
"tools_ncctipdia": self.ui.tools_defaults_form.tools_ncc_group.tipdia_entry,
|
||||
"tools_ncctipangle": self.ui.tools_defaults_form.tools_ncc_group.tipangle_entry,
|
||||
"tools_nccnewdia": self.ui.tools_defaults_form.tools_ncc_group.newdia_entry,
|
||||
"tools_ncc_plotting": self.ui.tools_defaults_form.tools_ncc_group.plotting_radio,
|
||||
|
||||
# CutOut Tool
|
||||
"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_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 ####################################################
|
||||
# #######################################################################################################
|
||||
|
@ -650,7 +668,7 @@ class PreferencesUIManager:
|
|||
|
||||
def show_preferences_gui(self):
|
||||
"""
|
||||
Called to initialize and show the Preferences GUI
|
||||
Called to initialize and show the Preferences AppGUI
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
@ -719,7 +737,7 @@ class PreferencesUIManager:
|
|||
self.ui.fa_scroll_area.setWidget(fa_form)
|
||||
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()
|
||||
|
||||
# Button handlers
|
||||
|
@ -732,167 +750,90 @@ class PreferencesUIManager:
|
|||
|
||||
def __init_color_pickers(self):
|
||||
# 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.pf_color_button.setStyleSheet(
|
||||
"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.fill_color_entry.set_value(self.defaults['gerber_plot_fill'])
|
||||
self.ui.gerber_defaults_form.gerber_gen_group.line_color_entry.set_value(self.defaults['gerber_plot_line'])
|
||||
|
||||
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.pl_color_button.setStyleSheet(
|
||||
"background-color:%s;"
|
||||
"border-color: dimgray" % str(self.defaults['gerber_plot_line'])[:7])
|
||||
self.ui.gerber_defaults_form.gerber_gen_group.gerber_alpha_entry.set_value(
|
||||
int(self.defaults['gerber_plot_fill'][7:9], 16)) # alpha
|
||||
|
||||
# Init Excellon Plot Colors
|
||||
self.ui.excellon_defaults_form.excellon_gen_group.fill_color_entry.set_value(
|
||||
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.defaults['excellon_plot_line'])
|
||||
self.ui.excellon_defaults_form.excellon_gen_group.line_color_button.setStyleSheet(
|
||||
"background-color:%s;"
|
||||
"border-color: dimgray" % str(self.defaults['excellon_plot_line'])[:7])
|
||||
|
||||
self.ui.excellon_defaults_form.excellon_gen_group.excellon_alpha_entry.set_value(
|
||||
int(self.defaults['excellon_plot_fill'][7:9], 16))
|
||||
|
||||
# Init Geometry Plot Colors
|
||||
self.ui.geometry_defaults_form.geometry_gen_group.line_color_entry.set_value(
|
||||
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
|
||||
self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry.set_value(
|
||||
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.defaults['cncjob_travel_line'])
|
||||
self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_button.setStyleSheet(
|
||||
"background-color:%s;"
|
||||
"border-color: dimgray" % str(self.defaults['cncjob_travel_line'])[:7])
|
||||
|
||||
self.ui.cncjob_defaults_form.cncjob_gen_group.cncjob_alpha_entry.set_value(
|
||||
int(self.defaults['cncjob_travel_fill'][7:9], 16)) # alpha
|
||||
|
||||
# Init CNCJob Plot Colors
|
||||
self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_entry.set_value(
|
||||
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.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
|
||||
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_button.setStyleSheet(
|
||||
"background-color:%s;"
|
||||
"border-color: dimgray" % str(self.defaults['global_sel_line'])[:7])
|
||||
|
||||
self.ui.general_defaults_form.general_gui_group.left_right_alpha_entry.set_value(
|
||||
int(self.defaults['global_sel_fill'][7:9], 16))
|
||||
|
||||
# Init Right-Left Selection colors
|
||||
self.ui.general_defaults_form.general_gui_group.alt_sf_color_entry.set_value(
|
||||
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.defaults['global_alt_sel_line'])
|
||||
self.ui.general_defaults_form.general_gui_group.alt_sl_color_button.setStyleSheet(
|
||||
"background-color:%s;"
|
||||
"border-color: dimgray" % str(self.defaults['global_alt_sel_line'])[:7])
|
||||
|
||||
self.ui.general_defaults_form.general_gui_group.right_left_alpha_entry.set_value(
|
||||
int(self.defaults['global_sel_fill'][7:9], 16))
|
||||
|
||||
# Init Draw color and Selection Draw Color
|
||||
self.ui.general_defaults_form.general_gui_group.draw_color_entry.set_value(
|
||||
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.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
|
||||
self.ui.general_defaults_form.general_gui_group.proj_color_entry.set_value(
|
||||
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
|
||||
self.ui.general_defaults_form.general_gui_group.proj_color_dis_entry.set_value(
|
||||
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.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
|
||||
self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry.set_value(
|
||||
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
|
||||
self.ui.tools_defaults_form.tools_film_group.film_color_entry.set_value(
|
||||
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
|
||||
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_entry.set_value(
|
||||
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.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):
|
||||
log.debug("on_save_button() --> Applying preferences to file.")
|
||||
|
@ -921,12 +862,17 @@ class PreferencesUIManager:
|
|||
theme = 'white'
|
||||
|
||||
should_restart = False
|
||||
val = self.ui.general_defaults_form.general_gui_group.theme_radio.get_value()
|
||||
if val != theme:
|
||||
theme_new_val = self.ui.general_defaults_form.general_gui_group.theme_radio.get_value()
|
||||
|
||||
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.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.setIcon(QtWidgets.QMessageBox.Question)
|
||||
|
||||
bt_yes = msgbox.addButton(_('Yes'), QtWidgets.QMessageBox.YesRole)
|
||||
msgbox.addButton(_('Cancel'), QtWidgets.QMessageBox.NoRole)
|
||||
|
@ -935,15 +881,22 @@ class PreferencesUIManager:
|
|||
msgbox.exec_()
|
||||
response = msgbox.clickedButton()
|
||||
|
||||
if response == bt_yes:
|
||||
theme_settings.setValue('theme', val)
|
||||
if theme_new_val != theme:
|
||||
if response == bt_yes:
|
||||
theme_settings.setValue('theme', theme_new_val)
|
||||
|
||||
# This will write the setting to the platform specific storage.
|
||||
del theme_settings
|
||||
# This will write the setting to the platform specific storage.
|
||||
del theme_settings
|
||||
|
||||
should_restart = True
|
||||
should_restart = True
|
||||
else:
|
||||
self.ui.general_defaults_form.general_gui_group.theme_radio.set_value(theme)
|
||||
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:
|
||||
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()
|
||||
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(
|
||||
'machinist',
|
||||
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.ignore_tab_close_event = True
|
||||
|
||||
# restore stylesheet to default for the statusBar icon
|
||||
self.ui.pref_status_label.setStyleSheet("")
|
||||
|
||||
try:
|
||||
self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.disconnect()
|
||||
except (TypeError, AttributeError):
|
||||
pass
|
||||
|
||||
self.defaults_write_form(source_dict=self.defaults.current_defaults)
|
||||
self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect(
|
||||
lambda: self.ui.app.on_toggle_units(no_pref=False))
|
||||
|
@ -1035,6 +996,7 @@ class PreferencesUIManager:
|
|||
:return: None
|
||||
"""
|
||||
self.defaults.report_usage("save_defaults")
|
||||
log.debug("App.PreferencesUIManager.save_defaults()")
|
||||
|
||||
if data_path is None:
|
||||
data_path = self.data_path
|
||||
|
@ -1071,7 +1033,7 @@ class PreferencesUIManager:
|
|||
if self.ui.toolbarfile.isVisible():
|
||||
tb_status += 1
|
||||
|
||||
if self.ui.toolbargeo.isVisible():
|
||||
if self.ui.toolbaredit.isVisible():
|
||||
tb_status += 2
|
||||
|
||||
if self.ui.toolbarview.isVisible():
|
||||
|
@ -1089,7 +1051,7 @@ class PreferencesUIManager:
|
|||
if self.ui.grb_edit_toolbar.isVisible():
|
||||
tb_status += 64
|
||||
|
||||
if self.ui.snap_toolbar.isVisible():
|
||||
if self.ui.status_toolbar.isVisible():
|
||||
tb_status += 128
|
||||
|
||||
if self.ui.toolbarshell.isVisible():
|
||||
|
@ -1118,6 +1080,9 @@ class PreferencesUIManager:
|
|||
if self.ignore_tab_close_event:
|
||||
return
|
||||
|
||||
# restore stylesheet to default for the statusBar icon
|
||||
self.ui.pref_status_label.setStyleSheet("")
|
||||
|
||||
# disconnect
|
||||
for idx in range(self.ui.pref_tab_area.count()):
|
||||
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?"))
|
||||
msgbox.setWindowTitle(_("Save Preferences"))
|
||||
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)
|
||||
msgbox.addButton(_('No'), QtWidgets.QMessageBox.NoRole)
|
|
@ -1,6 +1,6 @@
|
|||
from flatcamGUI.GUIElements import *
|
||||
from AppGUI.GUIElements import *
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||
from PyQt5 import QtWidgets, QtGui
|
||||
from PyQt5.QtCore import QSettings, Qt
|
||||
|
||||
from flatcamGUI.GUIElements import FCTextArea, FCCheckBox, FCComboBox, FCSpinner, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCTextArea, FCCheckBox, FCComboBox, FCSpinner, FCColorEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -158,28 +158,16 @@ class CNCJobAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
self.annotation_color_label.setToolTip(
|
||||
_("Set the font color for the annotation texts.")
|
||||
)
|
||||
self.annotation_fontcolor_entry = FCEntry()
|
||||
self.annotation_fontcolor_button = QtWidgets.QPushButton()
|
||||
self.annotation_fontcolor_button.setFixedSize(15, 15)
|
||||
self.annotation_fontcolor_entry = FCColorEntry()
|
||||
|
||||
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(color_widget, 3, 1)
|
||||
grid0.addWidget(QtWidgets.QLabel(''), 3, 2)
|
||||
grid0.addWidget(self.annotation_fontcolor_entry, 3, 1)
|
||||
|
||||
grid0.addWidget(QtWidgets.QLabel(''), 3, 2)
|
||||
self.layout.addStretch()
|
||||
|
||||
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_button.clicked.connect(self.on_annotation_fontcolor_button)
|
||||
|
||||
def on_cnc_custom_parameters(self, signal_text):
|
||||
if signal_text == 'Parameters':
|
||||
|
@ -189,20 +177,3 @@ class CNCJobAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
|
||||
def on_annotation_fontcolor_entry(self):
|
||||
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
|
|
@ -1,10 +1,10 @@
|
|||
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCSpinner, FCDoubleSpinner, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCCheckBox, RadioSet, FCSpinner, FCDoubleSpinner, FCSliderWithSpinner, FCColorEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -170,17 +170,10 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
|
|||
self.tline_color_label.setToolTip(
|
||||
_("Set the travel line color for plotted objects.")
|
||||
)
|
||||
self.tline_color_entry = FCEntry()
|
||||
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)
|
||||
self.tline_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
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"
|
||||
"digits are for alpha (transparency) level.")
|
||||
)
|
||||
self.tfill_color_entry = FCEntry()
|
||||
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)
|
||||
self.tfill_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
self.alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.alpha_label.setToolTip(
|
||||
self.cncjob_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.cncjob_alpha_label.setToolTip(
|
||||
_("Set the fill transparency for plotted objects.")
|
||||
)
|
||||
self.tcolor_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||
self.tcolor_alpha_slider.setMinimum(0)
|
||||
self.tcolor_alpha_slider.setMaximum(255)
|
||||
self.tcolor_alpha_slider.setSingleStep(1)
|
||||
self.cncjob_alpha_entry = FCSliderWithSpinner(0, 255, 1)
|
||||
|
||||
self.tcolor_alpha_spinner = FCSpinner()
|
||||
self.tcolor_alpha_spinner.setMinimumWidth(70)
|
||||
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)
|
||||
grid0.addWidget(self.cncjob_alpha_label, 16, 0)
|
||||
grid0.addWidget(self.cncjob_alpha_entry, 16, 1)
|
||||
|
||||
separator_line = QtWidgets.QFrame()
|
||||
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
|
@ -228,7 +203,7 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
|
|||
grid0.addWidget(separator_line, 17, 0, 1, 2)
|
||||
|
||||
# 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)
|
||||
|
||||
# Plot Line Color
|
||||
|
@ -236,17 +211,10 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
|
|||
self.line_color_label.setToolTip(
|
||||
_("Set the color for plotted objects.")
|
||||
)
|
||||
self.line_color_entry = FCEntry()
|
||||
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)
|
||||
self.line_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
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"
|
||||
"digits are for alpha (transparency) level.")
|
||||
)
|
||||
self.fill_color_entry = FCEntry()
|
||||
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)
|
||||
self.fill_color_entry = FCColorEntry()
|
||||
|
||||
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()
|
||||
|
||||
# Setting plot colors signals
|
||||
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_button.clicked.connect(self.on_tfill_color_button)
|
||||
self.tcolor_alpha_spinner.valueChanged.connect(self.on_tcolor_spinner)
|
||||
self.tcolor_alpha_slider.valueChanged.connect(self.on_tcolor_slider)
|
||||
|
||||
self.cncjob_alpha_entry.valueChanged.connect(self.on_cncjob_alpha_changed) # alpha
|
||||
|
||||
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_button.clicked.connect(self.on_fill_color_button)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Setting travel colors handlers
|
||||
|
@ -288,27 +245,12 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
|
|||
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'][7:9]
|
||||
self.tfill_color_button.setStyleSheet(
|
||||
"background-color:%s" % str(self.app.defaults['cncjob_travel_fill'])[:7])
|
||||
|
||||
def on_tfill_color_button(self):
|
||||
current_color = QtGui.QColor(self.app.defaults['cncjob_travel_fill'][:7])
|
||||
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]
|
||||
|
||||
c_dialog = QtWidgets.QColorDialog()
|
||||
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)
|
||||
def on_cncjob_alpha_changed(self, spinner_value):
|
||||
self.app.defaults['cncjob_travel_fill'] = \
|
||||
self.app.defaults['cncjob_travel_fill'][:7] + \
|
||||
(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] + \
|
||||
(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
|
||||
# ------------------------------------------------------
|
||||
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'][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):
|
||||
self.app.defaults['cncjob_plot_line'] = self.line_color_entry.get_value()[:7] + \
|
||||
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
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtGui
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCTextArea
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCTextArea
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,8 +1,8 @@
|
|||
from PyQt5 import QtWidgets
|
||||
|
||||
from flatcamGUI.preferences.cncjob.CNCJobAdvOptPrefGroupUI import CNCJobAdvOptPrefGroupUI
|
||||
from flatcamGUI.preferences.cncjob.CNCJobOptPrefGroupUI import CNCJobOptPrefGroupUI
|
||||
from flatcamGUI.preferences.cncjob.CNCJobGenPrefGroupUI import CNCJobGenPrefGroupUI
|
||||
from AppGUI.preferences.cncjob.CNCJobAdvOptPrefGroupUI import CNCJobAdvOptPrefGroupUI
|
||||
from AppGUI.preferences.cncjob.CNCJobOptPrefGroupUI import CNCJobOptPrefGroupUI
|
||||
from AppGUI.preferences.cncjob.CNCJobGenPrefGroupUI import CNCJobGenPrefGroupUI
|
||||
|
||||
|
||||
class CNCJobPreferencesUI(QtWidgets.QWidget):
|
|
@ -1,10 +1,10 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, FCEntry, FloatEntry, RadioSet, FCCheckBox
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, RadioSet, FCCheckBox, NumericalEvalTupleEntry, NumericalEvalEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -60,7 +60,7 @@ class ExcellonAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
toolchange_xy_label.setToolTip(
|
||||
_("Toolchange X,Y position.")
|
||||
)
|
||||
self.toolchangexy_entry = FCEntry()
|
||||
self.toolchangexy_entry = NumericalEvalTupleEntry(border_color='#0069A9')
|
||||
|
||||
grid1.addWidget(toolchange_xy_label, 1, 0)
|
||||
grid1.addWidget(self.toolchangexy_entry, 1, 1)
|
||||
|
@ -71,7 +71,7 @@ class ExcellonAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
_("Height of the tool just after start.\n"
|
||||
"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(self.estartz_entry, 2, 1)
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,10 +1,10 @@
|
|||
from PyQt5 import QtWidgets, QtCore
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import RadioSet, FCSpinner
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import RadioSet, FCSpinner
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -3,10 +3,10 @@ import platform
|
|||
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry, FCSliderWithSpinner, FCColorEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -36,22 +36,31 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||
grid1 = QtWidgets.QGridLayout()
|
||||
self.layout.addLayout(grid1)
|
||||
|
||||
# Plot CB
|
||||
self.plot_cb = FCCheckBox(label=_('Plot'))
|
||||
self.plot_cb.setToolTip(
|
||||
"Plot (show) this object."
|
||||
)
|
||||
grid1.addWidget(self.plot_cb, 0, 0)
|
||||
|
||||
# Solid CB
|
||||
self.solid_cb = FCCheckBox(label=_('Solid'))
|
||||
self.solid_cb.setToolTip(
|
||||
"Plot as solid circles."
|
||||
)
|
||||
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.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
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()
|
||||
self.layout.addLayout(grid2)
|
||||
|
@ -255,7 +264,7 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||
grid2.addWidget(separator_line, 11, 0, 1, 2)
|
||||
|
||||
# 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)
|
||||
|
||||
# Plot Line Color
|
||||
|
@ -263,17 +272,10 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||
self.line_color_label.setToolTip(
|
||||
_("Set the line color for plotted objects.")
|
||||
)
|
||||
self.line_color_entry = FCEntry()
|
||||
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)
|
||||
self.line_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
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"
|
||||
"digits are for alpha (transparency) level.")
|
||||
)
|
||||
self.fill_color_entry = FCEntry()
|
||||
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)
|
||||
self.fill_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
self.alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.alpha_label.setToolTip(
|
||||
self.excellon_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.excellon_alpha_label.setToolTip(
|
||||
_("Set the fill transparency for plotted objects.")
|
||||
)
|
||||
self.color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||
self.color_alpha_slider.setMinimum(0)
|
||||
self.color_alpha_slider.setMaximum(255)
|
||||
self.color_alpha_slider.setSingleStep(1)
|
||||
self.excellon_alpha_entry = FCSliderWithSpinner(0, 255, 1)
|
||||
|
||||
self.color_alpha_spinner = FCSpinner()
|
||||
self.color_alpha_spinner.setMinimumWidth(70)
|
||||
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)
|
||||
grid2.addWidget(self.excellon_alpha_label, 15, 0)
|
||||
grid2.addWidget(self.excellon_alpha_entry, 15, 1)
|
||||
|
||||
self.layout.addStretch()
|
||||
|
||||
|
@ -333,14 +317,18 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||
|
||||
# Setting plot colors signals
|
||||
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_button.clicked.connect(self.on_fill_color_button)
|
||||
self.color_alpha_spinner.valueChanged.connect(self.on_color_spinner)
|
||||
self.color_alpha_slider.valueChanged.connect(self.on_color_slider)
|
||||
|
||||
self.excellon_alpha_entry.valueChanged.connect(self.on_excellon_alpha_changed) # alpha
|
||||
|
||||
# Load the defaults values into the Excellon Format and Excellon Zeros fields
|
||||
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):
|
||||
if self.excellon_optimization_radio.get_value() == 'M':
|
||||
|
@ -354,26 +342,12 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||
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'][7:9]
|
||||
self.fill_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['excellon_plot_fill'])[:7])
|
||||
|
||||
def on_fill_color_button(self):
|
||||
current_color = QtGui.QColor(self.app.defaults['excellon_plot_fill'][:7])
|
||||
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]
|
||||
|
||||
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['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)
|
||||
def on_excellon_alpha_changed(self, spinner_value):
|
||||
self.app.defaults['excellon_plot_fill'] = \
|
||||
self.app.defaults['excellon_plot_fill'][:7] + \
|
||||
(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] + \
|
||||
(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):
|
||||
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')
|
||||
|
@ -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_zeros"].set_value('L')
|
||||
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()
|
|
@ -1,12 +1,12 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import Qt, QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, FCEntry, FCSpinner, OptionalInputSection, \
|
||||
FCComboBox
|
||||
from flatcamGUI.preferences import machinist_setting
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, FCEntry, FCSpinner, OptionalInputSection, \
|
||||
FCComboBox, NumericalEvalTupleEntry
|
||||
from AppGUI.preferences import machinist_setting
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -198,7 +198,7 @@ class ExcellonOptPrefGroupUI(OptionsGroupUI):
|
|||
"If no value is entered then there is no move\n"
|
||||
"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(self.endxy_entry, 9, 1)
|
|
@ -1,14 +1,14 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.preferences.excellon.ExcellonEditorPrefGroupUI import ExcellonEditorPrefGroupUI
|
||||
from flatcamGUI.preferences.excellon.ExcellonExpPrefGroupUI import ExcellonExpPrefGroupUI
|
||||
from flatcamGUI.preferences.excellon.ExcellonAdvOptPrefGroupUI import ExcellonAdvOptPrefGroupUI
|
||||
from flatcamGUI.preferences.excellon.ExcellonOptPrefGroupUI import ExcellonOptPrefGroupUI
|
||||
from flatcamGUI.preferences.excellon.ExcellonGenPrefGroupUI import ExcellonGenPrefGroupUI
|
||||
from AppGUI.preferences.excellon.ExcellonEditorPrefGroupUI import ExcellonEditorPrefGroupUI
|
||||
from AppGUI.preferences.excellon.ExcellonExpPrefGroupUI import ExcellonExpPrefGroupUI
|
||||
from AppGUI.preferences.excellon.ExcellonAdvOptPrefGroupUI import ExcellonAdvOptPrefGroupUI
|
||||
from AppGUI.preferences.excellon.ExcellonOptPrefGroupUI import ExcellonOptPrefGroupUI
|
||||
from AppGUI.preferences.excellon.ExcellonGenPrefGroupUI import ExcellonGenPrefGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -31,7 +31,7 @@ class ExcellonPreferencesUI(QtWidgets.QWidget):
|
|||
self.decimals = 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.setMinimumWidth(290)
|
||||
self.excellon_exp_group = ExcellonExpPrefGroupUI(decimals=self.decimals)
|
|
@ -1,13 +1,13 @@
|
|||
from PyQt5 import QtCore, QtWidgets, QtGui
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCComboBox, RadioSet, OptionalInputSection, FCSpinner, \
|
||||
FCEntry
|
||||
from flatcamGUI.preferences import settings
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCComboBox, RadioSet, OptionalInputSection, FCSpinner, \
|
||||
FCColorEntry
|
||||
from AppGUI.preferences import settings
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -177,14 +177,6 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
|
|||
{'label': _('Landscape'), 'value': 'l'},
|
||||
], 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_radio, 8, 1)
|
||||
|
||||
|
@ -201,7 +193,7 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
|
|||
self.notebook_font_size_label = QtWidgets.QLabel('%s:' % _('Notebook'))
|
||||
self.notebook_font_size_label.setToolTip(
|
||||
_("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.")
|
||||
)
|
||||
|
||||
|
@ -240,8 +232,8 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
|
|||
# TextBox Font Size
|
||||
self.textbox_font_size_label = QtWidgets.QLabel('%s:' % _('Textbox'))
|
||||
self.textbox_font_size_label.setToolTip(
|
||||
_("This sets the font size for the Textbox GUI\n"
|
||||
"elements that are used in FlatCAM.")
|
||||
_("This sets the font size for the Textbox AppGUI\n"
|
||||
"elements that are used in the application.")
|
||||
)
|
||||
|
||||
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_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.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
grid0.addWidget(separator_line, 14, 0, 1, 2)
|
||||
grid0.addWidget(separator_line, 16, 0, 1, 2)
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# -------------- MOUSE SETTINGS -----------------------------
|
||||
|
@ -323,24 +334,16 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
|
|||
self.mouse_color_label.setToolTip(
|
||||
_("Set the color of the mouse cursor.")
|
||||
)
|
||||
self.mouse_cursor_entry = FCEntry()
|
||||
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)
|
||||
self.mouse_cursor_entry = FCColorEntry()
|
||||
|
||||
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.mouse_cursor_color_cb,
|
||||
[
|
||||
self.mouse_color_label,
|
||||
self.mouse_cursor_entry,
|
||||
self.mouse_cursor_button
|
||||
self.mouse_cursor_entry
|
||||
]
|
||||
)
|
||||
# Select mouse pan button
|
||||
|
@ -440,9 +443,7 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
|
|||
self.layout.addStretch()
|
||||
|
||||
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_button.clicked.connect(self.on_mouse_cursor_button)
|
||||
|
||||
def on_mouse_cursor_color_enable(self, val):
|
||||
if val:
|
||||
|
@ -461,23 +462,4 @@ class GeneralAPPSetGroupUI(OptionsGroupUI):
|
|||
|
||||
def on_mouse_cursor_entry(self):
|
||||
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"]
|
|
@ -3,12 +3,12 @@ import sys
|
|||
from PyQt5 import QtWidgets
|
||||
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
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -380,12 +380,11 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
|
|||
|
||||
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
|
||||
"""
|
||||
|
||||
self.app.defaults.report_usage("on_toggle_shell_from_settings()")
|
||||
|
||||
if state is True:
|
||||
if not self.app.ui.shell_dock.isVisible():
|
||||
self.app.ui.shell_dock.show()
|
|
@ -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"]
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||
from PyQt5.QtCore import QSettings, Qt
|
||||
|
||||
from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import RadioSet, FCCheckBox, FCComboBox, FCSliderWithSpinner, FCColorEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -35,7 +35,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
# Theme selection
|
||||
self.theme_label = QtWidgets.QLabel('%s:' % _('Theme'))
|
||||
self.theme_label.setToolTip(
|
||||
_("Select a theme for FlatCAM.\n"
|
||||
_("Select a theme for the application.\n"
|
||||
"It will theme the plot area.")
|
||||
)
|
||||
|
||||
|
@ -72,7 +72,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
# Layout selection
|
||||
self.layout_label = QtWidgets.QLabel('%s:' % _('Layout'))
|
||||
self.layout_label.setToolTip(
|
||||
_("Select an layout for FlatCAM.\n"
|
||||
_("Select a layout for the application.\n"
|
||||
"It is applied immediately.")
|
||||
)
|
||||
self.layout_combo = FCComboBox()
|
||||
|
@ -94,7 +94,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
# Style selection
|
||||
self.style_label = QtWidgets.QLabel('%s:' % _('Style'))
|
||||
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.")
|
||||
)
|
||||
self.style_combo = FCComboBox()
|
||||
|
@ -110,7 +110,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
# Enable High DPI Support
|
||||
self.hdpi_cb = FCCheckBox('%s' % _('Activate HDPI Support'))
|
||||
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.")
|
||||
)
|
||||
|
||||
|
@ -126,7 +126,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
# Enable Hover box
|
||||
self.hover_cb = FCCheckBox('%s' % _('Display Hover Shape'))
|
||||
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"
|
||||
"over any kind of not-selected object.")
|
||||
)
|
||||
|
@ -135,7 +135,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
# Enable Selection box
|
||||
self.selection_cb = FCCheckBox('%s' % _('Display Selection Shape'))
|
||||
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"
|
||||
"either by clicking or dragging mouse from left to right or\n"
|
||||
"right to left.")
|
||||
|
@ -155,17 +155,10 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
self.sl_color_label.setToolTip(
|
||||
_("Set the line color for the 'left to right' selection box.")
|
||||
)
|
||||
self.sl_color_entry = FCEntry()
|
||||
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)
|
||||
self.sl_color_entry = FCColorEntry()
|
||||
|
||||
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.setToolTip(
|
||||
|
@ -174,38 +167,20 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
"First 6 digits are the color and the last 2\n"
|
||||
"digits are for alpha (transparency) level.")
|
||||
)
|
||||
self.sf_color_entry = FCEntry()
|
||||
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)
|
||||
self.sf_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
self.sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.sf_alpha_label.setToolTip(
|
||||
self.left_right_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.left_right_alpha_label.setToolTip(
|
||||
_("Set the fill transparency for the 'left to right' selection box.")
|
||||
)
|
||||
self.sf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||
self.sf_color_alpha_slider.setMinimum(0)
|
||||
self.sf_color_alpha_slider.setMaximum(255)
|
||||
self.sf_color_alpha_slider.setSingleStep(1)
|
||||
self.left_right_alpha_entry = FCSliderWithSpinner(0, 255, 1)
|
||||
|
||||
self.sf_color_alpha_spinner = FCSpinner()
|
||||
self.sf_color_alpha_spinner.setMinimumWidth(70)
|
||||
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)
|
||||
grid0.addWidget(self.left_right_alpha_label, 18, 0)
|
||||
grid0.addWidget(self.left_right_alpha_entry, 18, 1)
|
||||
|
||||
separator_line = QtWidgets.QFrame()
|
||||
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
|
@ -221,17 +196,10 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
self.alt_sl_color_label.setToolTip(
|
||||
_("Set the line color for the 'right to left' selection box.")
|
||||
)
|
||||
self.alt_sl_color_entry = FCEntry()
|
||||
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)
|
||||
self.alt_sl_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
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"
|
||||
"digits are for alpha (transparency) level.")
|
||||
)
|
||||
self.alt_sf_color_entry = FCEntry()
|
||||
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)
|
||||
self.alt_sf_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
self.alt_sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.alt_sf_alpha_label.setToolTip(
|
||||
self.right_left_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.right_left_alpha_label.setToolTip(
|
||||
_("Set the fill transparency for selection 'right to left' box.")
|
||||
)
|
||||
self.alt_sf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||
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.right_left_alpha_entry = FCSliderWithSpinner(0, 255, 1)
|
||||
|
||||
self.alt_sf_color_alpha_spinner = FCSpinner()
|
||||
self.alt_sf_color_alpha_spinner.setMinimumWidth(70)
|
||||
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)
|
||||
grid0.addWidget(self.right_left_alpha_label, 23, 0)
|
||||
grid0.addWidget(self.right_left_alpha_entry, 23, 1)
|
||||
|
||||
separator_line = QtWidgets.QFrame()
|
||||
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
|
@ -291,34 +241,20 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
self.alt_sf_color_label.setToolTip(
|
||||
_("Set the color for the shape.")
|
||||
)
|
||||
self.draw_color_entry = FCEntry()
|
||||
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)
|
||||
self.draw_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
self.sel_draw_color_label = QtWidgets.QLabel('%s:' % _('Selection'))
|
||||
self.sel_draw_color_label.setToolTip(
|
||||
_("Set the color of the shape when selected.")
|
||||
)
|
||||
self.sel_draw_color_entry = FCEntry()
|
||||
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)
|
||||
self.sel_draw_color_entry = FCColorEntry()
|
||||
|
||||
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.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
|
@ -337,34 +273,20 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
self.proj_color_label.setToolTip(
|
||||
_("Set the color of the items in Project Tab Tree.")
|
||||
)
|
||||
self.proj_color_entry = FCEntry()
|
||||
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)
|
||||
self.proj_color_entry = FCColorEntry()
|
||||
|
||||
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.setToolTip(
|
||||
_("Set the color of the items in Project Tab Tree,\n"
|
||||
"for the case when the items are disabled.")
|
||||
)
|
||||
self.proj_color_dis_entry = FCEntry()
|
||||
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)
|
||||
self.proj_color_dis_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
self.project_autohide_cb = FCCheckBox(label=_('Project AutoHide'))
|
||||
|
@ -387,32 +309,22 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
|
||||
# Setting selection (left - right) colors signals
|
||||
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_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
|
||||
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_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
|
||||
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_button.clicked.connect(self.on_sel_draw_color_button)
|
||||
|
||||
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_button.clicked.connect(self.on_proj_color_dis_button)
|
||||
|
||||
self.layout_combo.activated.connect(self.on_layout)
|
||||
|
||||
|
@ -437,191 +349,64 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
# Setting selection colors (left - right) handlers
|
||||
def on_sf_color_entry(self):
|
||||
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):
|
||||
current_color = QtGui.QColor(self.app.defaults['global_sel_fill'][:7])
|
||||
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]
|
||||
|
||||
c_dialog = QtWidgets.QColorDialog()
|
||||
plot_fill_color = c_dialog.getColor(initial=current_color)
|
||||
def on_left_right_alpha_changed(self, spinner_value):
|
||||
"""
|
||||
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:
|
||||
return
|
||||
:param spinner_value: passed value within [0, 255]
|
||||
: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] + \
|
||||
(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] + \
|
||||
(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
|
||||
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'][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):
|
||||
current_color = QtGui.QColor(self.app.defaults['global_alt_sel_fill'][:7])
|
||||
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]
|
||||
|
||||
c_dialog = QtWidgets.QColorDialog()
|
||||
plot_fill_color = c_dialog.getColor(initial=current_color)
|
||||
def on_right_left_alpha_changed(self, spinner_value):
|
||||
"""
|
||||
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:
|
||||
return
|
||||
:param spinner_value: passed value within [0, 255]
|
||||
: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] + \
|
||||
(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] + \
|
||||
(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
|
||||
def on_draw_color_entry(self):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
"""
|
||||
|
@ -647,14 +432,13 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
# first remove the toolbars:
|
||||
try:
|
||||
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.toolbarshell)
|
||||
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.geo_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)
|
||||
except Exception:
|
||||
pass
|
||||
|
@ -665,9 +449,9 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI):
|
|||
self.app.ui.toolbarfile.setObjectName('File_TB')
|
||||
self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarfile)
|
||||
|
||||
self.app.ui.toolbargeo = QtWidgets.QToolBar('Edit Toolbar')
|
||||
self.app.ui.toolbargeo.setObjectName('Edit_TB')
|
||||
self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbargeo)
|
||||
self.app.ui.toolbaredit = QtWidgets.QToolBar('Edit Toolbar')
|
||||
self.app.ui.toolbaredit.setObjectName('Edit_TB')
|
||||
self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbaredit)
|
||||
|
||||
self.app.ui.toolbarshell = QtWidgets.QToolBar('Shell Toolbar')
|
||||
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.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:
|
||||
# ## TOOLBAR INSTALLATION # ##
|
||||
self.app.ui.toolbarfile = QtWidgets.QToolBar('File Toolbar')
|
||||
self.app.ui.toolbarfile.setObjectName('File_TB')
|
||||
self.app.ui.addToolBar(self.app.ui.toolbarfile)
|
||||
|
||||
self.app.ui.toolbargeo = QtWidgets.QToolBar('Edit Toolbar')
|
||||
self.app.ui.toolbargeo.setObjectName('Edit_TB')
|
||||
self.app.ui.addToolBar(self.app.ui.toolbargeo)
|
||||
self.app.ui.toolbaredit = QtWidgets.QToolBar('Edit Toolbar')
|
||||
self.app.ui.toolbaredit.setObjectName('Edit_TB')
|
||||
self.app.ui.addToolBar(self.app.ui.toolbaredit)
|
||||
|
||||
self.app.ui.toolbarview = QtWidgets.QToolBar('View Toolbar')
|
||||
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.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':
|
||||
self.app.ui.toolbarview.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.grb_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.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_y_entry.setText(str(self.app.defaults["global_gridy"]))
|
|
@ -1,12 +1,12 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.preferences.general.GeneralAppPrefGroupUI import GeneralAppPrefGroupUI
|
||||
from flatcamGUI.preferences.general.GeneralAPPSetGroupUI import GeneralAPPSetGroupUI
|
||||
from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI
|
||||
from AppGUI.preferences.general.GeneralAppPrefGroupUI import GeneralAppPrefGroupUI
|
||||
from AppGUI.preferences.general.GeneralAPPSetGroupUI import GeneralAPPSetGroupUI
|
||||
from AppGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,12 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCEntry, FloatEntry, FCDoubleSpinner, FCCheckBox, RadioSet, FCLabel
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, RadioSet, FCLabel, NumericalEvalTupleEntry, \
|
||||
NumericalEvalEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -46,8 +47,9 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
toolchange_xy_label.setToolTip(
|
||||
_("Toolchange X,Y position.")
|
||||
)
|
||||
self.toolchangexy_entry = NumericalEvalTupleEntry(border_color='#0069A9')
|
||||
|
||||
grid1.addWidget(toolchange_xy_label, 1, 0)
|
||||
self.toolchangexy_entry = FCEntry()
|
||||
grid1.addWidget(self.toolchangexy_entry, 1, 1)
|
||||
|
||||
# Start move Z
|
||||
|
@ -56,8 +58,9 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
_("Height of the tool just after starting the work.\n"
|
||||
"Delete the value if you don't need this feature.")
|
||||
)
|
||||
self.gstartz_entry = NumericalEvalEntry(border_color='#0069A9')
|
||||
|
||||
grid1.addWidget(startzlabel, 2, 0)
|
||||
self.gstartz_entry = FloatEntry()
|
||||
grid1.addWidget(self.gstartz_entry, 2, 1)
|
||||
|
||||
# Feedrate rapids
|
||||
|
@ -186,6 +189,11 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
grid1.addWidget(segy_label, 11, 0)
|
||||
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 ----------
|
||||
# -----------------------------
|
||||
|
@ -195,10 +203,10 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
"Those parameters are available only for\n"
|
||||
"Advanced App. Level.")
|
||||
)
|
||||
grid1.addWidget(self.adv_label, 12, 0, 1, 2)
|
||||
grid1.addWidget(self.adv_label, 13, 0, 1, 2)
|
||||
|
||||
# Exclusion Area CB
|
||||
self.exclusion_cb = FCCheckBox('%s:' % _("Exclusion areas"))
|
||||
self.exclusion_cb = FCCheckBox('%s' % _("Exclusion areas"))
|
||||
self.exclusion_cb.setToolTip(
|
||||
_(
|
||||
"Include exclusion areas.\n"
|
||||
|
@ -206,7 +214,7 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
"is forbidden."
|
||||
)
|
||||
)
|
||||
grid1.addWidget(self.exclusion_cb, 13, 0, 1, 2)
|
||||
grid1.addWidget(self.exclusion_cb, 14, 0, 1, 2)
|
||||
|
||||
# Area Selection 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'},
|
||||
{'label': _("Polygon"), 'value': 'polygon'}])
|
||||
|
||||
grid1.addWidget(self.area_shape_label, 14, 0)
|
||||
grid1.addWidget(self.area_shape_radio, 14, 1)
|
||||
grid1.addWidget(self.area_shape_label, 15, 0)
|
||||
grid1.addWidget(self.area_shape_radio, 15, 1)
|
||||
|
||||
# Chose Strategy
|
||||
self.strategy_label = FCLabel('%s:' % _("Strategy"))
|
||||
|
@ -229,8 +237,8 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
self.strategy_radio = RadioSet([{'label': _('Over'), 'value': 'over'},
|
||||
{'label': _('Around'), 'value': 'around'}])
|
||||
|
||||
grid1.addWidget(self.strategy_label, 15, 0)
|
||||
grid1.addWidget(self.strategy_radio, 15, 1)
|
||||
grid1.addWidget(self.strategy_label, 16, 0)
|
||||
grid1.addWidget(self.strategy_radio, 16, 1)
|
||||
|
||||
# Over Z
|
||||
self.over_z_label = FCLabel('%s:' % _("Over Z"))
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCSpinner, RadioSet
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCSpinner, RadioSet
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCCheckBox, FCSpinner, FCEntry, FCColorEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -31,12 +31,22 @@ class GeometryGenPrefGroupUI(OptionsGroupUI):
|
|||
self.plot_options_label = QtWidgets.QLabel("<b>%s:</b>" % _("Plot Options"))
|
||||
self.layout.addWidget(self.plot_options_label)
|
||||
|
||||
plot_hlay = QtWidgets.QHBoxLayout()
|
||||
self.layout.addLayout(plot_hlay)
|
||||
|
||||
# Plot CB
|
||||
self.plot_cb = FCCheckBox(label=_('Plot'))
|
||||
self.plot_cb.setToolTip(
|
||||
_("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()
|
||||
self.layout.addLayout(grid0)
|
||||
|
@ -77,7 +87,7 @@ class GeometryGenPrefGroupUI(OptionsGroupUI):
|
|||
grid0.addWidget(separator_line, 9, 0, 1, 2)
|
||||
|
||||
# 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)
|
||||
|
||||
# Plot Line Color
|
||||
|
@ -85,39 +95,15 @@ class GeometryGenPrefGroupUI(OptionsGroupUI):
|
|||
self.line_color_label.setToolTip(
|
||||
_("Set the line color for plotted objects.")
|
||||
)
|
||||
self.line_color_entry = FCEntry()
|
||||
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)
|
||||
self.line_color_entry = FCColorEntry()
|
||||
|
||||
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()
|
||||
|
||||
# Setting plot colors signals
|
||||
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):
|
||||
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)
|
|
@ -1,12 +1,13 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import Qt, QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, OptionalInputSection, FCEntry, FCSpinner, FCComboBox
|
||||
from flatcamGUI.preferences import machinist_setting
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, OptionalInputSection, FCSpinner, FCComboBox, \
|
||||
NumericalEvalTupleEntry
|
||||
from AppGUI.preferences import machinist_setting
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -176,7 +177,7 @@ class GeometryOptPrefGroupUI(OptionsGroupUI):
|
|||
"If no value is entered then there is no move\n"
|
||||
"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(self.endxy_entry, 7, 1)
|
|
@ -1,13 +1,13 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.preferences.geometry.GeometryEditorPrefGroupUI import GeometryEditorPrefGroupUI
|
||||
from flatcamGUI.preferences.geometry.GeometryAdvOptPrefGroupUI import GeometryAdvOptPrefGroupUI
|
||||
from flatcamGUI.preferences.geometry.GeometryOptPrefGroupUI import GeometryOptPrefGroupUI
|
||||
from flatcamGUI.preferences.geometry.GeometryGenPrefGroupUI import GeometryGenPrefGroupUI
|
||||
from AppGUI.preferences.geometry.GeometryEditorPrefGroupUI import GeometryEditorPrefGroupUI
|
||||
from AppGUI.preferences.geometry.GeometryAdvOptPrefGroupUI import GeometryAdvOptPrefGroupUI
|
||||
from AppGUI.preferences.geometry.GeometryOptPrefGroupUI import GeometryOptPrefGroupUI
|
||||
from AppGUI.preferences.geometry.GeometryGenPrefGroupUI import GeometryGenPrefGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner, FCSpinner, OptionalInputSection
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner, FCSpinner, OptionalInputSection
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -63,85 +63,6 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
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_label = QtWidgets.QLabel('%s:' % _('Buffering'))
|
||||
buffering_label.setToolTip(
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, FCComboBox, FCEntry, RadioSet
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCSpinner, FCDoubleSpinner, FCComboBox, FCEntry, RadioSet, NumericalEvalTupleEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -109,8 +109,9 @@ class GerberEditorPrefGroupUI(OptionsGroupUI):
|
|||
"The value of the diameter has to use the dot decimals separator.\n"
|
||||
"Valid values: 0.3, 1.0")
|
||||
)
|
||||
self.adddim_entry = NumericalEvalTupleEntry(border_color='#0069A9')
|
||||
|
||||
grid0.addWidget(self.adddim_label, 5, 0)
|
||||
self.adddim_entry = FCEntry()
|
||||
grid0.addWidget(self.adddim_entry, 5, 1)
|
||||
|
||||
self.grb_array_linear_label = QtWidgets.QLabel('<b>%s:</b>' % _('Linear Pad Array'))
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtCore
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import RadioSet, FCSpinner
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import RadioSet, FCSpinner
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry, FCSliderWithSpinner, FCColorEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -34,26 +34,26 @@ class GerberGenPrefGroupUI(OptionsGroupUI):
|
|||
grid0 = QtWidgets.QGridLayout()
|
||||
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
|
||||
self.solid_cb = FCCheckBox(label='%s' % _('Solid'))
|
||||
self.solid_cb.setToolTip(
|
||||
_("Solid color polygons.")
|
||||
)
|
||||
grid0.addWidget(self.solid_cb, 0, 0)
|
||||
grid0.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.")
|
||||
)
|
||||
grid0.addWidget(self.multicolored_cb, 0, 1)
|
||||
|
||||
# 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)
|
||||
grid0.addWidget(self.multicolored_cb, 0, 2)
|
||||
|
||||
# Number of circle steps for circular aperture linear approximation
|
||||
self.circle_steps_label = QtWidgets.QLabel('%s:' % _("Circle Steps"))
|
||||
|
@ -146,100 +146,55 @@ class GerberGenPrefGroupUI(OptionsGroupUI):
|
|||
grid0.addWidget(separator_line, 9, 0, 1, 3)
|
||||
|
||||
# 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)
|
||||
|
||||
# Plot Line Color
|
||||
self.pl_color_label = QtWidgets.QLabel('%s:' % _('Outline'))
|
||||
self.pl_color_label.setToolTip(
|
||||
self.line_color_label = QtWidgets.QLabel('%s:' % _('Outline'))
|
||||
self.line_color_label.setToolTip(
|
||||
_("Set the line color for plotted objects.")
|
||||
)
|
||||
self.pl_color_entry = FCEntry()
|
||||
self.pl_color_button = QtWidgets.QPushButton()
|
||||
self.pl_color_button.setFixedSize(15, 15)
|
||||
self.line_color_entry = FCColorEntry()
|
||||
|
||||
self.form_box_child_2 = QtWidgets.QHBoxLayout()
|
||||
self.form_box_child_2.addWidget(self.pl_color_entry)
|
||||
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)
|
||||
grid0.addWidget(self.line_color_label, 11, 0)
|
||||
grid0.addWidget(self.line_color_entry, 11, 1, 1, 2)
|
||||
|
||||
# Plot Fill Color
|
||||
self.pf_color_label = QtWidgets.QLabel('%s:' % _('Fill'))
|
||||
self.pf_color_label.setToolTip(
|
||||
self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill'))
|
||||
self.fill_color_label.setToolTip(
|
||||
_("Set the fill color for plotted objects.\n"
|
||||
"First 6 digits are the color and the last 2\n"
|
||||
"digits are for alpha (transparency) level.")
|
||||
)
|
||||
self.pf_color_entry = FCEntry()
|
||||
self.pf_color_button = QtWidgets.QPushButton()
|
||||
self.pf_color_button.setFixedSize(15, 15)
|
||||
self.fill_color_entry = FCColorEntry()
|
||||
|
||||
self.form_box_child_1 = QtWidgets.QHBoxLayout()
|
||||
self.form_box_child_1.addWidget(self.pf_color_entry)
|
||||
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)
|
||||
grid0.addWidget(self.fill_color_label, 12, 0)
|
||||
grid0.addWidget(self.fill_color_entry, 12, 1, 1, 2)
|
||||
|
||||
# Plot Fill Transparency Level
|
||||
self.pf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.pf_alpha_label.setToolTip(
|
||||
self.gerber_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha'))
|
||||
self.gerber_alpha_label.setToolTip(
|
||||
_("Set the fill transparency for plotted objects.")
|
||||
)
|
||||
self.pf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||
self.pf_color_alpha_slider.setMinimum(0)
|
||||
self.pf_color_alpha_slider.setMaximum(255)
|
||||
self.pf_color_alpha_slider.setSingleStep(1)
|
||||
self.gerber_alpha_entry = FCSliderWithSpinner(0, 255, 1)
|
||||
|
||||
self.pf_color_alpha_spinner = FCSpinner()
|
||||
self.pf_color_alpha_spinner.setMinimumWidth(70)
|
||||
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)
|
||||
grid0.addWidget(self.gerber_alpha_label, 13, 0)
|
||||
grid0.addWidget(self.gerber_alpha_entry, 13, 1, 1, 2)
|
||||
|
||||
self.layout.addStretch()
|
||||
|
||||
# Setting plot colors signals
|
||||
self.pl_color_entry.editingFinished.connect(self.on_pl_color_entry)
|
||||
self.pl_color_button.clicked.connect(self.on_pl_color_button)
|
||||
self.pf_color_entry.editingFinished.connect(self.on_pf_color_entry)
|
||||
self.pf_color_button.clicked.connect(self.on_pf_color_button)
|
||||
self.pf_color_alpha_spinner.valueChanged.connect(self.on_pf_color_spinner)
|
||||
self.pf_color_alpha_slider.valueChanged.connect(self.on_pf_color_slider)
|
||||
self.line_color_entry.editingFinished.connect(self.on_line_color_changed)
|
||||
self.fill_color_entry.editingFinished.connect(self.on_fill_color_changed)
|
||||
|
||||
self.gerber_alpha_entry.valueChanged.connect(self.on_gerber_alpha_changed) # alpha
|
||||
|
||||
# Setting plot colors handlers
|
||||
def on_pf_color_entry(self):
|
||||
self.app.defaults['gerber_plot_fill'] = self.pf_color_entry.get_value()[:7] + \
|
||||
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_fill_color_changed(self):
|
||||
self.app.defaults['gerber_plot_fill'] = self.fill_color_entry.get_value()[:7] + \
|
||||
self.app.defaults['gerber_plot_fill'][7:9]
|
||||
|
||||
def on_pf_color_button(self):
|
||||
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)
|
||||
def on_gerber_alpha_changed(self, spinner_value):
|
||||
self.app.defaults['gerber_plot_fill'] = \
|
||||
self.app.defaults['gerber_plot_fill'][:7] + \
|
||||
(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] + \
|
||||
(hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00')
|
||||
|
||||
def on_pf_color_slider(self):
|
||||
slider_value = self.pf_color_alpha_slider.value()
|
||||
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] + \
|
||||
def on_line_color_changed(self):
|
||||
self.app.defaults['gerber_plot_line'] = self.line_color_entry.get_value()[:7] + \
|
||||
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
|
|
@ -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()
|
|
@ -1,14 +1,14 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.preferences.gerber.GerberEditorPrefGroupUI import GerberEditorPrefGroupUI
|
||||
from flatcamGUI.preferences.gerber.GerberExpPrefGroupUI import GerberExpPrefGroupUI
|
||||
from flatcamGUI.preferences.gerber.GerberAdvOptPrefGroupUI import GerberAdvOptPrefGroupUI
|
||||
from flatcamGUI.preferences.gerber.GerberOptPrefGroupUI import GerberOptPrefGroupUI
|
||||
from flatcamGUI.preferences.gerber.GerberGenPrefGroupUI import GerberGenPrefGroupUI
|
||||
from AppGUI.preferences.gerber.GerberEditorPrefGroupUI import GerberEditorPrefGroupUI
|
||||
from AppGUI.preferences.gerber.GerberExpPrefGroupUI import GerberExpPrefGroupUI
|
||||
from AppGUI.preferences.gerber.GerberAdvOptPrefGroupUI import GerberAdvOptPrefGroupUI
|
||||
from AppGUI.preferences.gerber.GerberOptPrefGroupUI import GerberOptPrefGroupUI
|
||||
from AppGUI.preferences.gerber.GerberGenPrefGroupUI import GerberGenPrefGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -44,6 +44,7 @@ class GerberPreferencesUI(QtWidgets.QWidget):
|
|||
self.vlay = QtWidgets.QVBoxLayout()
|
||||
self.vlay.addWidget(self.gerber_opt_group)
|
||||
self.vlay.addWidget(self.gerber_exp_group)
|
||||
self.vlay.addStretch()
|
||||
|
||||
self.layout.addWidget(self.gerber_gen_group)
|
||||
self.layout.addLayout(self.vlay)
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, NumericalEvalTupleEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -116,7 +116,7 @@ class Tools2CalPrefGroupUI(OptionsGroupUI):
|
|||
"(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(self.toolchange_xy_entry, 7, 1, 1, 2)
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, RadioSet
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, RadioSet
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, RadioSet
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, RadioSet
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCSpinner
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCSpinner
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,18 +1,18 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.preferences.tools.Tools2InvertPrefGroupUI import Tools2InvertPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.Tools2PunchGerberPrefGroupUI import Tools2PunchGerberPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.Tools2EDrillsPrefGroupUI import Tools2EDrillsPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.Tools2CalPrefGroupUI import Tools2CalPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.Tools2FiducialsPrefGroupUI import Tools2FiducialsPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.Tools2CThievingPrefGroupUI import Tools2CThievingPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.Tools2QRCodePrefGroupUI import Tools2QRCodePrefGroupUI
|
||||
from flatcamGUI.preferences.tools.Tools2OptimalPrefGroupUI import Tools2OptimalPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.Tools2RulesCheckPrefGroupUI import Tools2RulesCheckPrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2InvertPrefGroupUI import Tools2InvertPrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2PunchGerberPrefGroupUI import Tools2PunchGerberPrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2EDrillsPrefGroupUI import Tools2EDrillsPrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2CalPrefGroupUI import Tools2CalPrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2FiducialsPrefGroupUI import Tools2FiducialsPrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2CThievingPrefGroupUI import Tools2CThievingPrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2QRCodePrefGroupUI import Tools2QRCodePrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2OptimalPrefGroupUI import Tools2OptimalPrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2RulesCheckPrefGroupUI import Tools2RulesCheckPrefGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtCore
|
||||
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||
from PyQt5.QtCore import Qt, QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCSpinner, RadioSet, FCTextArea, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCSpinner, RadioSet, FCTextArea, FCEntry, FCColorEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -153,42 +153,20 @@ class Tools2QRCodePrefGroupUI(OptionsGroupUI):
|
|||
self.fill_color_label.setToolTip(
|
||||
_("Set the QRCode fill color (squares color).")
|
||||
)
|
||||
self.fill_color_entry = FCEntry()
|
||||
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)
|
||||
self.fill_color_entry = FCColorEntry()
|
||||
|
||||
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 #
|
||||
self.back_color_label = QtWidgets.QLabel('%s:' % _('Back Color'))
|
||||
self.back_color_label.setToolTip(
|
||||
_("Set the QRCode background color.")
|
||||
)
|
||||
self.back_color_entry = FCEntry()
|
||||
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)
|
||||
self.back_color_entry = FCColorEntry()
|
||||
|
||||
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
|
||||
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_entry, 11, 1)
|
||||
# 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()
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCCheckBox, FCDoubleSpinner
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCCheckBox, FCDoubleSpinner
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, RadioSet
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, RadioSet
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -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()
|
|
@ -1,12 +1,12 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, RadioSet, FCComboBox
|
||||
from flatcamGUI.preferences import machinist_setting
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, RadioSet, FCComboBox
|
||||
from AppGUI.preferences import machinist_setting
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtCore
|
||||
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||
from PyQt5.QtCore import Qt, QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import RadioSet, FCEntry, FCDoubleSpinner, FCCheckBox, FCComboBox
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import RadioSet, FCEntry, FCDoubleSpinner, FCCheckBox, FCComboBox, FCColorEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -30,8 +30,7 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
|
|||
# ## Parameters
|
||||
self.film_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
|
||||
self.film_label.setToolTip(
|
||||
_("Create a PCB film from a Gerber or Geometry\n"
|
||||
"FlatCAM object.\n"
|
||||
_("Create a PCB film from a Gerber or Geometry object.\n"
|
||||
"The file is saved in SVG format.")
|
||||
)
|
||||
self.layout.addWidget(self.film_label)
|
||||
|
@ -58,20 +57,10 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
|
|||
self.film_color_label.setToolTip(
|
||||
_("Set the film color when positive film is selected.")
|
||||
)
|
||||
self.film_color_entry = FCEntry()
|
||||
self.film_color_button = QtWidgets.QPushButton()
|
||||
self.film_color_button.setFixedSize(15, 15)
|
||||
self.film_color_entry = FCColorEntry()
|
||||
|
||||
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(film_color_widget, 1, 1)
|
||||
grid0.addWidget(self.film_color_entry, 1, 1)
|
||||
|
||||
# Film Border
|
||||
self.film_boundary_entry = FCDoubleSpinner()
|
||||
|
@ -314,3 +303,9 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
|
|||
grid0.addWidget(self.pagesize_combo, 17, 1)
|
||||
|
||||
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()
|
|
@ -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()
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCEntry, RadioSet, FCDoubleSpinner, FCComboBox, FCCheckBox
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import RadioSet, FCDoubleSpinner, FCComboBox, FCCheckBox, NumericalEvalTupleEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -45,7 +45,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
|
|||
"Valid values: 0.3, 1.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"))
|
||||
grid0.addWidget(self.ncc_tool_dia_entry, 0, 1)
|
||||
|
||||
|
@ -227,7 +227,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
|
|||
# ], orientation='vertical', stretch=False)
|
||||
self.ncc_method_combo = FCComboBox()
|
||||
self.ncc_method_combo.addItems(
|
||||
[_("Standard"), _("Seed"), _("Lines")]
|
||||
[_("Standard"), _("Seed"), _("Lines"), _("Combo")]
|
||||
)
|
||||
|
||||
grid0.addWidget(methodlabel, 12, 0)
|
||||
|
@ -285,7 +285,7 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
|
|||
grid0.addWidget(separator_line, 16, 0, 1, 2)
|
||||
|
||||
# Rest machining CheckBox
|
||||
self.ncc_rest_cb = FCCheckBox('%s' % _("Rest Machining"))
|
||||
self.ncc_rest_cb = FCCheckBox('%s' % _("Rest"))
|
||||
self.ncc_rest_cb.setToolTip(
|
||||
_("If checked, use 'rest machining'.\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)
|
||||
|
||||
# ## Plotting type
|
||||
self.ncc_plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'},
|
||||
{"label": _("Progressive"), "value": "progressive"}])
|
||||
plotting_label = QtWidgets.QLabel('%s:' % _("NCC Plotting"))
|
||||
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 NCC job\n"
|
||||
"- 'Progressive' - after each shape is generated it will be plotted.")
|
||||
_("- 'Normal' - normal plotting, done at the end of the job\n"
|
||||
"- 'Progressive' - each shape is plotted after it is generated")
|
||||
)
|
||||
grid0.addWidget(plotting_label, 21, 0)
|
||||
grid0.addWidget(self.ncc_plotting_radio, 21, 1)
|
||||
grid0.addWidget(self.plotting_radio, 21, 1)
|
||||
|
||||
self.layout.addStretch()
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCEntry, RadioSet, FCDoubleSpinner, FCComboBox, FCCheckBox
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import RadioSet, FCDoubleSpinner, FCComboBox, FCCheckBox, NumericalEvalTupleEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -53,7 +53,7 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
|
|||
)
|
||||
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"))
|
||||
|
||||
grid0.addWidget(self.painttooldia_entry, 0, 1)
|
||||
|
@ -105,7 +105,7 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
|
|||
cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
|
||||
cutzlabel.setToolTip(
|
||||
_("Depth of cut into material. Negative value.\n"
|
||||
"In FlatCAM units.")
|
||||
"In application units.")
|
||||
)
|
||||
self.cutz_entry = FCDoubleSpinner()
|
||||
self.cutz_entry.set_precision(self.decimals)
|
||||
|
@ -114,7 +114,7 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
|
|||
|
||||
self.cutz_entry.setToolTip(
|
||||
_("Depth of cut into material. Negative value.\n"
|
||||
"In FlatCAM units.")
|
||||
"In application units.")
|
||||
)
|
||||
grid0.addWidget(cutzlabel, 4, 0)
|
||||
grid0.addWidget(self.cutz_entry, 4, 1)
|
||||
|
@ -241,8 +241,8 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
|
|||
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
grid0.addWidget(separator_line, 13, 0, 1, 2)
|
||||
|
||||
self.rest_cb = FCCheckBox('%s' % _("Rest Machining"))
|
||||
self.rest_cb.setObjectName(_("Rest Machining"))
|
||||
self.rest_cb = FCCheckBox('%s' % _("Rest"))
|
||||
self.rest_cb.setObjectName(_("Rest"))
|
||||
self.rest_cb.setToolTip(
|
||||
_("If checked, use 'rest machining'.\n"
|
||||
"Basically it will clear copper outside PCB features,\n"
|
||||
|
@ -277,7 +277,7 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
|
|||
# )
|
||||
self.selectmethod_combo = FCComboBox()
|
||||
self.selectmethod_combo.addItems(
|
||||
[_("Polygon Selection"), _("Area Selection"), _("All Polygons"), _("Reference Object")]
|
||||
[_("Polygon Selection"), _("Area Selection"), _("All"), _("Reference Object")]
|
||||
)
|
||||
|
||||
grid0.addWidget(selectlabel, 15, 0)
|
||||
|
@ -302,10 +302,10 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
|
|||
# ## Plotting type
|
||||
self.paint_plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'},
|
||||
{"label": _("Progressive"), "value": "progressive"}])
|
||||
plotting_label = QtWidgets.QLabel('%s:' % _("Paint Plotting"))
|
||||
plotting_label = QtWidgets.QLabel('%s:' % _("Plotting"))
|
||||
plotting_label.setToolTip(
|
||||
_("- 'Normal' - normal plotting, done at the end of the Paint job\n"
|
||||
"- 'Progressive' - after each shape is generated it will be plotted.")
|
||||
_("- 'Normal' - normal plotting, done at the end of the job\n"
|
||||
"- 'Progressive' - each shape is plotted after it is generated")
|
||||
)
|
||||
grid0.addWidget(plotting_label, 20, 0)
|
||||
grid0.addWidget(self.paint_plotting_radio, 20, 1)
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, FCSpinner, RadioSet, FCCheckBox
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, FCSpinner, RadioSet, FCCheckBox
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,19 +1,22 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.preferences.tools.ToolsSubPrefGroupUI import ToolsSubPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.ToolsSolderpastePrefGroupUI import ToolsSolderpastePrefGroupUI
|
||||
from flatcamGUI.preferences.tools.ToolsTransformPrefGroupUI import ToolsTransformPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.ToolsCalculatorsPrefGroupUI import ToolsCalculatorsPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.ToolsPanelizePrefGroupUI import ToolsPanelizePrefGroupUI
|
||||
from flatcamGUI.preferences.tools.ToolsFilmPrefGroupUI import ToolsFilmPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.ToolsPaintPrefGroupUI import ToolsPaintPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.Tools2sidedPrefGroupUI import Tools2sidedPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.ToolsCutoutPrefGroupUI import ToolsCutoutPrefGroupUI
|
||||
from flatcamGUI.preferences.tools.ToolsNCCPrefGroupUI import ToolsNCCPrefGroupUI
|
||||
from AppGUI.preferences.tools.ToolsSubPrefGroupUI import ToolsSubPrefGroupUI
|
||||
from AppGUI.preferences.tools.ToolsSolderpastePrefGroupUI import ToolsSolderpastePrefGroupUI
|
||||
from AppGUI.preferences.tools.ToolsCornersPrefGroupUI import ToolsCornersPrefGroupUI
|
||||
from AppGUI.preferences.tools.ToolsTransformPrefGroupUI import ToolsTransformPrefGroupUI
|
||||
from AppGUI.preferences.tools.ToolsCalculatorsPrefGroupUI import ToolsCalculatorsPrefGroupUI
|
||||
from AppGUI.preferences.tools.ToolsPanelizePrefGroupUI import ToolsPanelizePrefGroupUI
|
||||
from AppGUI.preferences.tools.ToolsFilmPrefGroupUI import ToolsFilmPrefGroupUI
|
||||
from AppGUI.preferences.tools.Tools2sidedPrefGroupUI import Tools2sidedPrefGroupUI
|
||||
|
||||
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 FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -35,6 +38,9 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
|
|||
self.setLayout(self.layout)
|
||||
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.setMinimumWidth(220)
|
||||
|
||||
|
@ -62,6 +68,9 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
|
|||
self.tools_solderpaste_group = ToolsSolderpastePrefGroupUI(decimals=self.decimals)
|
||||
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.setMinimumWidth(200)
|
||||
|
||||
|
@ -71,7 +80,7 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
|
|||
|
||||
self.vlay1 = QtWidgets.QVBoxLayout()
|
||||
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.addWidget(self.tools_transform_group)
|
||||
|
@ -84,6 +93,8 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
|
|||
|
||||
self.vlay4 = QtWidgets.QVBoxLayout()
|
||||
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.vlay1)
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCEntry, FCDoubleSpinner, FCSpinner, FCComboBox
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, FCSpinner, FCComboBox, NumericalEvalTupleEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -45,7 +45,7 @@ class ToolsSolderpastePrefGroupUI(OptionsGroupUI):
|
|||
"The value of the diameter has to use the dot decimals separator.\n"
|
||||
"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(self.nozzle_tool_dia_entry, 0, 1)
|
||||
|
@ -130,7 +130,7 @@ class ToolsSolderpastePrefGroupUI(OptionsGroupUI):
|
|||
grid0.addWidget(self.z_toolchange_entry, 6, 1)
|
||||
|
||||
# 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.setToolTip(
|
||||
_("The X,Y location for tool (nozzle) change.\n"
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCCheckBox
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCCheckBox
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCDoubleSpinner, FCCheckBox, NumericalEvalTupleEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -31,7 +31,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
|
|||
self.transform_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
|
||||
self.transform_label.setToolTip(
|
||||
_("Various transformations that can be applied\n"
|
||||
"on a FlatCAM object.")
|
||||
"on a application object.")
|
||||
)
|
||||
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 '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_entry, 15, 0, 1, 2)
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtGui
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCButton, FCTextArea, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCButton, FCTextArea, FCEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtGui
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import VerticalScrollArea, FCButton, FCTextArea, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import VerticalScrollArea, FCButton, FCTextArea, FCEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtGui
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCButton, FCTextArea, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCButton, FCTextArea, FCEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,11 +1,11 @@
|
|||
from PyQt5 import QtWidgets, QtGui
|
||||
from PyQt5.QtCore import QSettings
|
||||
|
||||
from flatcamGUI.GUIElements import FCButton, FCTextArea, FCEntry
|
||||
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
from AppGUI.GUIElements import FCButton, FCTextArea, FCEntry
|
||||
from AppGUI.preferences.OptionsGroupUI import OptionsGroupUI
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
|
@ -1,9 +1,9 @@
|
|||
from PyQt5 import QtWidgets
|
||||
|
||||
from flatcamGUI.preferences.utilities.AutoCompletePrefGroupUI import AutoCompletePrefGroupUI
|
||||
from flatcamGUI.preferences.utilities.FAGrbPrefGroupUI import FAGrbPrefGroupUI
|
||||
from flatcamGUI.preferences.utilities.FAGcoPrefGroupUI import FAGcoPrefGroupUI
|
||||
from flatcamGUI.preferences.utilities.FAExcPrefGroupUI import FAExcPrefGroupUI
|
||||
from AppGUI.preferences.utilities.AutoCompletePrefGroupUI import AutoCompletePrefGroupUI
|
||||
from AppGUI.preferences.utilities.FAGrbPrefGroupUI import FAGrbPrefGroupUI
|
||||
from AppGUI.preferences.utilities.FAGcoPrefGroupUI import FAGcoPrefGroupUI
|
||||
from AppGUI.preferences.utilities.FAExcPrefGroupUI import FAExcPrefGroupUI
|
||||
|
||||
|
||||
class UtilPreferencesUI(QtWidgets.QWidget):
|
|
@ -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()
|
|
@ -14,8 +14,8 @@ from copy import deepcopy
|
|||
from io import StringIO
|
||||
from datetime import datetime
|
||||
|
||||
from flatcamEditors.FlatCAMTextEditor import TextEditor
|
||||
from flatcamObjects.FlatCAMObj import *
|
||||
from AppEditors.FlatCAMTextEditor import TextEditor
|
||||
from AppObjects.FlatCAMObj import *
|
||||
|
||||
from camlib import CNCjob
|
||||
|
||||
|
@ -24,7 +24,7 @@ import sys
|
|||
import math
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -504,17 +504,17 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
try:
|
||||
dir_file_to_save = self.app.get_last_save_folder() + '/' + str(name)
|
||||
filename, _f = FCFileSaveDialog.get_saved_filename(
|
||||
caption=_("Export Machine Code ..."),
|
||||
caption=_("Export Code ..."),
|
||||
directory=dir_file_to_save,
|
||||
filter=_filter_
|
||||
ext_filter=_filter_
|
||||
)
|
||||
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)
|
||||
|
||||
if filename == '':
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export Machine Code cancelled ..."))
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export cancelled ..."))
|
||||
return
|
||||
else:
|
||||
if save_gcode is True:
|
||||
|
@ -535,7 +535,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
if self.app.defaults["global_open_style"] is False:
|
||||
self.app.file_opened.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):
|
||||
"""
|
||||
|
@ -564,7 +564,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
|
||||
# delete the absolute and relative position and messages in the infobar
|
||||
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)
|
||||
self.gcode_editor_tab.code_editor.clear()
|
||||
|
@ -989,7 +989,6 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
for key in self.cnc_tools:
|
||||
ppg = self.cnc_tools[key]['data']['ppname_g']
|
||||
if 'toolchange_custom' not in str(ppg).lower():
|
||||
print(ppg)
|
||||
if self.ui.toolchange_cb.get_value():
|
||||
self.ui.toolchange_cb.set_value(False)
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
||||
|
@ -1107,7 +1106,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
except ValueError:
|
||||
# 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]
|
||||
self.plot2(dia_plot, obj=self, visible=visible, kind=kind)
|
||||
self.plot2(tooldia=dia_plot, obj=self, visible=visible, kind=kind)
|
||||
else:
|
||||
# multiple tools usage
|
||||
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)
|
||||
|
||||
# TODO: until the gcode parsed will be stored on each Excellon tool this will not get executed
|
||||
if self.exc_cnc_tools:
|
||||
for tooldia_key in self.exc_cnc_tools:
|
||||
tooldia = float('%.*f' % (self.decimals, float(tooldia_key)))
|
||||
# gcode_parsed = self.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)
|
||||
# I do this so the travel lines thickness will reflect the tool diameter
|
||||
# may work only for objects created within the app and not Gcode imported from elsewhere for which we
|
||||
# don't know the origin
|
||||
if self.origin_kind == "excellon":
|
||||
if self.exc_cnc_tools:
|
||||
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()
|
||||
except (ObjectDeleted, AttributeError):
|
|
@ -10,11 +10,11 @@
|
|||
# File modified by: Marius Stanciu #
|
||||
# ##########################################################
|
||||
|
||||
from flatcamEditors.FlatCAMTextEditor import TextEditor
|
||||
from flatcamObjects.FlatCAMObj import *
|
||||
from AppEditors.FlatCAMTextEditor import TextEditor
|
||||
from AppObjects.FlatCAMObj import *
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -284,6 +284,27 @@ class DocumentObject(FlatCAMObj):
|
|||
self.ui.sel_color_entry.set_value(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):
|
||||
"""
|
||||
Returns a representation of the object as a dictionary.
|
|
@ -15,13 +15,14 @@ from shapely.geometry import Point, LineString
|
|||
|
||||
from copy import deepcopy
|
||||
|
||||
from flatcamParsers.ParseExcellon import Excellon
|
||||
from flatcamObjects.FlatCAMObj import *
|
||||
from AppParsers.ParseExcellon import Excellon
|
||||
from AppObjects.FlatCAMObj import *
|
||||
|
||||
import itertools
|
||||
import numpy as np
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -31,7 +32,7 @@ if '_' not in builtins.__dict__:
|
|||
|
||||
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
|
||||
|
@ -50,6 +51,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
self.options.update({
|
||||
"plot": True,
|
||||
"solid": False,
|
||||
"multicolored": False,
|
||||
|
||||
"operation": "drill",
|
||||
"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
|
||||
|
||||
:param exc_list: List or one object of ExcellonObject Objects to join.
|
||||
:param exc_final: Destination ExcellonObject object.
|
||||
:return: None
|
||||
:param exc_list: List or one object of ExcellonObject Objects to join.
|
||||
:type exc_list: list
|
||||
:param exc_final: Destination ExcellonObject object.
|
||||
:type exc_final: class
|
||||
:return: None
|
||||
"""
|
||||
|
||||
if decimals is None:
|
||||
|
@ -316,6 +320,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
exc_final.create_geometry()
|
||||
|
||||
def build_ui(self):
|
||||
"""
|
||||
Will (re)build the Excellon UI updating it (the tool table)
|
||||
|
||||
:return: None
|
||||
:rtype:
|
||||
"""
|
||||
FlatCAMObj.build_ui(self)
|
||||
|
||||
# Area Exception - exclusion shape added signal
|
||||
|
@ -586,9 +596,9 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
Configures the user interface for this object.
|
||||
Connects options to form fields.
|
||||
|
||||
:param ui: User interface object.
|
||||
:type ui: ExcellonObjectUI
|
||||
:return: None
|
||||
:param ui: User interface object.
|
||||
:type ui: ExcellonObjectUI
|
||||
:return: None
|
||||
"""
|
||||
FlatCAMObj.set_ui(self, ui)
|
||||
|
||||
|
@ -599,6 +609,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
self.form_fields.update({
|
||||
"plot": self.ui.plot_cb,
|
||||
"solid": self.ui.solid_cb,
|
||||
"multicolored": self.ui.multicolored_cb,
|
||||
|
||||
"operation": self.ui.operation_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.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_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)
|
||||
|
@ -729,6 +742,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
self.ui.operation_radio.setEnabled(False)
|
||||
|
||||
def ui_connect(self):
|
||||
"""
|
||||
Will connect all signals in the Excellon UI that needs to be connected
|
||||
|
||||
:return: None
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
# selective plotting
|
||||
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)
|
||||
|
||||
def ui_disconnect(self):
|
||||
"""
|
||||
Will disconnect all signals in the Excellon UI that needs to be disconnected
|
||||
|
||||
:return: None
|
||||
:rtype:
|
||||
"""
|
||||
# selective plotting
|
||||
for row in range(self.ui.tools_table.rowCount()):
|
||||
try:
|
||||
|
@ -793,6 +818,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
pass
|
||||
|
||||
def on_row_selection_change(self):
|
||||
"""
|
||||
Called when the user clicks on a row in Tools Table
|
||||
|
||||
:return: None
|
||||
:rtype:
|
||||
"""
|
||||
self.ui_disconnect()
|
||||
|
||||
sel_rows = []
|
||||
|
@ -843,6 +874,14 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
self.ui_connect()
|
||||
|
||||
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 storage_key in dict_storage:
|
||||
if form_key == storage_key and form_key not in \
|
||||
|
@ -854,6 +893,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
pass
|
||||
|
||||
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:
|
||||
# there is no tool in tool table so we can't save the GUI elements values to storage
|
||||
return
|
||||
|
@ -882,6 +927,14 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
self.ui_connect()
|
||||
|
||||
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':
|
||||
self.ui.mill_type_label.show()
|
||||
self.ui.milling_type_radio.show()
|
||||
|
@ -910,10 +963,10 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
def get_selected_tools_list(self):
|
||||
"""
|
||||
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.
|
||||
:rtype: list
|
||||
:return: List of tools.
|
||||
:rtype: list
|
||||
"""
|
||||
|
||||
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
|
||||
|
||||
:return: List of table_tools items.
|
||||
:rtype: list
|
||||
:return: List of table_tools items.
|
||||
:rtype: list
|
||||
"""
|
||||
table_tools_items = []
|
||||
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'):
|
||||
"""
|
||||
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 = ''
|
||||
|
@ -1118,13 +1185,25 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
|
||||
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
|
||||
it takes it's options from parameters or otherwise from the
|
||||
object's options and returns a (success, msg) tuple as feedback
|
||||
for shell operations.
|
||||
|
||||
:return: Success/failure condition tuple (bool, str).
|
||||
:rtype: tuple
|
||||
:param tools: A list of tools where the drills are to be milled or a string: "all"
|
||||
: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
|
||||
|
@ -1167,6 +1246,15 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
return False, "Error: Milling tool is larger than hole."
|
||||
|
||||
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)
|
||||
|
||||
# ## 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['type'] = 'Excellon Geometry'
|
||||
geo_obj.options["cnctooldia"] = str(tooldia)
|
||||
|
||||
geo_obj.options["multidepth"] = self.options["multidepth"]
|
||||
geo_obj.solid_geometry = []
|
||||
|
||||
# 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)
|
||||
|
||||
if use_thread:
|
||||
def geo_thread(app_obj):
|
||||
app_obj.new_object("geometry", outname, geo_init, plot=plot)
|
||||
def geo_thread(a_obj):
|
||||
a_obj.app_obj.new_object("geometry", outname, geo_init, plot=plot)
|
||||
|
||||
# Create a promise with the new name
|
||||
self.app.collection.promise(outname)
|
||||
|
@ -1205,19 +1293,31 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
# Send to worker
|
||||
self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
|
||||
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, ""
|
||||
|
||||
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
|
||||
it takes it's options from parameters or otherwise from the
|
||||
object's options and returns a (success, msg) tuple as feedback
|
||||
for shell operations.
|
||||
|
||||
:return: Success/failure condition tuple (bool, str).
|
||||
:rtype: tuple
|
||||
:param tools: A list of tools where the drills are to be milled or a string: "all"
|
||||
: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
|
||||
|
@ -1258,7 +1358,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
return False, "Error: Milling tool is larger than hole."
|
||||
|
||||
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
|
||||
|
||||
|
@ -1270,7 +1370,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
geo_obj.options['Tools_in_use'] = tool_table_items
|
||||
geo_obj.options['type'] = 'Excellon Geometry'
|
||||
geo_obj.options["cnctooldia"] = str(tooldia)
|
||||
|
||||
geo_obj.options["multidepth"] = self.options["multidepth"]
|
||||
geo_obj.solid_geometry = []
|
||||
|
||||
# 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)
|
||||
|
||||
if use_thread:
|
||||
def geo_thread(app_obj):
|
||||
app_obj.new_object("geometry", outname + '_slot', geo_init, plot=plot)
|
||||
def geo_thread(a_obj):
|
||||
a_obj.app_obj.new_object("geometry", outname + '_slot', geo_init, plot=plot)
|
||||
|
||||
# Create a promise with the new name
|
||||
self.app.collection.promise(outname)
|
||||
|
@ -1309,7 +1409,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
# Send to worker
|
||||
self.app.worker_task.emit({'fcn': geo_thread, 'params': [self.app]})
|
||||
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, ""
|
||||
|
||||
|
@ -1317,13 +1417,13 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
self.app.defaults.report_usage("excellon_on_create_milling_drills button")
|
||||
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):
|
||||
self.app.defaults.report_usage("excellon_on_create_milling_slots_button")
|
||||
self.read_form()
|
||||
|
||||
self.generate_milling_slots(use_thread=False)
|
||||
self.generate_milling_slots(use_thread=False, plot=True)
|
||||
|
||||
def on_pp_changed(self):
|
||||
current_pp = self.ui.pp_excellon_name_cb.get_value()
|
||||
|
@ -1443,7 +1543,7 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
job_name = self.options["name"] + "_cnc"
|
||||
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):
|
||||
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()
|
||||
|
||||
# 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")):
|
||||
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.
|
||||
self.app.collection.promise(job_name)
|
||||
|
@ -1656,6 +1756,12 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
self.read_form_item('solid')
|
||||
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):
|
||||
if self.muted_ui:
|
||||
return
|
||||
|
@ -1729,6 +1835,27 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
if not FlatCAMObj.plot(self):
|
||||
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:
|
||||
# # Plot Excellon (All polygons?)
|
||||
# if self.options["solid"]:
|
||||
|
@ -1760,12 +1887,26 @@ class ExcellonObject(FlatCAMObj, Excellon):
|
|||
try:
|
||||
# Plot Excellon (All polygons?)
|
||||
if self.options["solid"]:
|
||||
for geo in self.solid_geometry:
|
||||
self.add_shape(shape=geo,
|
||||
color=self.outline_color,
|
||||
face_color=self.fill_color,
|
||||
visible=visible,
|
||||
layer=2)
|
||||
# for geo in self.solid_geometry:
|
||||
# self.add_shape(shape=geo,
|
||||
# color=self.outline_color,
|
||||
# face_color=random_color() if self.options['multicolored'] else self.fill_color,
|
||||
# visible=visible,
|
||||
# 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:
|
||||
for geo in self.solid_geometry:
|
||||
self.add_shape(shape=geo.exterior, color='red', visible=visible)
|
|
@ -15,7 +15,7 @@ import shapely.affinity as affinity
|
|||
|
||||
from camlib import Geometry
|
||||
|
||||
from flatcamObjects.FlatCAMObj import *
|
||||
from AppObjects.FlatCAMObj import *
|
||||
|
||||
import ezdxf
|
||||
import math
|
||||
|
@ -24,7 +24,7 @@ from copy import deepcopy
|
|||
import traceback
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -52,6 +52,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
|
||||
self.options.update({
|
||||
"plot": True,
|
||||
"multicolored": False,
|
||||
"cutz": -0.002,
|
||||
"vtipdia": 0.1,
|
||||
"vtipangle": 30,
|
||||
|
@ -304,25 +305,9 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
|
||||
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
|
||||
# -----------------------------
|
||||
e_len = len(self.app.exc_areas.exclusion_areas_storage)
|
||||
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.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):
|
||||
FlatCAMObj.set_ui(self, ui)
|
||||
|
||||
|
@ -391,6 +397,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
|
||||
self.form_fields.update({
|
||||
"plot": self.ui.plot_cb,
|
||||
"multicolored": self.ui.multicolored_cb,
|
||||
"cutz": self.ui.cutz_entry,
|
||||
"vtipdia": self.ui.tipdia_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.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.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))
|
||||
|
@ -652,8 +661,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
self.ui.tool_offset_entry.get_value().replace(',', '.')
|
||||
)
|
||||
except ValueError:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_("Wrong value format entered, use a number."))
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number."))
|
||||
return
|
||||
|
||||
def ui_connect(self):
|
||||
|
@ -661,6 +669,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
# changes in geometry UI
|
||||
for i in self.param_fields:
|
||||
current_widget = self.param_fields[i]
|
||||
|
||||
if isinstance(current_widget, FCCheckBox):
|
||||
current_widget.stateChanged.connect(self.gui_form_to_storage)
|
||||
elif isinstance(current_widget, FCComboBox):
|
||||
|
@ -931,7 +940,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
self.ui_connect()
|
||||
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:
|
||||
self.ui.geo_param_frame.setDisabled(False)
|
||||
|
||||
|
@ -1007,7 +1016,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
self.ui_connect()
|
||||
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:
|
||||
self.ui.geo_param_frame.setDisabled(False)
|
||||
|
||||
|
@ -1188,7 +1197,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
obj_active.options['xmax'] = 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:
|
||||
self.ui.geo_param_frame.setDisabled(True)
|
||||
|
||||
|
@ -1382,16 +1391,18 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
self.ui_connect()
|
||||
|
||||
def gui_form_to_storage(self):
|
||||
self.ui_disconnect()
|
||||
|
||||
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
|
||||
log.debug("GeometryObject.gui_form_to_storage() --> no tool in Tools Table, aborting.")
|
||||
return
|
||||
|
||||
self.ui_disconnect()
|
||||
widget_changed = self.sender()
|
||||
try:
|
||||
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
|
||||
|
||||
# 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
|
||||
(including the solid_geometry)
|
||||
: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 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
|
||||
|
@ -1778,7 +1789,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
self.app.inform.emit(msg)
|
||||
return
|
||||
|
||||
# Object initialization function for app.new_object()
|
||||
# Object initialization function for app.app_obj.new_object()
|
||||
# RUNNING ON SEPARATE THREAD!
|
||||
def job_init_single_geometry(job_obj, app_obj):
|
||||
log.debug("Creating a CNCJob out of a single-geometry")
|
||||
|
@ -1918,7 +1929,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
})
|
||||
dia_cnc_dict.clear()
|
||||
|
||||
# Object initialization function for app.new_object()
|
||||
# Object initialization function for app.app_obj.new_object()
|
||||
# RUNNING ON SEPARATE THREAD!
|
||||
def job_init_multi_geometry(job_obj, app_obj):
|
||||
log.debug("Creating a CNCJob out of a multi-geometry")
|
||||
|
@ -2072,15 +2083,15 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
|
||||
if use_thread:
|
||||
# To be run in separate thread
|
||||
def job_thread(app_obj):
|
||||
def job_thread(a_obj):
|
||||
if self.multigeo is False:
|
||||
with self.app.proc_container.new(_("Generating CNC Code")):
|
||||
if app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot) != 'fail':
|
||||
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
||||
if a_obj.app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot) != 'fail':
|
||||
a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
||||
else:
|
||||
with self.app.proc_container.new(_("Generating CNC Code")):
|
||||
if app_obj.new_object("cncjob", outname, job_init_multi_geometry) != 'fail':
|
||||
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
||||
if a_obj.app_obj.new_object("cncjob", outname, job_init_multi_geometry) != 'fail':
|
||||
a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
||||
|
||||
# Create a promise with the name
|
||||
self.app.collection.promise(outname)
|
||||
|
@ -2088,23 +2099,15 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
||||
else:
|
||||
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:
|
||||
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(
|
||||
self, outname=None,
|
||||
dia=None, offset=None,
|
||||
z_cut=None, z_move=None,
|
||||
feedrate=None, feedrate_z=None, feedrate_rapid=None,
|
||||
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):
|
||||
def generatecncjob(self, outname=None, dia=None, offset=None, z_cut=None, z_move=None,
|
||||
feedrate=None, feedrate_z=None, feedrate_rapid=None, spindlespeed=None, dwell=None, dwelltime=None,
|
||||
multidepth=None, dpp=None, toolchange=None, toolchangez=None, toolchangexy=None,
|
||||
extracut=None, extracut_length=None, startz=None, endz=None, endxy=None, pp=None, segx=None, segy=None,
|
||||
use_thread=True, plot=True):
|
||||
"""
|
||||
Only used by the TCL Command Cncjob.
|
||||
Creates a CNCJob out of this Geometry object. The actual
|
||||
|
@ -2123,14 +2126,17 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
:param dwell:
|
||||
:param dwelltime:
|
||||
:param multidepth:
|
||||
:param depthperpass:
|
||||
:param dpp: Depth for each pass when multidepth parameter is True
|
||||
:param toolchange:
|
||||
: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_length:
|
||||
:param startz:
|
||||
: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 segx:
|
||||
: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"])
|
||||
|
||||
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'])
|
||||
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"]
|
||||
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"])
|
||||
|
||||
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"]
|
||||
|
||||
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"]
|
||||
|
||||
# Object initialization function for app.new_object()
|
||||
# Object initialization function for app.app_obj.new_object()
|
||||
# RUNNING ON SEPARATE THREAD!
|
||||
def job_init(job_obj, app_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
|
||||
def job_thread(app_obj):
|
||||
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)
|
||||
|
||||
# Create a promise with the name
|
||||
|
@ -2232,7 +2249,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
# Send to worker
|
||||
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
||||
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):
|
||||
# if self.muted_ui:
|
||||
|
@ -2652,6 +2669,27 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
if not FlatCAMObj.plot(self):
|
||||
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:
|
||||
# plot solid geometries found as members of self.tools attribute dict
|
||||
# for MultiGeo
|
||||
|
@ -2659,7 +2697,8 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
for tooluid_key in self.tools:
|
||||
solid_geometry = self.tools[tooluid_key]['solid_geometry']
|
||||
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:
|
||||
# plot solid geometry that may be an direct attribute of the geometry object
|
||||
# for SingleGeo
|
||||
|
@ -2727,6 +2766,12 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|||
self.ui.plot_cb.setChecked(True)
|
||||
self.ui_connect()
|
||||
|
||||
def on_multicolored_cb_click(self, *args):
|
||||
if self.muted_ui:
|
||||
return
|
||||
self.read_form_item('multicolored')
|
||||
self.plot()
|
||||
|
||||
@staticmethod
|
||||
def merge(geo_list, geo_final, multigeo=None):
|
||||
"""
|
|
@ -14,15 +14,15 @@
|
|||
from shapely.geometry import Point, Polygon, MultiPolygon, MultiLineString, LineString, LinearRing
|
||||
from shapely.ops import cascaded_union
|
||||
|
||||
from flatcamParsers.ParseGerber import Gerber
|
||||
from flatcamObjects.FlatCAMObj import *
|
||||
from AppParsers.ParseGerber import Gerber
|
||||
from AppObjects.FlatCAMObj import *
|
||||
|
||||
import math
|
||||
import numpy as np
|
||||
from copy import deepcopy
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -115,23 +115,13 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
"plot": True,
|
||||
"multicolored": 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,
|
||||
"noncopperrounded": False,
|
||||
"bboxmargin": 0.0,
|
||||
"bboxrounded": False,
|
||||
"aperture_display": False,
|
||||
"follow": False,
|
||||
"iso_scope": 'all',
|
||||
"iso_type": 'full'
|
||||
"milling_type": 'cl',
|
||||
})
|
||||
|
||||
# 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,
|
||||
"multicolored": self.ui.multicolored_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,
|
||||
"noncopperrounded": self.ui.noncopper_rounded_cb,
|
||||
"bboxmargin": self.ui.bbmargin_entry,
|
||||
"bboxrounded": self.ui.bbrounded_cb,
|
||||
"aperture_display": self.ui.aperture_table_visibility_cb,
|
||||
"follow": self.ui.follow_cb,
|
||||
"iso_scope": self.ui.iso_scope_radio,
|
||||
"iso_type": self.ui.iso_type_radio
|
||||
"follow": self.ui.follow_cb
|
||||
})
|
||||
|
||||
# Fill form fields only on object create
|
||||
self.to_form()
|
||||
|
||||
assert isinstance(self.ui, GerberObjectUI)
|
||||
|
||||
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
|
||||
self.ui.solid_cb.stateChanged.connect(self.on_solid_cb_click)
|
||||
self.ui.multicolored_cb.stateChanged.connect(self.on_multicolored_cb_click)
|
||||
self.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_cutout_button.clicked.connect(self.app.cutout_tool.run)
|
||||
|
||||
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.aperture_table_visibility_cb.stateChanged.connect(self.on_aperture_table_visibility_change)
|
||||
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
|
||||
if self.app.defaults["global_app_level"] == 'b':
|
||||
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.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.except_cb.setChecked(False)
|
||||
self.ui.except_cb.hide()
|
||||
|
||||
else:
|
||||
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':
|
||||
self.ui.create_buffer_button.show()
|
||||
|
@ -296,58 +242,6 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
self.build_ui()
|
||||
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):
|
||||
FlatCAMObj.build_ui(self)
|
||||
|
||||
|
@ -530,7 +424,7 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
return "fail"
|
||||
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):
|
||||
self.app.defaults.report_usage("gerber_on_generatebb_button")
|
||||
|
@ -556,244 +450,24 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
return "fail"
|
||||
geo_obj.solid_geometry = bounding_box
|
||||
|
||||
self.app.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."))
|
||||
self.app.app_obj.new_object("geometry", name, geo_init)
|
||||
|
||||
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):
|
||||
"""
|
||||
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 geometry: specific geometry to isolate
|
||||
:param dia: Tool diameter
|
||||
:param passes: Number of tool widths to cut
|
||||
:param overlap: Overlap between passes in fraction of tool diameter
|
||||
: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 milling_type: type of milling: conventional or climbing
|
||||
:param iso_type: type of isolation to be done: 0 = exteriors, 1 = interiors and 2 = both
|
||||
:param geometry: specific geometry to isolate
|
||||
:param dia: Tool diameter
|
||||
:param passes: Number of tool widths to cut
|
||||
:param overlap: Overlap between passes in fraction of tool diameter
|
||||
: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 milling_type: type of milling: conventional or climbing
|
||||
:param follow: Boolean: if to generate a 'follow' geometry
|
||||
:param plot: Boolean: if to plot the resulting geometry object
|
||||
:return: None
|
||||
:param plot: Boolean: if to plot the resulting geometry object
|
||||
:return: None
|
||||
"""
|
||||
|
||||
if geometry is None:
|
||||
|
@ -802,20 +476,20 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
work_geo = geometry
|
||||
|
||||
if dia is None:
|
||||
dia = float(self.options["isotooldia"])
|
||||
dia = float(self.app.defaults["tools_iso_tooldia"])
|
||||
|
||||
if passes is None:
|
||||
passes = int(self.options["isopasses"])
|
||||
passes = int(self.app.defaults["tools_iso_passes"])
|
||||
|
||||
if overlap is None:
|
||||
overlap = float(self.options["isooverlap"])
|
||||
overlap = float(self.app.defaults["tools_iso_overlap"])
|
||||
|
||||
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:
|
||||
milling_type = self.options["milling_type"]
|
||||
milling_type = self.app.defaults["tools_iso_milling_type"]
|
||||
|
||||
if iso_type is None:
|
||||
iso_t = 2
|
||||
|
@ -837,16 +511,16 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
|
||||
def iso_init(geo_obj, app_obj):
|
||||
# Propagate options
|
||||
geo_obj.options["cnctooldia"] = str(self.options["isotooldia"])
|
||||
geo_obj.tool_type = self.ui.tool_type_radio.get_value().upper()
|
||||
geo_obj.options["cnctooldia"] = str(dia)
|
||||
geo_obj.tool_type = self.app.defaults["tools_iso_tool_type"]
|
||||
|
||||
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
|
||||
if self.ui.tool_type_radio.get_value() == 'v':
|
||||
new_cutz = self.ui.cutz_spinner.get_value()
|
||||
new_vtipdia = self.ui.tipdia_spinner.get_value()
|
||||
new_vtipangle = self.ui.tipangle_spinner.get_value()
|
||||
if geo_obj.tool_type.lower() == 'v':
|
||||
new_cutz = self.app.defaults["tools_iso_tool_cutz"]
|
||||
new_vtipdia = self.app.defaults["tools_iso_tool_vtipdia"]
|
||||
new_vtipangle = self.app.defaults["tools_iso_tool_vtipangle"]
|
||||
tool_type = 'V'
|
||||
else:
|
||||
new_cutz = self.app.defaults['geometry_cutz']
|
||||
|
@ -885,7 +559,7 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
geo_obj.tools['1'] = {}
|
||||
geo_obj.tools.update({
|
||||
'1': {
|
||||
'tooldia': float(self.options["isotooldia"]),
|
||||
'tooldia': dia,
|
||||
'offset': 'Path',
|
||||
'offset_value': 0.0,
|
||||
'type': _('Rough'),
|
||||
|
@ -937,12 +611,11 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
# ############################################################
|
||||
# ########## AREA SUBTRACTION ################################
|
||||
# ############################################################
|
||||
if self.ui.except_cb.get_value():
|
||||
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
|
||||
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
|
||||
# if self.app.defaults["tools_iso_except"]:
|
||||
# self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
|
||||
# geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
|
||||
|
||||
# TODO: Do something if this is None. Offer changing name?
|
||||
self.app.new_object("geometry", iso_name, iso_init, plot=plot)
|
||||
self.app.app_obj.new_object("geometry", iso_name, iso_init, plot=plot)
|
||||
else:
|
||||
for i in range(passes):
|
||||
|
||||
|
@ -970,17 +643,13 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
|
||||
def iso_init(geo_obj, app_obj):
|
||||
# Propagate options
|
||||
geo_obj.options["cnctooldia"] = str(self.options["isotooldia"])
|
||||
if self.ui.tool_type_radio.get_value() == 'v':
|
||||
geo_obj.tool_type = 'V'
|
||||
else:
|
||||
geo_obj.tool_type = 'C1'
|
||||
geo_obj.options["cnctooldia"] = str(dia)
|
||||
geo_obj.tool_type = self.app.defaults["tools_iso_tool_type"]
|
||||
|
||||
# if milling type is climb then the move is counter-clockwise around features
|
||||
mill_dir = 1 if milling_type == 'cl' else 0
|
||||
geom = self.generate_envelope(offset, mill_dir, geometry=work_geo, env_iso_type=iso_t,
|
||||
follow=follow,
|
||||
nr_passes=i)
|
||||
follow=follow, nr_passes=i)
|
||||
|
||||
if geom == 'fail':
|
||||
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
|
||||
# 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
|
||||
if self.ui.tool_type_radio.get_value() == 'v':
|
||||
new_cutz = self.ui.cutz_spinner.get_value()
|
||||
new_vtipdia = self.ui.tipdia_spinner.get_value()
|
||||
new_vtipangle = self.ui.tipangle_spinner.get_value()
|
||||
if self.app.defaults["tools_iso_tool_type"].lower() == 'v':
|
||||
new_cutz = self.app.defaults["tools_iso_tool_cutz"]
|
||||
new_vtipdia = self.app.defaults["tools_iso_tool_vtipdia"]
|
||||
new_vtipangle = self.app.defaults["tools_iso_tool_vtipangle"]
|
||||
tool_type = 'V'
|
||||
else:
|
||||
new_cutz = self.app.defaults['geometry_cutz']
|
||||
|
@ -1033,7 +702,7 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
geo_obj.tools['1'] = {}
|
||||
geo_obj.tools.update({
|
||||
'1': {
|
||||
'tooldia': float(self.options["isotooldia"]),
|
||||
'tooldia': dia,
|
||||
'offset': 'Path',
|
||||
'offset_value': 0.0,
|
||||
'type': _('Rough'),
|
||||
|
@ -1067,12 +736,11 @@ class GerberObject(FlatCAMObj, Gerber):
|
|||
# ############################################################
|
||||
# ########## AREA SUBTRACTION ################################
|
||||
# ############################################################
|
||||
if self.ui.except_cb.get_value():
|
||||
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
|
||||
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
|
||||
# if self.app.defaults["tools_iso_except"]:
|
||||
# self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
|
||||
# geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
|
||||
|
||||
# TODO: Do something if this is None. Offer changing name?
|
||||
self.app.new_object("geometry", iso_name, iso_init, plot=plot)
|
||||
self.app.app_obj.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):
|
||||
# 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 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
|
||||
:param subtractor_geo: geometry that acts as subtractor
|
||||
:return:
|
||||
:return: None
|
||||
"""
|
||||
new_geometry = []
|
||||
target_geo = geo
|
||||
|
||||
if subtractor_geo:
|
||||
sub_union = cascaded_union(subtractor_geo)
|
||||
if outname is None:
|
||||
follow_name = self.options["name"] + "_follow"
|
||||
else:
|
||||
name = self.ui.obj_combo.currentText()
|
||||
subtractor_obj = self.app.collection.get_by_name(name)
|
||||
sub_union = cascaded_union(subtractor_obj.solid_geometry)
|
||||
follow_name = outname
|
||||
|
||||
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:
|
||||
for geo_elem in target_geo:
|
||||
if isinstance(geo_elem, Polygon):
|
||||
for ring in self.poly2rings(geo_elem):
|
||||
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
|
||||
self.app.app_obj.new_object("geometry", follow_name, follow_init)
|
||||
except Exception as e:
|
||||
return "Operation failed: %s" % str(e)
|
||||
|
||||
def on_plot_cb_click(self, *args):
|
||||
if self.muted_ui:
|
|
@ -12,15 +12,15 @@
|
|||
|
||||
import inspect # TODO: For debugging only.
|
||||
|
||||
from flatcamGUI.ObjectUI import *
|
||||
from AppGUI.ObjectUI import *
|
||||
|
||||
from FlatCAMCommon import LoudDict
|
||||
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||
from Common import LoudDict
|
||||
from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy
|
||||
|
||||
import sys
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -43,7 +43,7 @@ class ValidationError(Exception):
|
|||
class FlatCAMObj(QtCore.QObject):
|
||||
"""
|
||||
Base type of objects handled in FlatCAM. These become interactive
|
||||
in the GUI, can be plotted, and their options can be modified
|
||||
in the AppGUI, can be plotted, and their options can be modified
|
||||
by the user in their respective forms.
|
||||
"""
|
||||
|
||||
|
@ -139,7 +139,7 @@ class FlatCAMObj(QtCore.QObject):
|
|||
except KeyError:
|
||||
log.debug("FlatCAMObj.from_dict() --> KeyError: %s. "
|
||||
"Means that we are loading an old project that don't"
|
||||
"have all attributes in the latest FlatCAM." % str(attr))
|
||||
"have all attributes in the latest application version." % str(attr))
|
||||
pass
|
||||
|
||||
def on_options_change(self, key):
|
||||
|
@ -182,6 +182,11 @@ class FlatCAMObj(QtCore.QObject):
|
|||
except (TypeError, AttributeError):
|
||||
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)
|
||||
|
||||
def build_ui(self):
|
||||
|
@ -245,14 +250,14 @@ class FlatCAMObj(QtCore.QObject):
|
|||
self.app.proc_container.update_view_text('')
|
||||
with self.app.proc_container.new('%s...' % _("Plotting")):
|
||||
self.plot()
|
||||
self.app.object_changed.emit(self)
|
||||
self.app.app_obj.object_changed.emit(self)
|
||||
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
|
||||
|
||||
def on_scale_button_click(self):
|
||||
self.read_form()
|
||||
try:
|
||||
factor = float(eval(self.ui.scale_entry.get_value()))
|
||||
factor = float(self.ui.scale_entry.get_value())
|
||||
except Exception as e:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Scaling could not be executed."))
|
||||
log.debug("FlatCAMObj.on_scale_button_click() -- %s" % str(e))
|
||||
|
@ -276,7 +281,7 @@ class FlatCAMObj(QtCore.QObject):
|
|||
self.app.proc_container.update_view_text('')
|
||||
with self.app.proc_container.new('%s...' % _("Plotting")):
|
||||
self.plot()
|
||||
self.app.object_changed.emit(self)
|
||||
self.app.app_obj.object_changed.emit(self)
|
||||
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
|
||||
|
||||
|
@ -292,7 +297,7 @@ class FlatCAMObj(QtCore.QObject):
|
|||
self.app.proc_container.update_view_text('')
|
||||
with self.app.proc_container.new('%s...' % _("Plotting")):
|
||||
self.plot()
|
||||
self.app.object_changed.emit(self)
|
||||
self.app.app_obj.object_changed.emit(self)
|
||||
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
|
||||
|
||||
|
@ -372,7 +377,7 @@ class FlatCAMObj(QtCore.QObject):
|
|||
def plot_task():
|
||||
with self.app.proc_container.new('%s...' % _("Plotting")):
|
||||
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': []})
|
||||
|
||||
|
@ -459,8 +464,16 @@ class FlatCAMObj(QtCore.QObject):
|
|||
def visible(self, value, threaded=True):
|
||||
log.debug("FlatCAMObj.visible()")
|
||||
|
||||
def worker_task(app_obj):
|
||||
self.shapes.visible = value
|
||||
current_visibility = self.shapes.visible
|
||||
# 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:
|
||||
# Not all object types has annotations
|
||||
|
@ -469,10 +482,10 @@ class FlatCAMObj(QtCore.QObject):
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
if threaded is False:
|
||||
worker_task(app_obj=self.app)
|
||||
if threaded:
|
||||
self.app.worker_task.emit({'fcn': task, 'params': [current_visibility]})
|
||||
else:
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': [self]})
|
||||
task(current_visibility)
|
||||
|
||||
@property
|
||||
def drawing_tolerance(self):
|
|
@ -10,16 +10,16 @@
|
|||
# File modified by: Marius Stanciu #
|
||||
# ##########################################################
|
||||
|
||||
from flatcamEditors.FlatCAMTextEditor import TextEditor
|
||||
from flatcamObjects.FlatCAMObj import *
|
||||
from flatcamGUI.ObjectUI import *
|
||||
from AppEditors.FlatCAMTextEditor import TextEditor
|
||||
from AppObjects.FlatCAMObj import *
|
||||
from AppGUI.ObjectUI import *
|
||||
|
||||
import tkinter as tk
|
||||
import sys
|
||||
from copy import deepcopy
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -183,7 +183,13 @@ class ScriptObject(FlatCAMObj):
|
|||
if self.app.ui.shell_dock.isHidden():
|
||||
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 = ''
|
||||
for tcl_command_line in self.script_code.splitlines():
|
||||
|
@ -202,8 +208,6 @@ class ScriptObject(FlatCAMObj):
|
|||
|
||||
# execute the actual Tcl command
|
||||
try:
|
||||
self.app.shell.open_processing() # Disables input box.
|
||||
|
||||
result = self.app.shell.tcl.eval(str(new_command))
|
||||
if result != 'None':
|
||||
self.app.shell.append_output(result + '\n')
|
||||
|
@ -220,6 +224,7 @@ class ScriptObject(FlatCAMObj):
|
|||
log.error("Exec command Exception: %s\n" % result)
|
||||
self.app.shell.append_error('ERROR: %s\n '% result)
|
||||
|
||||
self.app.ui.fcinfo.lock_pmaps = False
|
||||
self.app.shell.close_processing()
|
||||
|
||||
def on_autocomplete_changed(self, state):
|
||||
|
@ -228,6 +233,27 @@ class ScriptObject(FlatCAMObj):
|
|||
else:
|
||||
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):
|
||||
"""
|
||||
Returns a representation of the object as a dictionary.
|
|
@ -16,13 +16,13 @@ from PyQt5.QtCore import Qt, QSettings
|
|||
from PyQt5.QtGui import QColor
|
||||
# from PyQt5.QtCore import QModelIndex
|
||||
|
||||
from flatcamObjects.FlatCAMObj import FlatCAMObj
|
||||
from flatcamObjects.FlatCAMCNCJob import CNCJobObject
|
||||
from flatcamObjects.FlatCAMDocument import DocumentObject
|
||||
from flatcamObjects.FlatCAMExcellon import ExcellonObject
|
||||
from flatcamObjects.FlatCAMGeometry import GeometryObject
|
||||
from flatcamObjects.FlatCAMGerber import GerberObject
|
||||
from flatcamObjects.FlatCAMScript import ScriptObject
|
||||
from AppObjects.FlatCAMObj import FlatCAMObj
|
||||
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 inspect # TODO: Remove
|
||||
|
||||
|
@ -32,7 +32,7 @@ from copy import deepcopy
|
|||
from numpy import Inf
|
||||
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
|
@ -50,12 +50,13 @@ class KeySensitiveListView(QtWidgets.QTreeView):
|
|||
def __init__(self, app, parent=None):
|
||||
super(KeySensitiveListView, self).__init__(parent)
|
||||
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.setExpandsOnDoubleClick(False)
|
||||
|
||||
# Enable dragging and dropping onto the GUI
|
||||
# Enable dragging and dropping onto the AppGUI
|
||||
self.setAcceptDrops(True)
|
||||
self.filename = ""
|
||||
self.app = app
|
||||
|
@ -334,6 +335,8 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
self.click_modifier = None
|
||||
|
||||
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):
|
||||
log.debug("Object %s has been promised." % obj_name)
|
||||
|
@ -382,8 +385,9 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
|
||||
if type(obj) != GeometryObject:
|
||||
self.app.ui.menuprojectgeneratecnc.setVisible(False)
|
||||
if type(obj) != GeometryObject and type(obj) != ExcellonObject and type(obj) != GerberObject:
|
||||
self.app.ui.menuprojectedit.setVisible(False)
|
||||
# if type(obj) != GeometryObject and type(obj) != ExcellonObject and type(obj) != GerberObject or \
|
||||
# type(obj) != CNCJobObject:
|
||||
# self.app.ui.menuprojectedit.setVisible(False)
|
||||
if type(obj) != GerberObject and type(obj) != ExcellonObject and type(obj) != CNCJobObject:
|
||||
self.app.ui.menuprojectviewsource.setVisible(False)
|
||||
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():
|
||||
# ## Create a new name
|
||||
# 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)
|
||||
if match: # Yes: Increment the number!
|
||||
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.
|
||||
|
||||
:return: List of names.
|
||||
:rtype: list
|
||||
:return: List of names.
|
||||
:rtype: list
|
||||
"""
|
||||
|
||||
# log.debug(str(inspect.stack()[1][3]) + " --> OC.get_names()")
|
||||
|
@ -985,7 +989,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
|
||||
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:
|
||||
"""
|
||||
|
@ -998,3 +1002,199 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
|
||||
def update_view(self):
|
||||
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)
|
|
@ -12,8 +12,8 @@ import logging
|
|||
|
||||
log = logging.getLogger('base2')
|
||||
|
||||
from flatcamParsers.ParseFont import *
|
||||
from flatcamParsers.ParseDXF_Spline import *
|
||||
from AppParsers.ParseFont import *
|
||||
from AppParsers.ParseDXF_Spline import *
|
||||
|
||||
|
||||
def distance(pt1, pt2):
|
|
@ -6,7 +6,7 @@
|
|||
# MIT Licence #
|
||||
# ########################################################## ##
|
||||
|
||||
from camlib import Geometry
|
||||
from camlib import Geometry, grace
|
||||
|
||||
import shapely.affinity as affinity
|
||||
from shapely.geometry import Point, LineString
|
||||
|
@ -17,8 +17,7 @@ import logging
|
|||
import traceback
|
||||
from copy import deepcopy
|
||||
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
from FlatCAMCommon import GracefulException as grace
|
||||
# import AppTranslation as fcTranslate
|
||||
|
||||
import gettext
|
||||
import builtins
|
||||
|
@ -967,7 +966,7 @@ class Excellon(Geometry):
|
|||
:return: None
|
||||
"""
|
||||
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.create_geometry()")
|
||||
log.debug("AppParsers.ParseExcellon.Excellon.create_geometry()")
|
||||
self.solid_geometry = []
|
||||
try:
|
||||
# clear the solid_geometry in self.tools
|
||||
|
@ -982,7 +981,7 @@ class Excellon(Geometry):
|
|||
_("Excellon.create_geometry() -> a drill location was skipped "
|
||||
"due of not having a tool associated.\n"
|
||||
"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")
|
||||
continue
|
||||
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]['data'] = deepcopy(self.default_data)
|
||||
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))
|
||||
return "fail"
|
||||
|
||||
|
@ -1018,10 +1017,10 @@ class Excellon(Geometry):
|
|||
: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:
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon -> solid_geometry is None")
|
||||
log.debug("AppParsers.ParseExcellon.Excellon -> solid_geometry is None")
|
||||
return 0, 0, 0, 0
|
||||
|
||||
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
|
||||
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
|
||||
inside the file to the FlatCAM units.
|
||||
|
||||
|
@ -1092,7 +1091,7 @@ class Excellon(Geometry):
|
|||
else:
|
||||
log.error("Unsupported units: %s" % str(obj_units))
|
||||
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.scale(factor, factor)
|
||||
|
@ -1118,7 +1117,7 @@ class Excellon(Geometry):
|
|||
:return: None
|
||||
:rtype: None
|
||||
"""
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.scale()")
|
||||
log.debug("AppParsers.ParseExcellon.Excellon.scale()")
|
||||
|
||||
if yfactor is None:
|
||||
yfactor = xfactor
|
||||
|
@ -1183,7 +1182,7 @@ class Excellon(Geometry):
|
|||
:type vect: tuple
|
||||
:return: None
|
||||
"""
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.offset()")
|
||||
log.debug("AppParsers.ParseExcellon.Excellon.offset()")
|
||||
|
||||
dx, dy = vect
|
||||
|
||||
|
@ -1243,7 +1242,7 @@ class Excellon(Geometry):
|
|||
:type point: list
|
||||
:return: None
|
||||
"""
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.mirror()")
|
||||
log.debug("AppParsers.ParseExcellon.Excellon.mirror()")
|
||||
|
||||
px, py = point
|
||||
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:
|
||||
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:
|
||||
angle_x = 0.0
|
||||
|
@ -1396,7 +1395,7 @@ class Excellon(Geometry):
|
|||
:param point: tuple of coordinates (x, y)
|
||||
:return: None
|
||||
"""
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.rotate()")
|
||||
log.debug("AppParsers.ParseExcellon.Excellon.rotate()")
|
||||
|
||||
if angle == 0:
|
||||
return
|
||||
|
@ -1479,7 +1478,7 @@ class Excellon(Geometry):
|
|||
:param join: The type of line joint used by the shapely buffer method: round, square, bevel
|
||||
:return: None
|
||||
"""
|
||||
log.debug("flatcamParsers.ParseExcellon.Excellon.buffer()")
|
||||
log.debug("AppParsers.ParseExcellon.Excellon.buffer()")
|
||||
|
||||
if distance == 0:
|
||||
return
|
|
@ -22,7 +22,7 @@ from fontTools import ttLib
|
|||
|
||||
import logging
|
||||
import gettext
|
||||
import FlatCAMTranslation as fcTranslate
|
||||
import AppTranslation as fcTranslate
|
||||
import builtins
|
||||
|
||||
fcTranslate.apply_language('strings')
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue