- fixed issues in the Tools Database due of recent changes in how the data structure is created

- made sure that the right tools go only to the intended use, in Tools Database otherwise an error status message is created and Tools DB is closed on adding a wrong tool
- fixed the usage for Tools Database in Unix-like OS's
- done some modest refactoring
- fixed the Search and Add feature in Geometry Object UI
This commit is contained in:
Marius Stanciu 2020-10-29 22:32:44 +02:00 committed by Marius
parent 46d2304b67
commit 38abfa4f31
12 changed files with 327 additions and 135 deletions

View File

@ -18,6 +18,11 @@ CHANGELOG for FlatCAM beta
- fixed the sizePolicy for the FCComboBox widgets in the Preferences that holds the preprocessors
- fixed issue with how the preamble / postamble GCode were inserted into the final GCode
- fixed a small issue in GCode Editor where the signals for the buttons were attached again at each launch of the GCode Editor
- fixed issues in the Tools Database due of recent changes in how the data structure is created
- made sure that the right tools go only to the intended use, in Tools Database otherwise an error status message is created and Tools DB is closed on adding a wrong tool
- fixed the usage for Tools Database in Unix-like OS's
- done some modest refactoring
- fixed the Search and Add feature in Geometry Object UI
28.10.2020

View File

@ -1,6 +1,6 @@
from PyQt5 import QtGui, QtCore, QtWidgets
from appGUI.GUIElements import FCEntry, FCButton, FCDoubleSpinner, FCComboBox, FCCheckBox, FCSpinner, \
FCTree, RadioSet, FCFileSaveDialog, FCLabel
FCTree, RadioSet, FCFileSaveDialog, FCLabel, FCComboBox2
from camlib import to_dict
import sys
@ -25,6 +25,10 @@ class ToolsDB2UI:
self.app = app
self.decimals = self.app.decimals
self.offset_item_options = ["Path", "In", "Out", "Custom"]
self.type_item_options = [_("Iso"), _("Rough"), _("Finish")]
self.tool_type_item_options = ["C1", "C2", "C3", "C4", "B", "V"]
settings = QtCore.QSettings("Open Source", "FlatCAM")
if settings.contains("machinist"):
self.machinist_setting = settings.value('machinist', type=int)
@ -269,7 +273,7 @@ class ToolsDB2UI:
self.tool_op_label.setToolTip(
_("The kind of Application Tool where this tool is to be used."))
self.tool_op_combo = FCComboBox()
self.tool_op_combo = FCComboBox2()
self.tool_op_combo.addItems(
[_("General"), _("Milling"), _("Drilling"), _('Isolation'), _('Paint'), _('NCC'), _('Cutout')])
self.tool_op_combo.setObjectName('gdb_tool_target')
@ -296,7 +300,7 @@ class ToolsDB2UI:
"V = v-shape milling tool"))
self.mill_shape_combo = FCComboBox()
self.mill_shape_combo.addItems(["C1", "C2", "C3", "C4", "B", "V"])
self.mill_shape_combo.addItems(self.tool_type_item_options)
self.mill_shape_combo.setObjectName('gdb_shape')
self.grid0.addWidget(self.shape_label, 2, 0)
@ -345,7 +349,7 @@ class ToolsDB2UI:
"Finish = finishing cut, high feedrate"))
self.mill_type_combo = FCComboBox()
self.mill_type_combo.addItems(["Iso", "Rough", "Finish"])
self.mill_type_combo.addItems(self.type_item_options)
self.mill_type_combo.setObjectName('gdb_type')
self.grid0.addWidget(self.type_label, 10, 0)
@ -362,7 +366,7 @@ class ToolsDB2UI:
"Custom = custom offset using the Custom Offset value"))
self.mill_tooloffset_combo = FCComboBox()
self.mill_tooloffset_combo.addItems(["Path", "In", "Out", "Custom"])
self.mill_tooloffset_combo.addItems(self.offset_item_options)
self.mill_tooloffset_combo.setObjectName('gdb_tool_offset')
self.grid0.addWidget(self.tooloffset_label, 12, 0)
@ -663,7 +667,7 @@ class ToolsDB2UI:
"- Line-based: Parallel lines.")
)
self.ncc_method_combo = FCComboBox()
self.ncc_method_combo = FCComboBox2()
self.ncc_method_combo.addItems(
[_("Standard"), _("Seed"), _("Lines"), _("Combo")]
)
@ -778,7 +782,7 @@ class ToolsDB2UI:
"in the order specified.")
)
self.paint_method_combo = FCComboBox()
self.paint_method_combo = FCComboBox2()
self.paint_method_combo.addItems(
[_("Standard"), _("Seed"), _("Lines"), _("Laser_lines"), _("Combo")]
)
@ -876,8 +880,8 @@ class ToolsDB2UI:
self.iso_follow_cb = FCCheckBox()
self.iso_follow_cb.setToolTip(_("Generate a 'Follow' geometry.\n"
"This means that it will cut through\n"
"the middle of the trace."))
"This means that it will cut through\n"
"the middle of the trace."))
self.iso_follow_cb.setObjectName("gdb_i_follow")
self.grid4.addWidget(self.follow_label, 6, 0)
@ -1402,9 +1406,7 @@ class ToolsDB2(QtWidgets.QWidget):
self.on_tool_request = callback_on_tool_request
self.offset_item_options = ["Path", "In", "Out", "Custom"]
self.type_item_options = ["Iso", "Rough", "Finish"]
self.tool_type_item_options = ["C1", "C2", "C3", "C4", "B", "V"]
self.tools_db_changed_flag = False
'''
dict to hold all the tools in the Tools DB
@ -1717,7 +1719,7 @@ class ToolsDB2(QtWidgets.QWidget):
self.ui_connect()
def setup_db_ui(self):
filename = self.app.data_path + '\\tools_db.FlatDB'
filename = self.app.tools_database_path()
# load the database tools from the file
try:
@ -1809,7 +1811,7 @@ class ToolsDB2(QtWidgets.QWidget):
self.ui.tool_description_box.setEnabled(True)
if self.db_tool_dict:
if tool_target == _("General"):
if tool_target == 0: # _("General")
self.ui.milling_box.setEnabled(True)
self.ui.ncc_box.setEnabled(True)
self.ui.paint_box.setEnabled(True)
@ -1831,33 +1833,33 @@ class ToolsDB2(QtWidgets.QWidget):
self.ui.drill_box.hide()
self.ui.cutout_box.hide()
if tool_target == _("Milling"):
if tool_target == 1: # _("Milling")
self.ui.milling_box.setEnabled(True)
self.ui.milling_box.show()
if tool_target == _("Drilling"):
if tool_target == 2: # _("Drilling")
self.ui.drill_box.setEnabled(True)
self.ui.drill_box.show()
if tool_target == _("Isolation"):
if tool_target == 3: # _("Isolation")
self.ui.iso_box.setEnabled(True)
self.ui.iso_box.show()
self.ui.milling_box.setEnabled(True)
self.ui.milling_box.show()
if tool_target == _("Paint"):
if tool_target == 4: # _("Paint")
self.ui.paint_box.setEnabled(True)
self.ui.paint_box.show()
self.ui.milling_box.setEnabled(True)
self.ui.milling_box.show()
if tool_target == _("NCC"):
if tool_target == 5: # _("NCC")
self.ui.ncc_box.setEnabled(True)
self.ui.ncc_box.show()
self.ui.milling_box.setEnabled(True)
self.ui.milling_box.show()
if tool_target == _("Cutout"):
if tool_target == 6: # _("Cutout")
self.ui.cutout_box.setEnabled(True)
self.ui.cutout_box.show()
self.ui.milling_box.setEnabled(True)
@ -1872,7 +1874,7 @@ class ToolsDB2(QtWidgets.QWidget):
default_data = {}
default_data.update({
"plot": True,
"tool_target": _("General"),
"tool_target": 0, # _("General")
"tol_min": 0.0,
"tol_max": 0.0,
@ -2148,7 +2150,7 @@ class ToolsDB2(QtWidgets.QWidget):
def on_save_tools_db(self, silent=False):
self.app.log.debug("ToolsDB.on_save_button() --> Saving Tools Database to file.")
filename = self.app.data_path + "/tools_db.FlatDB"
filename = self.app.tools_database_path()
# Preferences save, update the color of the Tools DB Tab text
for idx in range(self.app_ui.plot_tab_area.count()):
@ -2884,7 +2886,7 @@ class ToolsDB2(QtWidgets.QWidget):
# "A position on Z plane to move immediately after job stop."))
#
# def setup_db_ui(self):
# filename = self.app.data_path + '/tools_db.FlatDB'
# filename = self.app.tools_database_path()
#
# # load the database tools from the file
# try:
@ -3321,7 +3323,7 @@ class ToolsDB2(QtWidgets.QWidget):
# def on_save_tools_db(self, silent=False):
# self.app.log.debug("ToolsDB.on_save_button() --> Saving Tools Database to file.")
#
# filename = self.app.data_path + "/tools_db.FlatDB"
# filename = self.app.tools_database_path()
#
# # Preferences save, update the color of the Tools DB Tab text
# for idx in range(self.app_ui.plot_tab_area.count()):

View File

@ -1885,6 +1885,17 @@ class MainGUI(QtWidgets.QMainWindow):
self.infobar.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self.build_infobar_context_menu()
def set_ui_title(self, name):
"""
Sets the title of the main window.
:param name: String that store the project path and project name
:return: None
"""
title = 'FlatCAM %s %s - %s - [%s] %s' % (
self.app.version, ('BETA' if self.app.beta else ''), platform.architecture()[0], self.app.engine, name)
self.setWindowTitle(title)
def save_geometry(self, x, y, width, height, notebook_width):
"""
Will save the application geometry and positions in the defaults dicitionary to be restored at the next
@ -2089,6 +2100,7 @@ class MainGUI(QtWidgets.QMainWindow):
resource_loc = self.app.resource_location
response = None
bt_yes = None
if forced_clear is False:
msgbox = QtWidgets.QMessageBox()
msgbox.setText(_("Are you sure you want to delete the GUI Settings? \n"))
@ -4449,32 +4461,32 @@ class ShortcutsTab(QtWidgets.QWidget):
# ALT section
_('Alt+A'), _("Align Objects Tool"),
_('Alt+C'),_("Calculators Tool"),
_('Alt+D'),_("2-Sided PCB Tool"),
_('Alt+E'),_("Extract Drills Tool"),
_('Alt+F'),_("Fiducials Tool"),
_('Alt+G'),_("Invert Gerber Tool"),
_('Alt+H'),_("Punch Gerber Tool"),
_('Alt+I'),_("Isolation Tool"),
_('Alt+J'),_("Copper Thieving Tool"),
_('Alt+K'),_("Solder Paste Dispensing Tool"),
_('Alt+L'),_("Film PCB Tool"),
_('Alt+M'),_("Corner Markers Tool"),
_('Alt+N'),_("Non-Copper Clearing Tool"),
_('Alt+O'),_("Optimal Tool"),
_('Alt+P'),_("Paint Area Tool"),
_('Alt+Q'),_("QRCode Tool"),
_('Alt+R'),_("Rules Check Tool"),
_('Alt+S'),_("View File Source"),
_('Alt+T'),_("Transformations Tool"),
_('Alt+W'),_("Subtract Tool"),
_('Alt+X'),_("Cutout PCB Tool"),
_('Alt+Z'),_("Panelize PCB"),
_('Alt+1'),_("Enable all"),
_('Alt+2'),_("Disable all"),
_('Alt+3'),_("Enable Non-selected Objects"),
_('Alt+4'),_("Disable Non-selected Objects"),
_('Alt+F10'),_("Toggle Full Screen"),
_('Alt+C'), _("Calculators Tool"),
_('Alt+D'), _("2-Sided PCB Tool"),
_('Alt+E'), _("Extract Drills Tool"),
_('Alt+F'), _("Fiducials Tool"),
_('Alt+G'), _("Invert Gerber Tool"),
_('Alt+H'), _("Punch Gerber Tool"),
_('Alt+I'), _("Isolation Tool"),
_('Alt+J'), _("Copper Thieving Tool"),
_('Alt+K'), _("Solder Paste Dispensing Tool"),
_('Alt+L'), _("Film PCB Tool"),
_('Alt+M'), _("Corner Markers Tool"),
_('Alt+N'), _("Non-Copper Clearing Tool"),
_('Alt+O'), _("Optimal Tool"),
_('Alt+P'), _("Paint Area Tool"),
_('Alt+Q'), _("QRCode Tool"),
_('Alt+R'), _("Rules Check Tool"),
_('Alt+S'), _("View File Source"),
_('Alt+T'), _("Transformations Tool"),
_('Alt+W'), _("Subtract Tool"),
_('Alt+X'), _("Cutout PCB Tool"),
_('Alt+Z'), _("Panelize PCB"),
_('Alt+1'), _("Enable all"),
_('Alt+2'), _("Disable all"),
_('Alt+3'), _("Enable Non-selected Objects"),
_('Alt+4'), _("Disable Non-selected Objects"),
_('Alt+F10'), _("Toggle Full Screen"),
# CTRL + ALT section
_('Ctrl+Alt+X'), _("Abort current task (gracefully)"),

View File

@ -1093,9 +1093,9 @@ class GeometryObjectUI(ObjectUI):
bhlay = QtWidgets.QHBoxLayout()
self.addtool_btn = QtWidgets.QPushButton(_('Search and Add'))
self.addtool_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/plus16.png'))
self.addtool_btn.setToolTip(
self.search_and_add_btn = QtWidgets.QPushButton(_('Search and Add'))
self.search_and_add_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/plus16.png'))
self.search_and_add_btn.setToolTip(
_("Add a new tool to the Tool Table\n"
"with the diameter specified above.")
)
@ -1109,7 +1109,7 @@ class GeometryObjectUI(ObjectUI):
"Menu: Options -> Tools Database")
)
bhlay.addWidget(self.addtool_btn)
bhlay.addWidget(self.search_and_add_btn)
bhlay.addWidget(self.addtool_from_db_btn)
grid1.addLayout(bhlay, 5, 0, 1, 2)

View File

@ -25,6 +25,8 @@ import traceback
from collections import defaultdict
from functools import reduce
import simplejson as json
import gettext
import appTranslation as fcTranslate
import builtins
@ -585,7 +587,7 @@ class GeometryObject(FlatCAMObj, Geometry):
# self.ui.geo_tools_table.setColumnHidden(4, True)
self.ui.addtool_entry_lbl.hide()
self.ui.addtool_entry.hide()
self.ui.addtool_btn.hide()
self.ui.search_and_add_btn.hide()
self.ui.deltool_btn.hide()
# self.ui.endz_label.hide()
# self.ui.endz_entry.hide()
@ -745,10 +747,9 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui.geo_tools_table.cellWidget(row, col).currentIndexChanged.connect(
self.on_tooltable_cellwidget_change)
# I use lambda's because the connected functions have parameters that could be used in certain scenarios
self.ui.addtool_btn.clicked.connect(lambda: self.on_tool_add())
self.ui.search_and_add_btn.clicked.connect(self.on_tool_add)
self.ui.deltool_btn.clicked.connect(lambda: self.on_tool_delete())
self.ui.deltool_btn.clicked.connect(self.on_tool_delete)
self.ui.geo_tools_table.clicked.connect(self.on_row_selection_change)
self.ui.geo_tools_table.horizontalHeader().sectionClicked.connect(self.on_toggle_all_rows)
@ -808,7 +809,7 @@ class GeometryObject(FlatCAMObj, Geometry):
pass
try:
self.ui.addtool_btn.clicked.disconnect()
self.ui.search_and_add_btn.clicked.disconnect()
except (TypeError, AttributeError):
pass
@ -1015,18 +1016,150 @@ class GeometryObject(FlatCAMObj, Geometry):
self.ui_connect()
def on_tool_add(self, dia=None, new_geo=None):
log.debug("GeometryObject.on_add_tool()")
self.ui_disconnect()
self.units = self.app.defaults['units'].upper()
filename = self.app.tools_database_path()
tooldia = dia if dia is not None else float(self.ui.addtool_entry.get_value())
tool_dia = dia if dia is not None else self.ui.addtool_entry.get_value()
# construct a list of all 'tooluid' in the self.iso_tools
tool_uid_list = [int(tooluid_key) for tooluid_key in self.tools]
# find maximum from the temp_uid, add 1 and this is the new 'tooluid'
max_uid = 0 if not tool_uid_list else max(tool_uid_list)
tooluid = int(max_uid) + 1
new_tools_dict = deepcopy(self.default_data)
updated_tooldia = None
# determine the new tool diameter
if tool_dia is None or tool_dia == 0:
self.build_ui()
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Please enter a tool diameter with non-zero value, "
"in Float format."))
self.ui_connect()
return
truncated_tooldia = self.app.dec_format(tool_dia, self.decimals)
# load the database tools from the file
try:
with open(filename) as f:
tools = f.read()
except IOError:
self.app.log.error("Could not load tools DB file.")
self.app.inform.emit('[ERROR] %s' % _("Could not load Tools DB file."))
self.ui_connect()
self.on_tool_default_add(dia=tool_dia)
return
try:
# store here the tools from Tools Database when searching in Tools Database
tools_db_dict = json.loads(tools)
except Exception:
e = sys.exc_info()[0]
self.app.log.error(str(e))
self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
self.ui_connect()
self.on_tool_default_add(dia=tool_dia)
return
tool_found = 0
offset = 'Path'
offset_val = 0.0
typ = _("Rough")
tool_type = 'C1'
# look in database tools
for db_tool, db_tool_val in tools_db_dict.items():
offset = db_tool_val['offset']
offset_val = db_tool_val['offset_value']
typ = db_tool_val['type']
tool_type = db_tool_val['tool_type']
db_tooldia = db_tool_val['tooldia']
low_limit = float(db_tool_val['data']['tol_min'])
high_limit = float(db_tool_val['data']['tol_max'])
# we need only tool marked for Milling Tool (Geometry Object)
if db_tool_val['data']['tool_target'] != 1: # _('Milling')
continue
# if we find a tool with the same diameter in the Tools DB just update it's data
if truncated_tooldia == db_tooldia:
tool_found += 1
for d in db_tool_val['data']:
if d.find('tools_mill_') == 0:
new_tools_dict[d] = db_tool_val['data'][d]
elif d.find('tools_') == 0:
# don't need data for other App Tools; this tests after 'tools_mill_'
continue
else:
new_tools_dict[d] = db_tool_val['data'][d]
# search for a tool that has a tolerance that the tool fits in
elif high_limit >= truncated_tooldia >= low_limit:
tool_found += 1
updated_tooldia = db_tooldia
for d in db_tool_val['data']:
if d.find('tools_iso') == 0:
new_tools_dict[d] = db_tool_val['data'][d]
elif d.find('tools_') == 0:
# don't need data for other App Tools; this tests after 'tools_drill_'
continue
else:
new_tools_dict[d] = db_tool_val['data'][d]
# test we found a suitable tool in Tools Database or if multiple ones
if tool_found == 0:
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Tool not in Tools Database. Adding a default tool."))
self.on_tool_default_add(dia=tool_dia, new_geo=new_geo)
self.ui_connect()
return
if tool_found > 1:
self.app.inform.emit(
'[WARNING_NOTCL] %s' % _("Cancelled.\n"
"Multiple tools for one tool diameter found in Tools Database."))
self.ui_connect()
return
new_tdia = deepcopy(updated_tooldia) if updated_tooldia is not None else deepcopy(truncated_tooldia)
self.tools.update({
tooluid: {
'tooldia': new_tdia,
'offset': deepcopy(offset),
'offset_value': deepcopy(offset_val),
'type': deepcopy(typ),
'tool_type': deepcopy(tool_type),
'data': deepcopy(new_tools_dict),
'solid_geometry': self.solid_geometry
}
})
self.ui_connect()
self.build_ui()
# select the tool just added
for row in range(self.ui.geo_tools_table.rowCount()):
if int(self.ui.geo_tools_table.item(row, 5).text()) == tooluid:
self.ui.geo_tools_table.selectRow(row)
break
# update the UI form
self.update_ui()
self.app.inform.emit('[success] %s' % _("New tool added to Tool Table from Tools Database."))
def on_tool_default_add(self, dia=None, new_geo=None, muted=None):
self.ui_disconnect()
tooldia = dia if dia is not None else self.ui.addtool_entry.get_value()
tool_uid_list = [int(tooluid_key) for tooluid_key in self.tools]
# find maximum from the temp_uid, add 1 and this is the new 'tooluid'
max_uid = max(tool_uid_list) if tool_uid_list else 0
self.tooluid = max_uid + 1
self.tooluid = int(max_uid) + 1
tooldia = float('%.*f' % (self.decimals, tooldia))
tooldia = self.app.dec_format(tooldia, self.decimals)
# here we actually add the new tool; if there is no tool in the tool table we add a tool with default data
# otherwise we add a tool with data copied from last tool
@ -1080,7 +1213,8 @@ class GeometryObject(FlatCAMObj, Geometry):
pass
self.ser_attrs.append('tools')
self.app.inform.emit('[success] %s' % _("Tool added in Tool Table."))
if muted is None:
self.app.inform.emit('[success] %s' % _("Tool added in Tool Table."))
self.ui_connect()
self.build_ui()
@ -2782,7 +2916,7 @@ class GeometryObject(FlatCAMObj, Geometry):
tooldia = float('%.*f' % (self.decimals, tooldia))
self.ui.addtool_entry.set_value(tooldia)
self.ui.addtool_entry.returnPressed.connect(self.on_tool_add)
self.ui.addtool_entry.returnPressed.connect(self.on_tool_default_add)
return factor

View File

@ -266,7 +266,7 @@ class CutOut(AppTool):
def on_tool_add(self, custom_dia=None):
self.blockSignals(True)
filename = self.app.data_path + '\\tools_db.FlatDB'
filename = self.app.tools_database_path()
new_tools_dict = deepcopy(self.default_data)
updated_tooldia = None
@ -311,7 +311,7 @@ class CutOut(AppTool):
offset = 'Path'
offset_val = 0.0
typ = "Rough"
typ = _("Rough")
tool_type = 'V'
# look in database tools
for db_tool, db_tool_val in tools_db_dict.items():
@ -462,7 +462,12 @@ class CutOut(AppTool):
:return:
"""
if tool['data']['tool_target'] != _("Cutout"):
if tool['data']['tool_target'] not in [0, 6]: # [General, Cutout Tool]
for idx in range(self.app.ui.plot_tab_area.count()):
if self.app.ui.plot_tab_area.tabText(idx) == _("Tools Database"):
wdg = self.app.ui.plot_tab_area.widget(idx)
wdg.deleteLater()
self.app.ui.plot_tab_area.removeTab(idx)
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Selected tool can't be used here. Pick another."))
return
tool_from_db = deepcopy(self.default_data)

View File

@ -884,7 +884,7 @@ class ToolDrilling(AppTool, Excellon):
def on_tool_db_load(self):
filename = self.app.data_path + '\\tools_db.FlatDB'
filename = self.app.tools_database_path()
# load the database tools from the file
try:
@ -1213,7 +1213,7 @@ class ToolDrilling(AppTool, Excellon):
# if the sender is in the column with index 2 then we update the tool_type key
if cw_col == 2:
tt = cw.currentText()
typ = 'Iso' if tt == 'V' else "Rough"
typ = 'Iso' if tt == 'V' else _("Rough")
self.excellon_tools[current_uid].update({
'type': typ,

View File

@ -208,7 +208,7 @@ class ToolIsolation(AppTool, Gerber):
self.ui.apply_param_to_all.clicked.connect(self.on_apply_param_to_all_clicked)
# adding Tools
self.ui.add_newtool_button.clicked.connect(lambda: self.on_tool_add())
self.ui.search_and_add_btn.clicked.connect(lambda: self.on_tool_add())
self.ui.addtool_from_db_btn.clicked.connect(self.on_tool_add_from_db_clicked)
self.ui.generate_iso_button.clicked.connect(self.on_iso_button_click)
@ -899,7 +899,7 @@ class ToolIsolation(AppTool, Gerber):
# if the sender is in the column with index 2 then we update the tool_type key
if cw_col == 2:
tt = cw.currentText()
typ = 'Iso' if tt == 'V' else "Rough"
typ = 'Iso' if tt == 'V' else _("Rough")
self.iso_tools[currenuid].update({
'type': typ,
@ -1034,29 +1034,26 @@ class ToolIsolation(AppTool, Gerber):
def on_tool_add(self, custom_dia=None):
self.blockSignals(True)
filename = self.app.data_path + '\\tools_db.FlatDB'
new_tools_dict = deepcopy(self.default_data)
updated_tooldia = None
filename = self.app.tools_database_path()
tool_dia = custom_dia if custom_dia is not None else self.ui.new_tooldia_entry.get_value()
# construct a list of all 'tooluid' in the self.iso_tools
tool_uid_list = [int(tooluid_key) for tooluid_key in self.iso_tools]
# find maximum from the temp_uid, add 1 and this is the new 'tooluid'
max_uid = 0 if not tool_uid_list else max(tool_uid_list)
tooluid = int(max_uid + 1)
tooluid = int(max_uid) + 1
new_tools_dict = deepcopy(self.default_data)
updated_tooldia = None
tool_dias = []
for k, v in self.iso_tools.items():
for tool_v in v.keys():
if tool_v == 'tooldia':
tool_dias.append(self.app.dec_format(v[tool_v], self.decimals))
tool_dias.append(self.app.dec_format(v['tooldia'], self.decimals))
# determine the new tool diameter
if custom_dia is None:
tool_dia = self.ui.new_tooldia_entry.get_value()
else:
tool_dia = custom_dia
if tool_dia is None or tool_dia == 0:
self.build_ui()
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Please enter a tool diameter with non-zero value, "
@ -1097,7 +1094,7 @@ class ToolIsolation(AppTool, Gerber):
offset = 'Path'
offset_val = 0.0
typ = "Rough"
typ = _("Rough")
tool_type = 'V'
# look in database tools
for db_tool, db_tool_val in tools_db_dict.items():
@ -1111,7 +1108,7 @@ class ToolIsolation(AppTool, Gerber):
high_limit = float(db_tool_val['data']['tol_max'])
# we need only tool marked for Isolation Tool
if db_tool_val['data']['tool_target'] != _('Isolation'):
if db_tool_val['data']['tool_target'] != 3: # _('Isolation')
continue
# if we find a tool with the same diameter in the Tools DB just update it's data
@ -1186,12 +1183,8 @@ class ToolIsolation(AppTool, Gerber):
def on_tool_default_add(self, dia=None, muted=None):
self.blockSignals(True)
self.units = self.app.defaults['units'].upper()
if dia:
tool_dia = dia
else:
tool_dia = self.ui.new_tooldia_entry.get_value()
tool_dia = dia if dia is not None else self.ui.new_tooldia_entry.get_value()
if tool_dia is None or tool_dia == 0:
self.build_ui()
@ -2586,7 +2579,12 @@ class ToolIsolation(AppTool, Gerber):
"""
tool_from_db = deepcopy(tool)
if tool['data']['tool_target'] != _("Isolation"):
if tool['data']['tool_target'] not in [0, 3]: # [General, Isolation]
for idx in range(self.app.ui.plot_tab_area.count()):
if self.app.ui.plot_tab_area.tabText(idx) == _("Tools Database"):
wdg = self.app.ui.plot_tab_area.widget(idx)
wdg.deleteLater()
self.app.ui.plot_tab_area.removeTab(idx)
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Selected tool can't be used here. Pick another."))
return
@ -3134,16 +3132,16 @@ class IsoUI:
bhlay = QtWidgets.QHBoxLayout()
self.add_newtool_button = FCButton(_('Search and Add'))
self.add_newtool_button.setIcon(QtGui.QIcon(self.app.resource_location + '/plus16.png'))
self.add_newtool_button.setToolTip(
self.search_and_add_btn = FCButton(_('Search and Add'))
self.search_and_add_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/plus16.png'))
self.search_and_add_btn.setToolTip(
_("Add a new tool to the Tool Table\n"
"with the diameter specified above.\n"
"This is done by a background search\n"
"in the Tools Database. If nothing is found\n"
"in the Tools DB then a default tool is added.")
)
bhlay.addWidget(self.add_newtool_button)
bhlay.addWidget(self.search_and_add_btn)
self.addtool_from_db_btn = FCButton(_('Pick from DB'))
self.addtool_from_db_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/search_db32.png'))

View File

@ -980,7 +980,7 @@ class ToolMilling(AppTool, Excellon):
# if the sender is in the column with index 2 then we update the tool_type key
if cw_col == 2:
tt = cw.currentText()
typ = 'Iso' if tt == 'V' else "Rough"
typ = 'Iso' if tt == 'V' else _("Rough")
self.iso_tools[current_uid].update({
'type': typ,

View File

@ -836,7 +836,7 @@ class NonCopperClear(AppTool, Gerber):
# if the sender is in the column with index 2 then we update the tool_type key
if cw_col == 2:
tt = cw.currentText()
typ = 'Iso' if tt == 'V' else "Rough"
typ = 'Iso' if tt == 'V' else _("Rough")
self.ncc_tools[current_uid].update({
'type': typ,
@ -976,7 +976,7 @@ class NonCopperClear(AppTool, Gerber):
def on_tool_add(self, custom_dia=None):
self.blockSignals(True)
filename = self.app.data_path + '\\tools_db.FlatDB'
filename = self.app.tools_database_path()
new_tools_dict = deepcopy(self.default_data)
updated_tooldia = None
@ -1042,7 +1042,7 @@ class NonCopperClear(AppTool, Gerber):
offset = 'Path'
offset_val = 0.0
typ = "Rough"
typ = _("Rough")
tool_type = 'V'
# look in database tools
for db_tool, db_tool_val in tools_db_dict.items():
@ -3721,7 +3721,12 @@ class NonCopperClear(AppTool, Gerber):
"""
tool_from_db = deepcopy(tool)
if tool['data']['tool_target'] != _("NCC"):
if tool['data']['tool_target'] not in [0, 5]: # [General, NCC]
for idx in range(self.app.ui.plot_tab_area.count()):
if self.app.ui.plot_tab_area.tabText(idx) == _("Tools Database"):
wdg = self.app.ui.plot_tab_area.widget(idx)
wdg.deleteLater()
self.app.ui.plot_tab_area.removeTab(idx)
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Selected tool can't be used here. Pick another."))
return

View File

@ -411,7 +411,7 @@ class ToolPaint(AppTool, Gerber):
# if the sender is in the column with index 2 then we update the tool_type key
if cw_col == 2:
tt = cw.currentText()
typ = 'Iso' if tt == 'V' else "Rough"
typ = 'Iso' if tt == 'V' else _("Rough")
self.paint_tools[current_uid].update({
'type': typ,
@ -666,7 +666,7 @@ class ToolPaint(AppTool, Gerber):
def on_tool_add(self, custom_dia=None):
self.blockSignals(True)
filename = self.app.data_path + '\\tools_db.FlatDB'
filename = self.app.tools_database_path()
new_tools_dict = deepcopy(self.default_data)
updated_tooldia = None
@ -729,7 +729,7 @@ class ToolPaint(AppTool, Gerber):
offset = 'Path'
offset_val = 0.0
typ = "Rough"
typ = _("Rough")
tool_type = 'V'
# look in database tools
for db_tool, db_tool_val in tools_db_dict.items():
@ -2626,7 +2626,12 @@ class ToolPaint(AppTool, Gerber):
"""
tool_from_db = deepcopy(tool)
if tool['data']['tool_target'] != _("Paint"):
if tool['data']['tool_target'] not in [0, 4]: # [General, Paint]
for idx in range(self.app.ui.plot_tab_area.count()):
if self.app.ui.plot_tab_area.tabText(idx) == _("Tools Database"):
wdg = self.app.ui.plot_tab_area.widget(idx)
wdg.deleteLater()
self.app.ui.plot_tab_area.removeTab(idx)
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Selected tool can't be used here. Pick another."))
return

View File

@ -359,54 +359,59 @@ class App(QtCore.QObject):
if not os.path.exists(self.data_path):
os.makedirs(self.data_path)
self.log.debug('Created data folder: ' + self.data_path)
os.makedirs(os.path.join(self.data_path, 'preprocessors'))
self.log.debug('Created data preprocessors folder: ' + os.path.join(self.data_path, 'preprocessors'))
self.preprocessorpaths = os.path.join(self.data_path, 'preprocessors')
self.preprocessorpaths = self.preprocessors_path()
if not os.path.exists(self.preprocessorpaths):
os.makedirs(self.preprocessorpaths)
self.log.debug('Created preprocessors folder: ' + self.preprocessorpaths)
# create tools_db.FlatDB file if there is none
db_path = self.tools_database_path()
try:
f = open(self.data_path + '/tools_db.FlatDB')
f = open(db_path)
f.close()
except IOError:
self.log.debug('Creating empty tools_db.FlatDB')
f = open(self.data_path + '/tools_db.FlatDB', 'w')
f = open(db_path, 'w')
json.dump({}, f)
f.close()
# create current_defaults.FlatConfig file if there is none
def_path = self.defaults_path()
try:
f = open(self.data_path + '/current_defaults.FlatConfig')
f = open(def_path)
f.close()
except IOError:
self.log.debug('Creating empty current_defaults.FlatConfig')
f = open(self.data_path + '/current_defaults.FlatConfig', 'w')
f = open(def_path, 'w')
json.dump({}, f)
f.close()
# the factory defaults are written only once at the first launch of the application after installation
FlatCAMDefaults.save_factory_defaults(os.path.join(self.data_path, "factory_defaults.FlatConfig"), self.version)
FlatCAMDefaults.save_factory_defaults(self.factory_defaults_path(), self.version)
# create a recent files json file if there is none
rec_f_path = self.recent_files_path()
try:
f = open(self.data_path + '/recent.json')
f = open(rec_f_path)
f.close()
except IOError:
self.log.debug('Creating empty recent.json')
f = open(self.data_path + '/recent.json', 'w')
f = open(rec_f_path, 'w')
json.dump([], f)
f.close()
# create a recent projects json file if there is none
rec_proj_path = self.recent_projects_path()
try:
fp = open(self.data_path + '/recent_projects.json')
fp = open(rec_proj_path)
fp.close()
except IOError:
self.log.debug('Creating empty recent_projects.json')
fp = open(self.data_path + '/recent_projects.json', 'w')
fp = open(rec_proj_path, 'w')
json.dump([], fp)
fp.close()
@ -1275,7 +1280,7 @@ class App(QtCore.QObject):
self.log.debug("Finished adding FlatCAM Editor's.")
self.set_ui_title(name=_("New Project - Not saved"))
self.ui.set_ui_title(name=_("New Project - Not saved"))
current_platform = platform.architecture()[0]
if current_platform != '64bit':
@ -1865,20 +1870,23 @@ class App(QtCore.QObject):
# else:
# sys.exit(2)
def set_ui_title(self, name):
"""
Sets the title of the main window.
def tools_database_path(self):
return os.path.join(self.data_path, 'tools_db.FlatDB')
:param name: String that store the project path and project name
:return: None
"""
self.ui.setWindowTitle('FlatCAM %s %s - %s - [%s] %s' %
(self.version,
('BETA' if self.beta else ''),
platform.architecture()[0],
self.engine,
name)
)
def defaults_path(self):
return os.path.join(self.data_path, 'current_defaults.FlatConfig')
def factory_defaults_path(self):
return os.path.join(self.data_path, 'factory_defaults.FlatConfig')
def recent_files_path(self):
return os.path.join(self.data_path, 'recent.json')
def recent_projects_path(self):
return os.path.join(self.data_path, 'recent_projects.json')
def preprocessors_path(self):
return os.path.join(self.data_path, 'preprocessors')
def on_app_restart(self):
@ -5651,7 +5659,7 @@ class App(QtCore.QObject):
:return:
"""
filename = self.data_path + '\\tools_db.FlatDB'
filename = self.tools_database_path()
# load the database tools from the file
try:
@ -5731,9 +5739,18 @@ class App(QtCore.QObject):
:return:
"""
tool_from_db = deepcopy(tool)
obj = self.collection.get_active()
if obj.kind == 'geometry':
if tool['data']['tool_target'] not in [0, 1]: # General, Milling Type
# close the tab and delete it
for idx in range(self.ui.plot_tab_area.count()):
if self.ui.plot_tab_area.tabText(idx) == _("Tools Database"):
wdg = self.ui.plot_tab_area.widget(idx)
wdg.deleteLater()
self.ui.plot_tab_area.removeTab(idx)
self.inform.emit('[ERROR_NOTCL] %s' % _("Selected tool can't be used here. Pick another."))
return
obj.on_tool_from_db_inserted(tool=tool_from_db)
# close the tab and delete it
@ -5744,6 +5761,15 @@ class App(QtCore.QObject):
self.ui.plot_tab_area.removeTab(idx)
self.inform.emit('[success] %s' % _("Tool from DB added in Tool Table."))
elif obj.kind == 'gerber':
if tool['data']['tool_target'] not in [0, 3]: # General, Isolation Type
# close the tab and delete it
for idx in range(self.ui.plot_tab_area.count()):
if self.ui.plot_tab_area.tabText(idx) == _("Tools Database"):
wdg = self.ui.plot_tab_area.widget(idx)
wdg.deleteLater()
self.ui.plot_tab_area.removeTab(idx)
self.inform.emit('[ERROR_NOTCL] %s' % _("Selected tool can't be used here. Pick another."))
return
self.isolation_tool.on_tool_from_db_inserted(tool=tool_from_db)
# close the tab and delete it
@ -8894,7 +8920,7 @@ class MenuFileHandlers(QtCore.QObject):
# take the focus of the Notebook on Project Tab.
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
self.app.set_ui_title(name=_("New Project - Not saved"))
self.app.ui.set_ui_title(name=_("New Project - Not saved"))
def on_filenewscript(self, silent=False):
"""
@ -9055,7 +9081,7 @@ class MenuFileHandlers(QtCore.QObject):
self.app.file_opened.emit("project", self.project_filename)
self.app.file_saved.emit("project", self.project_filename)
self.app.set_ui_title(name=self.app.project_filename)
self.app.ui.set_ui_title(name=self.app.project_filename)
self.app.should_we_save = False
@ -9107,7 +9133,7 @@ class MenuFileHandlers(QtCore.QObject):
if not make_copy:
self.app.project_filename = filename
self.app.set_ui_title(name=self.app.project_filename)
self.app.ui.set_ui_title(name=self.app.project_filename)
self.app.should_we_save = False
def on_file_save_objects_pdf(self, use_thread=True):
@ -10316,7 +10342,7 @@ class MenuFileHandlers(QtCore.QObject):
# for some reason, setting ui_title does not work when this method is called from Tcl Shell
# it's because the TclCommand is run in another thread (it inherit TclCommandSignaled)
if cli is None:
self.app.set_ui_title(name=_("Loading Project ... Please Wait ..."))
self.app.ui.set_ui_title(name=_("Loading Project ... Please Wait ..."))
if run_from_arg:
self.splash.showMessage('%s: %ssec\n%s' % (_("Canvas initialization started.\n"
@ -10398,7 +10424,7 @@ class MenuFileHandlers(QtCore.QObject):
# for some reason, setting ui_title does not work when this method is called from Tcl Shell
# it's because the TclCommand is run in another thread (it inherit TclCommandSignaled)
if cli is None:
self.app.set_ui_title(name="{} {}: {}".format(
self.app.ui.set_ui_title(name="{} {}: {}".format(
_("Loading Project ... restoring"), obj['kind'].upper(), obj['options']['name']))
self.app.app_obj.new_object(obj['kind'], obj['options']['name'], obj_init, plot=plot)
@ -10414,7 +10440,7 @@ class MenuFileHandlers(QtCore.QObject):
# for some reason, setting ui_title does not work when this method is called from Tcl Shell
# it's because the TclCommand is run in another thread (it inherit TclCommandSignaled)
if cli is None:
self.app.set_ui_title(name=self.app.project_filename)
self.app.ui.set_ui_title(name=self.app.project_filename)
self.app.log.debug(" **************** Finished PROJECT loading... **************** ")