add combobox selector to toolbit dock (#14297)

Create a more useful tooltip

checkpoint

fix missing dovetail shape

CAM tool fix

remove image stuff
This commit is contained in:
sliptonic
2024-05-26 13:35:50 -05:00
committed by GitHub
parent 21e6911a81
commit 3980f5281f
5 changed files with 226 additions and 142 deletions

View File

@@ -276,8 +276,9 @@ SET(Tools_Library_SRCS
SET(Tools_Shape_SRCS
Tools/Shape/ballend.fcstd
Tools/Shape/bullnose.fcstd
Tools/Shape/drill.fcstd
Tools/Shape/chamfer.fcstd
Tools/Shape/dovetail.fcstd
Tools/Shape/drill.fcstd
Tools/Shape/endmill.fcstd
Tools/Shape/probe.fcstd
Tools/Shape/slittingsaw.fcstd

View File

@@ -22,53 +22,50 @@
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget_2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lblLibrary">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="libraryEditorOpen">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Path.qrc">
<normaloff>:/icons/CAM_ToolTable.svg</normaloff>:/icons/CAM_ToolTable.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="cboLibraries"/>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="libraryEditorOpen">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Library editor...</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/edit-edit.svg</normaloff>:/icons/edit-edit.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">

View File

@@ -53,7 +53,7 @@ def _getProperty(obj, prop):
attr = getattr(o, name)
if o == attr:
Path.Log.warning(
Path.Log.debug(
translate("PathGui", "%s has no property %s (%s)")
% (obj.Label, prop, name)
)

View File

@@ -344,7 +344,15 @@ class ToolBit(object):
Path.Log.track(obj.Label)
activeDoc = FreeCAD.ActiveDocument
(doc, docOpened) = self._loadBitBody(obj, path)
try:
(doc, docOpened) = self._loadBitBody(obj, path)
except FileNotFoundError:
Path.Log.error(
"Could not find shape file {} for tool bit {}".format(
obj.BitShape, obj.Label
)
)
return
obj.Label = doc.RootObjects[0].Label
self._deleteBitSetup(obj)

View File

@@ -40,6 +40,9 @@ import uuid as UUID
from functools import partial
from PySide.QtGui import QStandardItem, QStandardItemModel, QPixmap
from PySide.QtCore import Qt
if False:
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
@@ -240,84 +243,14 @@ class _TableView(PySide.QtGui.QTableView):
model.removeRow(self._rowWithUuid(uuid))
class ModelFactory(object):
class ModelFactory:
"""Helper class to generate qtdata models for toolbit libraries"""
def __init__(self, path=None):
Path.Log.track()
self.path = ""
# self.currentLib = ""
def __libraryLoad(self, path, datamodel):
Path.Log.track(path)
Path.Preferences.setLastFileToolLibrary(path)
# self.currenLib = path
with open(path) as fp:
library = json.load(fp)
for toolBit in library["tools"]:
try:
nr = toolBit["nr"]
bit = PathToolBit.findToolBit(toolBit["path"], path)
if bit:
Path.Log.track(bit)
tool = PathToolBit.Declaration(bit)
datamodel.appendRow(self._toolAdd(nr, tool, bit))
else:
Path.Log.error(
"Could not find tool #{}: {}".format(nr, toolBit["path"])
)
except Exception as e:
msg = "Error loading tool: {} : {}".format(toolBit["path"], e)
FreeCAD.Console.PrintError(msg)
def _toolAdd(self, nr, tool, path):
strShape = os.path.splitext(os.path.basename(tool["shape"]))[0]
# strDiam = tool['parameter']['Diameter']
tooltip = "{}".format(strShape)
toolNr = PySide.QtGui.QStandardItem()
toolNr.setData(nr, PySide.QtCore.Qt.EditRole)
toolNr.setToolTip(tool["shape"])
toolNr.setData(path, _PathRole)
toolNr.setData(UUID.uuid4(), _UuidRole)
toolNr.setToolTip(tooltip)
toolName = PySide.QtGui.QStandardItem()
toolName.setData(tool["name"], PySide.QtCore.Qt.EditRole)
toolName.setEditable(False)
toolName.setToolTip(tooltip)
toolShape = PySide.QtGui.QStandardItem()
toolShape.setData(strShape, PySide.QtCore.Qt.EditRole)
toolShape.setEditable(False)
return [toolNr, toolName, toolShape]
def newTool(self, datamodel, path):
@staticmethod
def find_libraries(model) -> QStandardItemModel:
"""
Adds a toolbit item to a model
"""
Path.Log.track()
try:
nr = 0
for row in range(datamodel.rowCount()):
itemNr = int(datamodel.item(row, 0).data(PySide.QtCore.Qt.EditRole))
nr = max(nr, itemNr)
nr += 1
tool = PathToolBit.Declaration(path)
except Exception as e:
Path.Log.error(e)
datamodel.appendRow(self._toolAdd(nr, tool, path))
def findLibraries(self, model):
"""
Finds all the fctl files in a location
Returns a QStandardItemModel
Finds all the fctl files in a location.
Returns a QStandardItemModel.
"""
Path.Log.track()
path = Path.Preferences.lastPathToolLibrary()
@@ -328,30 +261,132 @@ class ModelFactory(object):
for libFile in libFiles:
loc, fnlong = os.path.split(libFile)
fn, ext = os.path.splitext(fnlong)
libItem = PySide.QtGui.QStandardItem(fn)
libItem = QStandardItem(fn)
libItem.setToolTip(loc)
libItem.setData(libFile, _PathRole)
libItem.setIcon(PySide.QtGui.QPixmap(":/icons/CAM_ToolTable.svg"))
libItem.setIcon(QPixmap(":/icons/CAM_ToolTable.svg"))
model.appendRow(libItem)
Path.Log.debug("model rows: {}".format(model.rowCount()))
return model
def libraryOpen(self, model, lib=""):
@staticmethod
def __library_load(path: str, data_model: QStandardItemModel):
Path.Log.track(path)
Path.Preferences.setLastFileToolLibrary(path)
try:
with open(path) as fp:
library = json.load(fp)
except Exception as e:
Path.Log.error(f"Failed to load library from {path}: {e}")
return
for tool_bit in library.get("tools", []):
try:
nr = tool_bit["nr"]
bit = PathToolBit.findToolBit(tool_bit["path"], path)
if bit:
Path.Log.track(bit)
tool = PathToolBit.Declaration(bit)
data_model.appendRow(ModelFactory._tool_add(nr, tool, bit))
else:
Path.Log.error(f"Could not find tool #{nr}: {tool_bit['path']}")
except Exception as e:
msg = f"Error loading tool: {tool_bit['path']} : {e}"
FreeCAD.Console.PrintError(msg)
@staticmethod
def _generate_tooltip(toolbit: dict) -> str:
"""
opens the tools in library
Returns a QStandardItemModel
Generate an HTML tooltip for a given toolbit dictionary.
Args:
toolbit (dict): A dictionary containing toolbit information.
Returns:
str: An HTML string representing the tooltip.
"""
tooltip = f"<b>Name:</b> {toolbit['name']}<br>"
tooltip += f"<b>Shape File:</b> {toolbit['shape']}<br>"
tooltip += "<b>Parameters:</b><br>"
parameters = toolbit.get("parameter", {})
if parameters:
for key, value in parameters.items():
tooltip += f" <b>{key}:</b> {value}<br>"
else:
tooltip += " No parameters provided.<br>"
attributes = toolbit.get("attribute", {})
if attributes:
tooltip += "<b>Attributes:</b><br>"
for key, value in attributes.items():
tooltip += f" <b>{key}:</b> {value}<br>"
return tooltip
@staticmethod
def _tool_add(nr: int, tool: dict, path: str):
str_shape = os.path.splitext(os.path.basename(tool["shape"]))[0]
tooltip = ModelFactory._generate_tooltip(tool)
tool_nr = QStandardItem()
tool_nr.setData(nr, Qt.EditRole)
tool_nr.setData(path, _PathRole)
tool_nr.setData(UUID.uuid4(), _UuidRole)
tool_nr.setToolTip(tooltip)
tool_name = QStandardItem()
tool_name.setData(tool["name"], Qt.EditRole)
tool_name.setEditable(False)
tool_name.setToolTip(tooltip)
tool_shape = QStandardItem()
tool_shape.setData(str_shape, Qt.EditRole)
tool_shape.setEditable(False)
return [tool_nr, tool_name, tool_shape]
@staticmethod
def new_tool(datamodel: QStandardItemModel, path: str):
"""
Adds a toolbit item to a model.
"""
Path.Log.track()
try:
nr = (
max(
(
int(datamodel.item(row, 0).data(Qt.EditRole))
for row in range(datamodel.rowCount())
),
default=0,
)
+ 1
)
tool = PathToolBit.Declaration(path)
except Exception as e:
Path.Log.error(e)
return
datamodel.appendRow(ModelFactory._tool_add(nr, tool, path))
@staticmethod
def library_open(model: QStandardItemModel, lib: str = "") -> QStandardItemModel:
"""
Opens the tools in a library.
Returns a QStandardItemModel.
"""
Path.Log.track(lib)
if lib == "":
if not lib:
lib = Path.Preferences.lastFileToolLibrary()
if lib == "" or lib is None:
if not lib or not os.path.isfile(lib):
return model
if os.path.isfile(lib): # An individual library is wanted
self.__libraryLoad(lib, model)
ModelFactory.__library_load(lib, model)
Path.Log.debug("model rows: {}".format(model.rowCount()))
return model
@@ -365,6 +400,9 @@ class ToolBitSelector(object):
self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolBitSelector.ui")
self.factory = ModelFactory()
self.toolModel = PySide.QtGui.QStandardItemModel(0, len(self.columnNames()))
self.libraryModel = PySide.QtGui.QStandardItemModel(0, len(self.columnNames()))
self.factory.find_libraries(self.libraryModel)
self.setupUI()
self.title = self.form.windowTitle()
@@ -383,23 +421,63 @@ class ToolBitSelector(object):
Path.Log.track()
self.toolModel.clear()
self.toolModel.setHorizontalHeaderLabels(self.columnNames())
self.form.lblLibrary.setText(self.currentLibrary(True))
self.form.lblLibrary.setToolTip(self.currentLibrary(False))
self.factory.libraryOpen(self.toolModel)
# Get the currently selected index in the combobox
currentIndex = self.form.cboLibraries.currentIndex()
if currentIndex != -1:
# Get the data for the selected index
libPath = self.libraryModel.item(currentIndex).data(_PathRole)
self.factory.library_open(self.toolModel, libPath)
else:
pass
self.toolModel.takeColumn(3)
self.toolModel.takeColumn(2)
def setupUI(self):
Path.Log.track()
self.loadData()
self.loadData() # Load the initial data for the tool model
self.form.tools.setModel(self.toolModel)
self.form.tools.selectionModel().selectionChanged.connect(self.enableButtons)
self.form.tools.doubleClicked.connect(
partial(self.selectedOrAllToolControllers)
)
# Set the library model to the combobox
self.form.cboLibraries.setModel(self.libraryModel)
# Connect the library change to reload data and update tooltip
self.form.cboLibraries.currentIndexChanged.connect(self.loadData)
self.form.cboLibraries.currentIndexChanged.connect(self.updateLibraryTooltip)
# Set the current library as the selected item in the combobox
current_lib = self.currentLibrary(True) # True to get short name only
currentIndex = self.form.cboLibraries.findText(current_lib)
if currentIndex == -1 and self.libraryModel.rowCount() > 0:
# If current library is not found, default to the first item
currentIndex = 0
self.form.cboLibraries.setCurrentIndex(currentIndex)
self.updateLibraryTooltip(currentIndex) # Initialize the tooltip
self.form.libraryEditorOpen.clicked.connect(self.libraryEditorOpen)
self.form.addToolController.clicked.connect(self.selectedOrAllToolControllers)
def updateLibraryTooltip(self, index):
if index != -1:
item = self.libraryModel.item(index)
if item:
libPath = item.data(_PathRole)
self.form.cboLibraries.setToolTip(f"{libPath}")
else:
self.form.cboLibraries.setToolTip(
translate("CAM_Toolbit", "Select a library")
)
else:
self.form.cboLibraries.setToolTip(
translate("CAM_Toolbit", "No library selected")
)
def enableButtons(self):
selected = len(self.form.tools.selectedIndexes()) >= 1
if selected:
@@ -742,12 +820,12 @@ class ToolBitLibrary(object):
self.toolModel.clear()
self.listModel.clear()
self.factory.libraryOpen(self.toolModel, lib=path)
self.factory.findLibraries(self.listModel)
self.factory.library_open(self.toolModel, lib=path)
self.factory.find_libraries(self.listModel)
else:
self.toolModel.clear()
self.factory.libraryOpen(self.toolModel, lib=path)
self.factory.library_open(self.toolModel, lib=path)
self.path = path
self.form.setWindowTitle("{}".format(Path.Preferences.lastPathToolLibrary()))