add unused parameters to show_object for compat with ocp_vscode

This commit is contained in:
jdegenstein
2023-04-12 10:49:10 -05:00
committed by GitHub
parent 151b8b8e36
commit 9a60cf7802
2 changed files with 617 additions and 557 deletions

View File

@@ -6,9 +6,15 @@ from typing import List
import cadquery as cq import cadquery as cq
from PyQt5 import QtCore from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QObject, pyqtSlot, pyqtSignal, QEventLoop, QAbstractTableModel from PyQt5.QtCore import (
from PyQt5.QtWidgets import (QAction, Qt,
QTableView) QObject,
pyqtSlot,
pyqtSignal,
QEventLoop,
QAbstractTableModel,
)
from PyQt5.QtWidgets import QAction, QTableView
from logbook import info from logbook import info
from path import Path from path import Path
from pyqtgraph.parametertree import Parameter from pyqtgraph.parametertree import Parameter
@@ -18,46 +24,43 @@ from random import randrange as rrr, seed
from ..cq_utils import find_cq_objects, reload_cq from ..cq_utils import find_cq_objects, reload_cq
from ..mixins import ComponentMixin from ..mixins import ComponentMixin
DUMMY_FILE = '<string>' DUMMY_FILE = "<string>"
class DbgState(Enum): class DbgState(Enum):
STEP = auto() STEP = auto()
CONT = auto() CONT = auto()
STEP_IN = auto() STEP_IN = auto()
RETURN = auto() RETURN = auto()
class DbgEevent(object):
LINE = 'line' class DbgEevent(object):
CALL = 'call' LINE = "line"
RETURN = 'return' CALL = "call"
RETURN = "return"
class LocalsModel(QAbstractTableModel): class LocalsModel(QAbstractTableModel):
HEADER = ("Name", "Type", "Value")
HEADER = ('Name','Type', 'Value')
def __init__(self, parent): def __init__(self, parent):
super(LocalsModel, self).__init__(parent) super(LocalsModel, self).__init__(parent)
self.frame = None self.frame = None
def update_frame(self, frame): def update_frame(self, frame):
self.frame = [
self.frame = \ (k, type(v).__name__, str(v))
[(k,type(v).__name__, str(v)) for k,v in frame.items() if not k.startswith('_')] for k, v in frame.items()
if not k.startswith("_")
]
def rowCount(self, parent=QtCore.QModelIndex()): def rowCount(self, parent=QtCore.QModelIndex()):
if self.frame: if self.frame:
return len(self.frame) return len(self.frame)
else: else:
return 0 return 0
def columnCount(self, parent=QtCore.QModelIndex()): def columnCount(self, parent=QtCore.QModelIndex()):
return 3 return 3
def headerData(self, section, orientation, role=Qt.DisplayRole): def headerData(self, section, orientation, role=Qt.DisplayRole):
@@ -75,11 +78,9 @@ class LocalsModel(QAbstractTableModel):
class LocalsView(QTableView, ComponentMixin): class LocalsView(QTableView, ComponentMixin):
name = "Variables"
name = 'Variables'
def __init__(self, parent): def __init__(self, parent):
super(LocalsView, self).__init__(parent) super(LocalsView, self).__init__(parent)
ComponentMixin.__init__(self) ComponentMixin.__init__(self)
@@ -91,23 +92,24 @@ class LocalsView(QTableView,ComponentMixin):
@pyqtSlot(dict) @pyqtSlot(dict)
def update_frame(self, frame): def update_frame(self, frame):
model = LocalsModel(self) model = LocalsModel(self)
model.update_frame(frame) model.update_frame(frame)
self.setModel(model) self.setModel(model)
class Debugger(QObject, ComponentMixin): class Debugger(QObject, ComponentMixin):
name = "Debugger"
name = 'Debugger' preferences = Parameter.create(
name="Preferences",
preferences = Parameter.create(name='Preferences',children=[ children=[
{'name': 'Reload CQ', 'type': 'bool', 'value': False}, {"name": "Reload CQ", "type": "bool", "value": False},
{'name': 'Add script dir to path','type': 'bool', 'value': True}, {"name": "Add script dir to path", "type": "bool", "value": True},
{'name': 'Change working dir to script dir','type': 'bool', 'value': True}, {"name": "Change working dir to script dir", "type": "bool", "value": True},
{'name': 'Reload imported modules', 'type': 'bool', 'value': True}, {"name": "Reload imported modules", "type": "bool", "value": True},
]) ],
)
sigRendered = pyqtSignal(dict) sigRendered = pyqtSignal(dict)
sigLocals = pyqtSignal(dict) sigLocals = pyqtSignal(dict)
@@ -122,78 +124,81 @@ class Debugger(QObject,ComponentMixin):
_frames: List[FrameType] _frames: List[FrameType]
def __init__(self, parent): def __init__(self, parent):
super(Debugger, self).__init__(parent) super(Debugger, self).__init__(parent)
ComponentMixin.__init__(self) ComponentMixin.__init__(self)
self.inner_event_loop = QEventLoop(self) self.inner_event_loop = QEventLoop(self)
self._actions = \ self._actions = {
{'Run' : [QAction(icon('run'), "Run": [
'Render', QAction(
self, icon("run"), "Render", self, shortcut="F5", triggered=self.render
shortcut='F5', ),
triggered=self.render), QAction(
QAction(icon('debug'), icon("debug"),
'Debug', "Debug",
self, self,
checkable=True, checkable=True,
shortcut='ctrl+F5', shortcut="ctrl+F5",
triggered=self.debug), triggered=self.debug,
QAction(icon('arrow-step-over'), ),
'Step', QAction(
icon("arrow-step-over"),
"Step",
self, self,
shortcut='ctrl+F10', shortcut="ctrl+F10",
triggered=lambda: self.debug_cmd(DbgState.STEP)), triggered=lambda: self.debug_cmd(DbgState.STEP),
QAction(icon('arrow-step-in'), ),
'Step in', QAction(
icon("arrow-step-in"),
"Step in",
self, self,
shortcut='ctrl+F11', shortcut="ctrl+F11",
triggered=lambda: self.debug_cmd(DbgState.STEP_IN)), triggered=lambda: self.debug_cmd(DbgState.STEP_IN),
QAction(icon('arrow-continue'), ),
'Continue', QAction(
icon("arrow-continue"),
"Continue",
self, self,
shortcut='ctrl+F12', shortcut="ctrl+F12",
triggered=lambda: self.debug_cmd(DbgState.CONT)) triggered=lambda: self.debug_cmd(DbgState.CONT),
]} ),
]
}
self._frames = [] self._frames = []
def get_current_script(self): def get_current_script(self):
return self.parent().components["editor"].get_text_with_eol()
return self.parent().components['editor'].get_text_with_eol()
def get_breakpoints(self): def get_breakpoints(self):
return self.parent().components["editor"].debugger.get_breakpoints()
return self.parent().components['editor'].debugger.get_breakpoints()
def compile_code(self, cq_script): def compile_code(self, cq_script):
try: try:
module = ModuleType('temp') module = ModuleType("temp")
cq_code = compile(cq_script, '<string>', 'exec') cq_code = compile(cq_script, "<string>", "exec")
return cq_code, module return cq_code, module
except Exception: except Exception:
self.sigTraceback.emit(sys.exc_info(), cq_script) self.sigTraceback.emit(sys.exc_info(), cq_script)
return None, None return None, None
def _exec(self, code, locals_dict, globals_dict): def _exec(self, code, locals_dict, globals_dict):
with ExitStack() as stack: with ExitStack() as stack:
fname = self.parent().components['editor'].filename fname = self.parent().components["editor"].filename
p = Path(fname if fname else '').abspath().dirname() p = Path(fname if fname else "").abspath().dirname()
if self.preferences['Add script dir to path'] and p.exists(): if self.preferences["Add script dir to path"] and p.exists():
sys.path.insert(0, p) sys.path.insert(0, p)
stack.callback(sys.path.remove, p) stack.callback(sys.path.remove, p)
if self.preferences['Change working dir to script dir'] and p.exists(): if self.preferences["Change working dir to script dir"] and p.exists():
stack.enter_context(p) stack.enter_context(p)
if self.preferences['Reload imported modules']: if self.preferences["Reload imported modules"]:
stack.enter_context(module_manager()) stack.enter_context(module_manager())
exec(code, locals_dict, globals_dict) exec(code, locals_dict, globals_dict)
def _rand_color(self, alpha = 0., cfloat=False): def _rand_color(self, alpha=0.0, cfloat=False):
# helper function to generate a random color dict # helper function to generate a random color dict
# for CQ-editor's show_object function # for CQ-editor's show_object function
lower = 10 lower = 10
@@ -205,50 +210,80 @@ class Debugger(QObject,ComponentMixin):
(rrr(lower, upper) / 255), (rrr(lower, upper) / 255),
alpha, alpha,
) )
return {"alpha": alpha, return {
"alpha": alpha,
"color": ( "color": (
rrr(lower, upper), rrr(lower, upper),
rrr(lower, upper), rrr(lower, upper),
rrr(lower, upper), rrr(lower, upper),
)} ),
}
def _inject_locals(self, module): def _inject_locals(self, module):
cq_objects = {} cq_objects = {}
def _show_object(obj,name=None, options={}): def _show_object(
obj,
name=None,
options={}, # all following inputs are ignored by cq-editor
parent=1,
clear=True,
port=3939,
axes=False,
axes0=False,
grid=False,
ticks=10,
ortho=True,
transparent=False,
default_color=(232, 176, 36),
reset_camera=True,
zoom=1.0,
default_edgecolor=(128, 128, 128),
render_edges=True,
render_normals=False,
render_mates=False,
mate_scale=1.0,
deviation=0.1,
angular_tolerance=0.2,
edge_accuracy=5.0,
ambient_intensity=1.0,
direct_intensity=0.12,
):
if name: if name:
cq_objects.update({name: SimpleNamespace(shape=obj, options=options)}) cq_objects.update({name: SimpleNamespace(shape=obj, options=options)})
else: else:
cq_objects.update({str(id(obj)) : SimpleNamespace(shape=obj,options=options)}) cq_objects.update(
{str(id(obj)): SimpleNamespace(shape=obj, options=options)}
)
def _debug(obj, name=None): def _debug(obj, name=None):
_show_object(obj, name, options=dict(color="red", alpha=0.2))
_show_object(obj,name,options=dict(color='red',alpha=0.2)) module.__dict__["show_object"] = _show_object
module.__dict__["debug"] = _debug
module.__dict__["rand_color"] = self._rand_color
module.__dict__["log"] = lambda x: info(str(x))
module.__dict__["cq"] = cq
module.__dict__['show_object'] = _show_object return cq_objects, set(module.__dict__) - {"cq"}
module.__dict__['debug'] = _debug
module.__dict__['rand_color'] = self._rand_color
module.__dict__['log'] = lambda x: info(str(x))
module.__dict__['cq'] = cq
return cq_objects, set(module.__dict__)-{'cq'}
def _cleanup_locals(self, module, injected_names): def _cleanup_locals(self, module, injected_names):
for name in injected_names:
for name in injected_names: module.__dict__.pop(name) module.__dict__.pop(name)
@pyqtSlot(bool) @pyqtSlot(bool)
def render(self): def render(self):
seed(59798267586177) #reset the seed every time render is called (preserves colors run to run) seed(
if self.preferences['Reload CQ']: 59798267586177
) # reset the seed every time render is called (preserves colors run to run)
if self.preferences["Reload CQ"]:
reload_cq() reload_cq()
cq_script = self.get_current_script() cq_script = self.get_current_script()
cq_code, module = self.compile_code(cq_script) cq_code, module = self.compile_code(cq_script)
if cq_code is None: return if cq_code is None:
return
cq_objects, injected_names = self._inject_locals(module) cq_objects, injected_names = self._inject_locals(module)
@@ -262,8 +297,7 @@ class Debugger(QObject,ComponentMixin):
if len(cq_objects) == 0: if len(cq_objects) == 0:
cq_objects = find_cq_objects(module.__dict__) cq_objects = find_cq_objects(module.__dict__)
self.sigRendered.emit(cq_objects) self.sigRendered.emit(cq_objects)
self.sigTraceback.emit(None, self.sigTraceback.emit(None, cq_script)
cq_script)
self.sigLocals.emit(module.__dict__) self.sigLocals.emit(module.__dict__)
except Exception: except Exception:
exc_info = sys.exc_info() exc_info = sys.exc_info()
@@ -276,7 +310,6 @@ class Debugger(QObject,ComponentMixin):
@pyqtSlot(bool) @pyqtSlot(bool)
def debug(self, value): def debug(self, value):
previous_trace = sys.gettrace() previous_trace = sys.gettrace()
if value: if value:
@@ -288,14 +321,13 @@ class Debugger(QObject,ComponentMixin):
if code is None: if code is None:
self.sigDebugging.emit(False) self.sigDebugging.emit(False)
self._actions['Run'][1].setChecked(False) self._actions["Run"][1].setChecked(False)
return return
cq_objects, injected_names = self._inject_locals(module) cq_objects, injected_names = self._inject_locals(module)
# clear possible traceback # clear possible traceback
self.sigTraceback.emit(None, self.sigTraceback.emit(None, self.script)
self.script)
try: try:
sys.settrace(self.trace_callback) sys.settrace(self.trace_callback)
@@ -303,12 +335,11 @@ class Debugger(QObject,ComponentMixin):
except Exception: except Exception:
exc_info = sys.exc_info() exc_info = sys.exc_info()
sys.last_traceback = exc_info[-1] sys.last_traceback = exc_info[-1]
self.sigTraceback.emit(exc_info, self.sigTraceback.emit(exc_info, self.script)
self.script)
finally: finally:
sys.settrace(previous_trace) sys.settrace(previous_trace)
self.sigDebugging.emit(False) self.sigDebugging.emit(False)
self._actions['Run'][1].setChecked(False) self._actions["Run"][1].setChecked(False)
if len(cq_objects) == 0: if len(cq_objects) == 0:
cq_objects = find_cq_objects(module.__dict__) cq_objects = find_cq_objects(module.__dict__)
@@ -322,15 +353,11 @@ class Debugger(QObject,ComponentMixin):
sys.settrace(previous_trace) sys.settrace(previous_trace)
self.inner_event_loop.exit(0) self.inner_event_loop.exit(0)
def debug_cmd(self, state=DbgState.STEP): def debug_cmd(self, state=DbgState.STEP):
self.state = state self.state = state
self.inner_event_loop.exit(0) self.inner_event_loop.exit(0)
def trace_callback(self, frame, event, arg): def trace_callback(self, frame, event, arg):
filename = frame.f_code.co_filename filename = frame.f_code.co_filename
if filename == DUMMY_FILE: if filename == DUMMY_FILE:
@@ -343,13 +370,13 @@ class Debugger(QObject,ComponentMixin):
return None return None
def trace_local(self, frame, event, arg): def trace_local(self, frame, event, arg):
lineno = frame.f_lineno lineno = frame.f_lineno
if event in (DbgEevent.LINE,): if event in (DbgEevent.LINE,):
if (self.state in (DbgState.STEP, DbgState.STEP_IN) and frame is self._frames[-1]) \ if (
or (lineno in self.breakpoints): self.state in (DbgState.STEP, DbgState.STEP_IN)
and frame is self._frames[-1]
) or (lineno in self.breakpoints):
if lineno in self.breakpoints: if lineno in self.breakpoints:
self._frames.append(frame) self._frames.append(frame)

