from PySide6.QtWidgets import QTreeWidget, QTreeWidgetItem from PySide6.QtCore import Qt, Slot as pyqtSlot, Signal as pyqtSignal from PySide6.QtGui import QAction from OCP.AIS import AIS_ColoredShape from OCP.gp import gp_Ax3 from cadquery import Vector from ..mixins import ComponentMixin from ..icons import icon class CQChildItem(QTreeWidgetItem): def __init__(self, cq_item, **kwargs): super(CQChildItem, self).__init__( [type(cq_item).__name__, str(cq_item)], **kwargs ) self.cq_item = cq_item class CQStackItem(QTreeWidgetItem): def __init__(self, name, workplane=None, **kwargs): super(CQStackItem, self).__init__([name, ""], **kwargs) self.workplane = workplane class CQObjectInspector(QTreeWidget, ComponentMixin): name = "CQ Object Inspector" sigRemoveObjects = pyqtSignal(list) sigDisplayObjects = pyqtSignal(list, bool) sigShowPlane = pyqtSignal(bool) sigShowPlane2 = pyqtSignal(bool, float) sigChangePlane = pyqtSignal(gp_Ax3) def __init__(self, parent): super(CQObjectInspector, self).__init__(parent) self.setHeaderHidden(False) self.setRootIsDecorated(True) self.setContextMenuPolicy(Qt.ActionsContextMenu) self.setColumnCount(2) self.setHeaderLabels(["Type", "Value"]) self.root = self.invisibleRootItem() self.inspected_items = [] self._toolbar_actions = [ QAction( icon("inspect"), "Inspect CQ object", self, toggled=self.inspect, checkable=True, ) ] self.addActions(self._toolbar_actions) def menuActions(self): return {"Tools": self._toolbar_actions} def toolbarActions(self): return self._toolbar_actions @pyqtSlot(bool) def inspect(self, value): if value: self.itemSelectionChanged.connect(self.handleSelection) self.itemSelectionChanged.emit() else: self.itemSelectionChanged.disconnect(self.handleSelection) self.sigRemoveObjects.emit(self.inspected_items) self.sigShowPlane.emit(False) @pyqtSlot() def handleSelection(self): inspected_items = self.inspected_items self.sigRemoveObjects.emit(inspected_items) inspected_items.clear() items = self.selectedItems() if len(items) == 0: return item = items[-1] if type(item) is CQStackItem: cq_plane = item.workplane.plane dim = item.workplane.largestDimension() plane = gp_Ax3( cq_plane.origin.toPnt(), cq_plane.zDir.toDir(), cq_plane.xDir.toDir() ) self.sigChangePlane.emit(plane) self.sigShowPlane[bool, float].emit(True, dim) for child in (item.child(i) for i in range(item.childCount())): obj = child.cq_item if hasattr(obj, "wrapped") and type(obj) != Vector: ais = AIS_ColoredShape(obj.wrapped) inspected_items.append(ais) else: self.sigShowPlane.emit(False) obj = item.cq_item if hasattr(obj, "wrapped") and type(obj) != Vector: ais = AIS_ColoredShape(obj.wrapped) inspected_items.append(ais) self.sigDisplayObjects.emit(inspected_items, False) @pyqtSlot(object) def setObject(self, cq_obj): self.root.takeChildren() # iterate through parent objects if they exist while getattr(cq_obj, "parent", None): current_frame = CQStackItem(str(cq_obj.plane.origin), workplane=cq_obj) self.root.addChild(current_frame) for obj in cq_obj.objects: current_frame.addChild(CQChildItem(obj)) cq_obj = cq_obj.parent