View File

@@ -1,4 +1,11 @@
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QAction, QMenu, QWidget, QAbstractItemView from PyQt5.QtWidgets import (
QTreeWidget,
QTreeWidgetItem,
QAction,
QMenu,
QWidget,
QAbstractItemView,
)
from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal
from pyqtgraph.parametertree import Parameter, ParameterTree from pyqtgraph.parametertree import Parameter, ParameterTree
@@ -8,33 +15,42 @@ from OCP.gp import gp_Dir, gp_Pnt, gp_Ax1
from ..mixins import ComponentMixin from ..mixins import ComponentMixin
from ..icons import icon from ..icons import icon
from ..cq_utils import make_AIS, export, to_occ_color, is_obj_empty, get_occ_color, set_color from ..cq_utils import (
make_AIS,
export,
to_occ_color,
is_obj_empty,
get_occ_color,
set_color,
)
from .viewer import DEFAULT_FACE_COLOR from .viewer import DEFAULT_FACE_COLOR
from ..utils import splitter, layout, get_save_filename from ..utils import splitter, layout, get_save_filename
class TopTreeItem(QTreeWidgetItem): class TopTreeItem(QTreeWidgetItem):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(TopTreeItem, self).__init__(*args, **kwargs) super(TopTreeItem, self).__init__(*args, **kwargs)
class ObjectTreeItem(QTreeWidgetItem): class ObjectTreeItem(QTreeWidgetItem):
props = [
{"name": "Name", "type": "str", "value": ""},
{"name": "Color", "type": "color", "value": "#f4a824"},
{"name": "Alpha", "type": "float", "value": 0, "limits": (0, 1), "step": 1e-1},
{"name": "Visible", "type": "bool", "value": True},
]
props = [{'name': 'Name', 'type': 'str', 'value': ''}, def __init__(
{'name': 'Color', 'type': 'color', 'value': "#f4a824"}, self,
{'name': 'Alpha', 'type': 'float', 'value': 0, 'limits': (0,1), 'step': 1e-1},
{'name': 'Visible', 'type': 'bool','value': True}]
def __init__(self,
name, name,
ais=None, ais=None,
shape=None, shape=None,
shape_display=None, shape_display=None,
sig=None, sig=None,
alpha=0., alpha=0.0,
color='#f4a824', color="#f4a824",
**kwargs): **kwargs
):
super(ObjectTreeItem, self).__init__([name], **kwargs) super(ObjectTreeItem, self).__init__([name], **kwargs)
self.setFlags(self.flags() | Qt.ItemIsUserCheckable) self.setFlags(self.flags() | Qt.ItemIsUserCheckable)
self.setCheckState(0, Qt.Checked) self.setCheckState(0, Qt.Checked)
@@ -44,27 +60,29 @@ class ObjectTreeItem(QTreeWidgetItem):
self.shape_display = shape_display self.shape_display = shape_display
self.sig = sig self.sig = sig
self.properties = Parameter.create(name='Properties', self.properties = Parameter.create(name="Properties", children=self.props)
children=self.props)
self.properties['Name'] = name self.properties["Name"] = name
self.properties['Alpha'] = ais.Transparency() self.properties["Alpha"] = ais.Transparency()
self.properties['Color'] = get_occ_color(ais) if ais and ais.HasColor() else get_occ_color(DEFAULT_FACE_COLOR) self.properties["Color"] = (
get_occ_color(ais)
if ais and ais.HasColor()
else get_occ_color(DEFAULT_FACE_COLOR)
)
self.properties.sigTreeStateChanged.connect(self.propertiesChanged) self.properties.sigTreeStateChanged.connect(self.propertiesChanged)
def propertiesChanged(self, properties, changed): def propertiesChanged(self, properties, changed):
changed_prop = changed[0][0] changed_prop = changed[0][0]
self.setData(0,0,self.properties['Name']) self.setData(0, 0, self.properties["Name"])
self.ais.SetTransparency(self.properties['Alpha']) self.ais.SetTransparency(self.properties["Alpha"])
if changed_prop.name() == 'Color': if changed_prop.name() == "Color":
set_color(self.ais, to_occ_color(self.properties['Color'])) set_color(self.ais, to_occ_color(self.properties["Color"]))
self.ais.Redisplay() self.ais.Redisplay()
if self.properties['Visible']: if self.properties["Visible"]:
self.setCheckState(0, Qt.Checked) self.setCheckState(0, Qt.Checked)
else: else:
self.setCheckState(0, Qt.Unchecked) self.setCheckState(0, Qt.Unchecked)
@@ -72,29 +90,29 @@ class ObjectTreeItem(QTreeWidgetItem):
if self.sig: if self.sig:
self.sig.emit() self.sig.emit()
class CQRootItem(TopTreeItem): class CQRootItem(TopTreeItem):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(CQRootItem, self).__init__(["CQ models"], *args, **kwargs)
super(CQRootItem,self).__init__(['CQ models'],*args,**kwargs)
class HelpersRootItem(TopTreeItem): class HelpersRootItem(TopTreeItem):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(HelpersRootItem, self).__init__(["Helpers"], *args, **kwargs)
super(HelpersRootItem,self).__init__(['Helpers'],*args,**kwargs)
class ObjectTree(QWidget, ComponentMixin): class ObjectTree(QWidget, ComponentMixin):
name = "Object Tree"
name = 'Object Tree'
_stash = [] _stash = []
preferences = Parameter.create(name='Preferences',children=[ preferences = Parameter.create(
{'name': 'Preserve properties on reload', 'type': 'bool', 'value': False}, name="Preferences",
{'name': 'Clear all before each run', 'type': 'bool', 'value': True}, children=[
{'name': 'STL precision','type': 'float', 'value': .1}]) {"name": "Preserve properties on reload", "type": "bool", "value": False},
{"name": "Clear all before each run", "type": "bool", "value": True},
{"name": "STL precision", "type": "float", "value": 0.1},
],
)
sigObjectsAdded = pyqtSignal([list], [list, bool]) sigObjectsAdded = pyqtSignal([list], [list, bool])
sigObjectsRemoved = pyqtSignal(list) sigObjectsRemoved = pyqtSignal(list)
@@ -104,11 +122,11 @@ class ObjectTree(QWidget,ComponentMixin):
sigObjectPropertiesChanged = pyqtSignal() sigObjectPropertiesChanged = pyqtSignal()
def __init__(self, parent): def __init__(self, parent):
super(ObjectTree, self).__init__(parent) super(ObjectTree, self).__init__(parent)
self.tree = tree = QTreeWidget(self, self.tree = tree = QTreeWidget(
selectionMode=QAbstractItemView.ExtendedSelection) self, selectionMode=QAbstractItemView.ExtendedSelection
)
self.properties_editor = ParameterTree(self) self.properties_editor = ParameterTree(self)
tree.setHeaderHidden(True) tree.setHeaderHidden(True)
@@ -117,8 +135,7 @@ class ObjectTree(QWidget,ComponentMixin):
tree.setContextMenuPolicy(Qt.ActionsContextMenu) tree.setContextMenuPolicy(Qt.ActionsContextMenu)
# forward itemChanged singal # forward itemChanged singal
tree.itemChanged.connect(\ tree.itemChanged.connect(lambda item, col: self.sigItemChanged.emit(item, col))
lambda item,col: self.sigItemChanged.emit(item,col))
# handle visibility changes form tree # handle visibility changes form tree
tree.itemChanged.connect(self.handleChecked) tree.itemChanged.connect(self.handleChecked)
@@ -131,30 +148,31 @@ class ObjectTree(QWidget,ComponentMixin):
tree.expandToDepth(1) tree.expandToDepth(1)
self._export_STL_action = \ self._export_STL_action = QAction(
QAction('Export as STL', "Export as STL",
self, self,
enabled=False, enabled=False,
triggered=lambda: \ triggered=lambda: self.export("stl", self.preferences["STL precision"]),
self.export('stl', )
self.preferences['STL precision']))
self._export_STEP_action = \ self._export_STEP_action = QAction(
QAction('Export as STEP', "Export as STEP", self, enabled=False, triggered=lambda: self.export("step")
)
self._clear_current_action = QAction(
icon("delete"),
"Clear current",
self, self,
enabled=False, enabled=False,
triggered=lambda: \ triggered=self.removeSelected,
self.export('step')) )
self._clear_current_action = QAction(icon('delete'), self._toolbar_actions = [
'Clear current', QAction(
self, icon("delete-many"), "Clear all", self, triggered=self.removeObjects
enabled=False, ),
triggered=self.removeSelected) self._clear_current_action,
]
self._toolbar_actions = \
[QAction(icon('delete-many'),'Clear all',self,triggered=self.removeObjects),
self._clear_current_action,]
self.prepareMenu() self.prepareMenu()
@@ -163,87 +181,78 @@ class ObjectTree(QWidget,ComponentMixin):
self.prepareLayout() self.prepareLayout()
def prepareMenu(self): def prepareMenu(self):
self.tree.setContextMenuPolicy(Qt.CustomContextMenu) self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
self._context_menu = QMenu(self) self._context_menu = QMenu(self)
self._context_menu.addActions(self._toolbar_actions) self._context_menu.addActions(self._toolbar_actions)
self._context_menu.addActions((self._export_STL_action, self._context_menu.addActions(
self._export_STEP_action)) (self._export_STL_action, self._export_STEP_action)
)
def prepareLayout(self): def prepareLayout(self):
self._splitter = splitter(
self._splitter = splitter((self.tree,self.properties_editor), (self.tree, self.properties_editor),
stretch_factors=(2, 1), stretch_factors=(2, 1),
orientation=Qt.Vertical) orientation=Qt.Vertical,
)
layout(self, (self._splitter,), top_widget=self) layout(self, (self._splitter,), top_widget=self)
self._splitter.show() self._splitter.show()
def showMenu(self, position): def showMenu(self, position):
self._context_menu.exec_(self.tree.viewport().mapToGlobal(position)) self._context_menu.exec_(self.tree.viewport().mapToGlobal(position))
def menuActions(self): def menuActions(self):
return {"Tools": [self._export_STL_action, self._export_STEP_action]}
return {'Tools' : [self._export_STL_action,
self._export_STEP_action]}
def toolbarActions(self): def toolbarActions(self):
return self._toolbar_actions return self._toolbar_actions
def addLines(self): def addLines(self):
origin = (0, 0, 0) origin = (0, 0, 0)
ais_list = [] ais_list = []
for name,color,direction in zip(('X','Y','Z'), for name, color, direction in zip(
((0.2,0,0),'lawngreen','blue'), ("X", "Y", "Z"),
((1,0,0),(0,1,0),(0,0,1))): ((0.2, 0, 0), "lawngreen", "blue"),
line_placement = Geom_Line(gp_Ax1(gp_Pnt(*origin), ((1, 0, 0), (0, 1, 0), (0, 0, 1)),
gp_Dir(*direction))) ):
line_placement = Geom_Line(gp_Ax1(gp_Pnt(*origin), gp_Dir(*direction)))
line = AIS_Line(line_placement) line = AIS_Line(line_placement)
line.SetColor(to_occ_color(color)) line.SetColor(to_occ_color(color))
self.Helpers.addChild(ObjectTreeItem(name, self.Helpers.addChild(ObjectTreeItem(name, ais=line))
ais=line))
ais_list.append(line) ais_list.append(line)
self.sigObjectsAdded.emit(ais_list) self.sigObjectsAdded.emit(ais_list)
def _current_properties(self): def _current_properties(self):
current_params = {} current_params = {}
for i in range(self.CQ.childCount()): for i in range(self.CQ.childCount()):
child = self.CQ.child(i) child = self.CQ.child(i)
current_params[child.properties['Name']] = child.properties current_params[child.properties["Name"]] = child.properties
return current_params return current_params
def _restore_properties(self, obj, properties): def _restore_properties(self, obj, properties):
for p in properties[obj.properties["Name"]]:
for p in properties[obj.properties['Name']]:
obj.properties[p.name()] = p.value() obj.properties[p.name()] = p.value()
@pyqtSlot(dict, bool) @pyqtSlot(dict, bool)
@pyqtSlot(dict) @pyqtSlot(dict)
def addObjects(self, objects, clean=False, root=None): def addObjects(self, objects, clean=False, root=None):
if root is None: if root is None:
root = self.CQ root = self.CQ
request_fit_view = True if root.childCount() == 0 else False request_fit_view = True if root.childCount() == 0 else False
preserve_props = self.preferences['Preserve properties on reload'] preserve_props = self.preferences["Preserve properties on reload"]
if preserve_props: if preserve_props:
current_props = self._current_properties() current_props = self._current_properties()
if clean or self.preferences['Clear all before each run']: if clean or self.preferences["Clear all before each run"]:
self.removeObjects() self.removeObjects()
ais_list = [] ais_list = []
@@ -254,16 +263,18 @@ class ObjectTree(QWidget,ComponentMixin):
for name, obj in objects_f.items(): for name, obj in objects_f.items():
ais, shape_display = make_AIS(obj.shape, obj.options) ais, shape_display = make_AIS(obj.shape, obj.options)
child = ObjectTreeItem(name, child = ObjectTreeItem(
name,
shape=obj.shape, shape=obj.shape,
shape_display=shape_display, shape_display=shape_display,
ais=ais, ais=ais,
sig=self.sigObjectPropertiesChanged) sig=self.sigObjectPropertiesChanged,
)
if preserve_props and name in current_props: if preserve_props and name in current_props:
self._restore_properties(child, current_props) self._restore_properties(child, current_props)
if child.properties['Visible']: if child.properties["Visible"]:
ais_list.append(ais) ais_list.append(ais)
root.addChild(child) root.addChild(child)
@@ -274,24 +285,53 @@ class ObjectTree(QWidget,ComponentMixin):
self.sigObjectsAdded[list].emit(ais_list) self.sigObjectsAdded[list].emit(ais_list)
@pyqtSlot(object, str, object) @pyqtSlot(object, str, object)
def addObject(self,obj,name='',options={}): def addObject(
self,
obj,
name="",
options={}, # all following inputs are ignored by cq-editor
parent=1,
clear=True,
port=3939,
axes=False,
axes0=False,
grid=False,
ticks=10,
ortho=True,
transparent=False,
default_color=(232, 176, 36),
reset_camera=True,
zoom=1.0,
default_edgecolor=(128, 128, 128),
render_edges=True,
render_normals=False,
render_mates=False,
mate_scale=1.0,
deviation=0.1,
angular_tolerance=0.2,
edge_accuracy=5.0,
ambient_intensity=1.0,
direct_intensity=0.12,
):
root = self.CQ root = self.CQ
ais, shape_display = make_AIS(obj, options) ais, shape_display = make_AIS(obj, options)
root.addChild(ObjectTreeItem(name, root.addChild(
ObjectTreeItem(
name,
shape=obj, shape=obj,
shape_display=shape_display, shape_display=shape_display,
ais=ais, ais=ais,
sig=self.sigObjectPropertiesChanged)) sig=self.sigObjectPropertiesChanged,
)
)
self.sigObjectsAdded.emit([ais]) self.sigObjectsAdded.emit([ais])
@pyqtSlot(list) @pyqtSlot(list)
@pyqtSlot() @pyqtSlot()
def removeObjects(self, objects=None): def removeObjects(self, objects=None):
if objects: if objects:
removed_items_ais = [self.CQ.takeChild(i).ais for i in objects] removed_items_ais = [self.CQ.takeChild(i).ais for i in objects]
else: else:
@@ -301,7 +341,6 @@ class ObjectTree(QWidget,ComponentMixin):
@pyqtSlot(bool) @pyqtSlot(bool)
def stashObjects(self, action: bool): def stashObjects(self, action: bool):
if action: if action:
self._stash = self.CQ.takeChildren() self._stash = self.CQ.takeChildren()
removed_items_ais = [ch.ais for ch in self._stash] removed_items_ais = [ch.ais for ch in self._stash]
@@ -314,14 +353,12 @@ class ObjectTree(QWidget,ComponentMixin):
@pyqtSlot() @pyqtSlot()
def removeSelected(self): def removeSelected(self):
ixs = self.tree.selectedIndexes() ixs = self.tree.selectedIndexes()
rows = [ix.row() for ix in ixs] rows = [ix.row() for ix in ixs]
self.removeObjects(rows) self.removeObjects(rows)
def export(self, export_type, precision=None): def export(self, export_type, precision=None):
items = self.tree.selectedItems() items = self.tree.selectedItems()
# if CQ models is selected get all children # if CQ models is selected get all children
@@ -333,12 +370,11 @@ class ObjectTree(QWidget,ComponentMixin):
shapes = [item.shape for item in items if item.parent() is self.CQ] shapes = [item.shape for item in items if item.parent() is self.CQ]
fname = get_save_filename(export_type) fname = get_save_filename(export_type)
if fname != '': if fname != "":
export(shapes, export_type, fname, precision) export(shapes, export_type, fname, precision)
@pyqtSlot() @pyqtSlot()
def handleSelection(self): def handleSelection(self):
items = self.tree.selectedItems() items = self.tree.selectedItems()
if len(items) == 0: if len(items) == 0:
self._export_STL_action.setEnabled(False) self._export_STL_action.setEnabled(False)
@@ -356,8 +392,7 @@ class ObjectTree(QWidget,ComponentMixin):
self._export_STEP_action.setEnabled(True) self._export_STEP_action.setEnabled(True)
self._clear_current_action.setEnabled(True) self._clear_current_action.setEnabled(True)
self.sigCQObjectSelected.emit(item.shape) self.sigCQObjectSelected.emit(item.shape)
self.properties_editor.setParameters(item.properties, self.properties_editor.setParameters(item.properties, showTop=False)
showTop=False)
self.properties_editor.setEnabled(True) self.properties_editor.setEnabled(True)
elif item is self.CQ and item.childCount() > 0: elif item is self.CQ and item.childCount() > 0:
self._export_STL_action.setEnabled(True) self._export_STL_action.setEnabled(True)
@@ -371,7 +406,6 @@ class ObjectTree(QWidget,ComponentMixin):
@pyqtSlot(list) @pyqtSlot(list)
def handleGraphicalSelection(self, shapes): def handleGraphicalSelection(self, shapes):
self.tree.clearSelection() self.tree.clearSelection()
CQ = self.CQ CQ = self.CQ
@@ -383,9 +417,8 @@ class ObjectTree(QWidget,ComponentMixin):
@pyqtSlot(QTreeWidgetItem, int) @pyqtSlot(QTreeWidgetItem, int)
def handleChecked(self, item, col): def handleChecked(self, item, col):
if type(item) is ObjectTreeItem: if type(item) is ObjectTreeItem:
if item.checkState(0): if item.checkState(0):
item.properties['Visible'] = True item.properties["Visible"] = True
else: else:
item.properties['Visible'] = False item.properties["Visible"] = False