mirror of
https://github.com/jdegenstein/jmwright-CQ-Editor.git
synced 2026-01-01 04:14:21 +01:00
more testing of pyside6
This commit is contained in:
@@ -1,23 +1,23 @@
|
||||
from PySide6.QtWidgets import QApplication
|
||||
from PySide6.QtCore import pyqtSlot
|
||||
from PySide6.QtCore import Slot as pyqtSlot
|
||||
|
||||
from qtconsole.rich_jupyter_widget import RichJupyterWidget
|
||||
from qtconsole.inprocess import QtInProcessKernelManager
|
||||
|
||||
from ..mixins import ComponentMixin
|
||||
|
||||
class ConsoleWidget(RichJupyterWidget,ComponentMixin):
|
||||
|
||||
name = 'Console'
|
||||
|
||||
class ConsoleWidget(RichJupyterWidget, ComponentMixin):
|
||||
name = "Console"
|
||||
|
||||
def __init__(self, customBanner=None, namespace=dict(), *args, **kwargs):
|
||||
super(ConsoleWidget, self).__init__(*args, **kwargs)
|
||||
|
||||
# if not customBanner is None:
|
||||
# self.banner = customBanner
|
||||
# if not customBanner is None:
|
||||
# self.banner = customBanner
|
||||
|
||||
self.font_size = 6
|
||||
self.style_sheet = '''<style>
|
||||
self.style_sheet = """<style>
|
||||
QPlainTextEdit, QTextEdit {
|
||||
background-color: #3f3f3f;
|
||||
background-clip: padding;
|
||||
@@ -34,14 +34,14 @@ class ConsoleWidget(RichJupyterWidget,ComponentMixin):
|
||||
.in-prompt { color: navy; }
|
||||
.out-prompt { color: darkred; }
|
||||
</style>
|
||||
'''
|
||||
self.syntax_style = 'zenburn' #CHANGES FOR DARKMODE
|
||||
|
||||
"""
|
||||
self.syntax_style = "zenburn" # CHANGES FOR DARKMODE
|
||||
|
||||
self.kernel_manager = kernel_manager = QtInProcessKernelManager()
|
||||
kernel_manager.start_kernel(show_banner=False)
|
||||
kernel_manager.kernel.gui = 'qt'
|
||||
kernel_manager.kernel.gui = "qt"
|
||||
kernel_manager.kernel.shell.banner1 = ""
|
||||
|
||||
|
||||
self.kernel_client = kernel_client = self._kernel_manager.client()
|
||||
kernel_client.start_channels()
|
||||
|
||||
@@ -51,9 +51,9 @@ class ConsoleWidget(RichJupyterWidget,ComponentMixin):
|
||||
QApplication.instance().exit()
|
||||
|
||||
self.exit_requested.connect(stop)
|
||||
|
||||
|
||||
self.clear()
|
||||
|
||||
|
||||
self.push_vars(namespace)
|
||||
|
||||
@pyqtSlot(dict)
|
||||
@@ -70,7 +70,6 @@ class ConsoleWidget(RichJupyterWidget,ComponentMixin):
|
||||
"""
|
||||
self._control.clear()
|
||||
|
||||
|
||||
def print_text(self, text):
|
||||
"""
|
||||
Prints some plain text to the console
|
||||
@@ -82,20 +81,17 @@ class ConsoleWidget(RichJupyterWidget,ComponentMixin):
|
||||
Execute a command in the frame of the console widget
|
||||
"""
|
||||
self._execute(command, False)
|
||||
|
||||
def _banner_default(self):
|
||||
|
||||
return ''
|
||||
|
||||
|
||||
def _banner_default(self):
|
||||
return ""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
console = ConsoleWidget(customBanner='IPython console test')
|
||||
|
||||
console = ConsoleWidget(customBanner="IPython console test")
|
||||
console.show()
|
||||
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from PySide6.QtWidgets import QTreeWidget, QTreeWidgetItem, QAction
|
||||
from PySide6.QtCore import Qt, pyqtSlot, pyqtSignal
|
||||
|
||||
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
|
||||
|
||||
@@ -10,63 +10,62 @@ 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)
|
||||
|
||||
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)
|
||||
|
||||
def __init__(self, name, workplane=None, **kwargs):
|
||||
super(CQStackItem, self).__init__([name, ""], **kwargs)
|
||||
|
||||
self.workplane = workplane
|
||||
|
||||
|
||||
class CQObjectInspector(QTreeWidget,ComponentMixin):
|
||||
|
||||
name = 'CQ Object Inspector'
|
||||
|
||||
class CQObjectInspector(QTreeWidget, ComponentMixin):
|
||||
name = "CQ Object Inspector"
|
||||
|
||||
sigRemoveObjects = pyqtSignal(list)
|
||||
sigDisplayObjects = pyqtSignal(list,bool)
|
||||
sigShowPlane = pyqtSignal([bool],[bool,float])
|
||||
sigDisplayObjects = pyqtSignal(list, bool)
|
||||
sigShowPlane = pyqtSignal(bool)
|
||||
sigShowPlane2 = pyqtSignal(bool, float)
|
||||
sigChangePlane = pyqtSignal(gp_Ax3)
|
||||
|
||||
def __init__(self,parent):
|
||||
|
||||
super(CQObjectInspector,self).__init__(parent)
|
||||
|
||||
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.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._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}
|
||||
|
||||
return {"Tools": self._toolbar_actions}
|
||||
|
||||
def toolbarActions(self):
|
||||
|
||||
return self._toolbar_actions
|
||||
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def inspect(self,value):
|
||||
|
||||
def inspect(self, value):
|
||||
if value:
|
||||
self.itemSelectionChanged.connect(self.handleSelection)
|
||||
self.itemSelectionChanged.emit()
|
||||
@@ -74,56 +73,52 @@ class CQObjectInspector(QTreeWidget,ComponentMixin):
|
||||
self.itemSelectionChanged.disconnect(self.handleSelection)
|
||||
self.sigRemoveObjects.emit(self.inspected_items)
|
||||
self.sigShowPlane.emit(False)
|
||||
|
||||
@pyqtSlot()
|
||||
|
||||
@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())
|
||||
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)
|
||||
|
||||
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:
|
||||
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:
|
||||
if hasattr(obj, "wrapped") and type(obj) != Vector:
|
||||
ais = AIS_ColoredShape(obj.wrapped)
|
||||
inspected_items.append(ais)
|
||||
|
||||
self.sigDisplayObjects.emit(inspected_items,False)
|
||||
|
||||
|
||||
self.sigDisplayObjects.emit(inspected_items, False)
|
||||
|
||||
@pyqtSlot(object)
|
||||
def setObject(self,cq_obj):
|
||||
|
||||
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)
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -9,12 +9,13 @@ from PySide6 import QtCore
|
||||
from PySide6.QtCore import (
|
||||
Qt,
|
||||
QObject,
|
||||
pyqtSlot,
|
||||
pyqtSignal,
|
||||
Slot as pyqtSlot,
|
||||
Signal as pyqtSignal,
|
||||
QEventLoop,
|
||||
QAbstractTableModel,
|
||||
)
|
||||
from PySide6.QtWidgets import QAction, QTableView
|
||||
from PySide6.QtWidgets import QTableView
|
||||
from PySide6.QtGui import QAction
|
||||
from logbook import info
|
||||
from path import Path
|
||||
from pyqtgraph.parametertree import Parameter
|
||||
|
||||
@@ -2,9 +2,11 @@ import os
|
||||
from modulefinder import ModuleFinder
|
||||
|
||||
from spyder.plugins.editor.widgets.codeeditor import CodeEditor
|
||||
from PySide6.QtCore import pyqtSignal, QFileSystemWatcher, QTimer
|
||||
from PySide6.QtWidgets import QAction, QFileDialog
|
||||
from PySide6.QtGui import QFontDatabase
|
||||
from PySide6.QtCore import Signal as pyqtSignal
|
||||
from PySide6.QtCore import QFileSystemWatcher, QTimerEvent, QTimer
|
||||
|
||||
from PySide6.QtWidgets import QFileDialog
|
||||
from PySide6.QtGui import QFontDatabase, QAction
|
||||
from path import Path
|
||||
|
||||
import sys
|
||||
@@ -16,91 +18,104 @@ from ..utils import get_save_filename, get_open_filename, confirm
|
||||
|
||||
from ..icons import icon
|
||||
|
||||
class Editor(CodeEditor,ComponentMixin):
|
||||
|
||||
name = 'Code Editor'
|
||||
class Editor(CodeEditor, ComponentMixin):
|
||||
name = "Code Editor"
|
||||
|
||||
# This signal is emitted whenever the currently-open file changes and
|
||||
# autoreload is enabled.
|
||||
triggerRerender = pyqtSignal(bool)
|
||||
sigFilenameChanged = pyqtSignal(str)
|
||||
|
||||
preferences = Parameter.create(name='Preferences',children=[
|
||||
{'name': 'Font size', 'type': 'int', 'value': 12},
|
||||
{'name': 'Autoreload', 'type': 'bool', 'value': False},
|
||||
{'name': 'Autoreload delay', 'type': 'int', 'value': 50},
|
||||
{'name': 'Autoreload: watch imported modules', 'type': 'bool', 'value': False},
|
||||
{'name': 'Line wrap', 'type': 'bool', 'value': False},
|
||||
{'name': 'Color scheme', 'type': 'list',
|
||||
'values': ['Spyder','Monokai','Zenburn'], 'value': 'Spyder'}])
|
||||
preferences = Parameter.create(
|
||||
name="Preferences",
|
||||
children=[
|
||||
{"name": "Font size", "type": "int", "value": 12},
|
||||
{"name": "Autoreload", "type": "bool", "value": False},
|
||||
{"name": "Autoreload delay", "type": "int", "value": 50},
|
||||
{
|
||||
"name": "Autoreload: watch imported modules",
|
||||
"type": "bool",
|
||||
"value": False,
|
||||
},
|
||||
{"name": "Line wrap", "type": "bool", "value": False},
|
||||
{
|
||||
"name": "Color scheme",
|
||||
"type": "list",
|
||||
"values": ["Spyder", "Monokai", "Zenburn"],
|
||||
"value": "Spyder",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
EXTENSIONS = 'py'
|
||||
|
||||
def __init__(self,parent=None):
|
||||
EXTENSIONS = "py"
|
||||
|
||||
def __init__(self, parent=None):
|
||||
self._watched_file = None
|
||||
|
||||
super(Editor,self).__init__(parent)
|
||||
super(Editor, self).__init__(parent)
|
||||
ComponentMixin.__init__(self)
|
||||
|
||||
self.setup_editor(linenumbers=True,
|
||||
markers=True,
|
||||
edge_line=False,
|
||||
tab_mode=False,
|
||||
show_blanks=True,
|
||||
font=QFontDatabase.systemFont(QFontDatabase.FixedFont),
|
||||
language='Python',
|
||||
filename='')
|
||||
self.setup_editor(
|
||||
linenumbers=True,
|
||||
markers=True,
|
||||
edge_line=False,
|
||||
tab_mode=False,
|
||||
show_blanks=True,
|
||||
font=QFontDatabase.systemFont(QFontDatabase.FixedFont),
|
||||
language="Python",
|
||||
filename="",
|
||||
)
|
||||
|
||||
self._actions = \
|
||||
{'File' : [QAction(icon('new'),
|
||||
'New',
|
||||
self,
|
||||
shortcut='ctrl+N',
|
||||
triggered=self.new),
|
||||
QAction(icon('open'),
|
||||
'Open',
|
||||
self,
|
||||
shortcut='ctrl+O',
|
||||
triggered=self.open),
|
||||
QAction(icon('save'),
|
||||
'Save',
|
||||
self,
|
||||
shortcut='ctrl+S',
|
||||
triggered=self.save),
|
||||
QAction(icon('save_as'),
|
||||
'Save as',
|
||||
self,
|
||||
shortcut='ctrl+shift+S',
|
||||
triggered=self.save_as),
|
||||
QAction(icon('autoreload'),
|
||||
'Automatic reload and preview',
|
||||
self,triggered=self.autoreload,
|
||||
checkable=True,
|
||||
checked=False,
|
||||
objectName='autoreload'),
|
||||
]}
|
||||
self._actions = {
|
||||
"File": [
|
||||
QAction(
|
||||
icon("new"), "New", self, shortcut="ctrl+N", triggered=self.new
|
||||
),
|
||||
QAction(
|
||||
icon("open"), "Open", self, shortcut="ctrl+O", triggered=self.open
|
||||
),
|
||||
QAction(
|
||||
icon("save"), "Save", self, shortcut="ctrl+S", triggered=self.save
|
||||
),
|
||||
QAction(
|
||||
icon("save_as"),
|
||||
"Save as",
|
||||
self,
|
||||
shortcut="ctrl+shift+S",
|
||||
triggered=self.save_as,
|
||||
),
|
||||
QAction(
|
||||
icon("autoreload"),
|
||||
"Automatic reload and preview",
|
||||
self,
|
||||
triggered=self.autoreload,
|
||||
checkable=True,
|
||||
checked=False,
|
||||
objectName="autoreload",
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
for a in self._actions.values():
|
||||
self.addActions(a)
|
||||
|
||||
|
||||
self._fixContextMenu()
|
||||
|
||||
# autoreload support
|
||||
self._file_watcher = QFileSystemWatcher(self)
|
||||
# we wait for 50ms after a file change for the file to be written completely
|
||||
self._file_watch_timer = QTimer(self)
|
||||
self._file_watch_timer.setInterval(self.preferences['Autoreload delay'])
|
||||
self._file_watch_timer.setInterval(self.preferences["Autoreload delay"])
|
||||
self._file_watch_timer.setSingleShot(True)
|
||||
self._file_watcher.fileChanged.connect(
|
||||
lambda val: self._file_watch_timer.start())
|
||||
lambda val: self._file_watch_timer.start()
|
||||
)
|
||||
self._file_watch_timer.timeout.connect(self._file_changed)
|
||||
|
||||
self.updatePreferences()
|
||||
|
||||
def _fixContextMenu(self):
|
||||
|
||||
menu = self.menu
|
||||
|
||||
menu.removeAction(self.run_cell_action)
|
||||
@@ -108,68 +123,66 @@ class Editor(CodeEditor,ComponentMixin):
|
||||
menu.removeAction(self.run_selection_action)
|
||||
menu.removeAction(self.re_run_last_cell_action)
|
||||
|
||||
def updatePreferences(self,*args):
|
||||
|
||||
self.set_color_scheme(self.preferences['Color scheme'])
|
||||
def updatePreferences(self, *args):
|
||||
self.set_color_scheme(self.preferences["Color scheme"])
|
||||
|
||||
font = self.font()
|
||||
font.setPointSize(self.preferences['Font size'])
|
||||
font.setPointSize(self.preferences["Font size"])
|
||||
self.set_font(font)
|
||||
|
||||
self.findChild(QAction, 'autoreload') \
|
||||
.setChecked(self.preferences['Autoreload'])
|
||||
self.findChild(QAction, "autoreload").setChecked(self.preferences["Autoreload"])
|
||||
|
||||
self._file_watch_timer.setInterval(self.preferences['Autoreload delay'])
|
||||
self._file_watch_timer.setInterval(self.preferences["Autoreload delay"])
|
||||
|
||||
self.toggle_wrap_mode(self.preferences['Line wrap'])
|
||||
self.toggle_wrap_mode(self.preferences["Line wrap"])
|
||||
|
||||
self._clear_watched_paths()
|
||||
self._watch_paths()
|
||||
|
||||
def confirm_discard(self):
|
||||
|
||||
if self.modified:
|
||||
rv = confirm(self,'Please confirm','Current document is not saved - do you want to continue?')
|
||||
rv = confirm(
|
||||
self,
|
||||
"Please confirm",
|
||||
"Current document is not saved - do you want to continue?",
|
||||
)
|
||||
else:
|
||||
rv = True
|
||||
|
||||
return rv
|
||||
|
||||
def new(self):
|
||||
if not self.confirm_discard():
|
||||
return
|
||||
|
||||
if not self.confirm_discard(): return
|
||||
|
||||
self.set_text('')
|
||||
self.filename = ''
|
||||
self.set_text("")
|
||||
self.filename = ""
|
||||
self.reset_modified()
|
||||
|
||||
def open(self):
|
||||
|
||||
if not self.confirm_discard(): return
|
||||
if not self.confirm_discard():
|
||||
return
|
||||
|
||||
curr_dir = Path(self.filename).abspath().dirname()
|
||||
fname = get_open_filename(self.EXTENSIONS, curr_dir)
|
||||
if fname != '':
|
||||
if fname != "":
|
||||
self.load_from_file(fname)
|
||||
|
||||
def load_from_file(self,fname):
|
||||
|
||||
def load_from_file(self, fname):
|
||||
self.set_text_from_file(fname)
|
||||
self.filename = fname
|
||||
self.reset_modified()
|
||||
|
||||
def save(self):
|
||||
|
||||
if self._filename != '':
|
||||
|
||||
if self.preferences['Autoreload']:
|
||||
if self._filename != "":
|
||||
if self.preferences["Autoreload"]:
|
||||
self._file_watcher.blockSignals(True)
|
||||
self._file_watch_timer.stop()
|
||||
|
||||
with open(self._filename, 'w') as f:
|
||||
with open(self._filename, "w") as f:
|
||||
f.write(self.toPlainText())
|
||||
|
||||
if self.preferences['Autoreload']:
|
||||
if self.preferences["Autoreload"]:
|
||||
self._file_watcher.blockSignals(False)
|
||||
self.triggerRerender.emit(True)
|
||||
|
||||
@@ -179,20 +192,25 @@ class Editor(CodeEditor,ComponentMixin):
|
||||
self.save_as()
|
||||
|
||||
def save_as(self):
|
||||
|
||||
fname = get_save_filename(self.EXTENSIONS)
|
||||
if fname != '':
|
||||
with open(fname,'w') as f:
|
||||
if fname != "":
|
||||
with open(fname, "w") as f:
|
||||
f.write(self.toPlainText())
|
||||
self.filename = fname
|
||||
|
||||
self.reset_modified()
|
||||
|
||||
def _update_filewatcher(self):
|
||||
if self._watched_file and (self._watched_file != self.filename or not self.preferences['Autoreload']):
|
||||
if self._watched_file and (
|
||||
self._watched_file != self.filename or not self.preferences["Autoreload"]
|
||||
):
|
||||
self._clear_watched_paths()
|
||||
self._watched_file = None
|
||||
if self.preferences['Autoreload'] and self.filename and self.filename != self._watched_file:
|
||||
if (
|
||||
self.preferences["Autoreload"]
|
||||
and self.filename
|
||||
and self.filename != self._watched_file
|
||||
):
|
||||
self._watched_file = self._filename
|
||||
self._watch_paths()
|
||||
|
||||
@@ -214,8 +232,8 @@ class Editor(CodeEditor,ComponentMixin):
|
||||
def _watch_paths(self):
|
||||
if Path(self._filename).exists():
|
||||
self._file_watcher.addPath(self._filename)
|
||||
if self.preferences['Autoreload: watch imported modules']:
|
||||
module_paths = self.get_imported_module_paths(self._filename)
|
||||
if self.preferences["Autoreload: watch imported modules"]:
|
||||
module_paths = self.get_imported_module_paths(self._filename)
|
||||
if module_paths:
|
||||
self._file_watcher.addPaths(module_paths)
|
||||
|
||||
@@ -228,51 +246,45 @@ class Editor(CodeEditor,ComponentMixin):
|
||||
|
||||
# Turn autoreload on/off.
|
||||
def autoreload(self, enabled):
|
||||
self.preferences['Autoreload'] = enabled
|
||||
self.preferences["Autoreload"] = enabled
|
||||
self._update_filewatcher()
|
||||
|
||||
def reset_modified(self):
|
||||
|
||||
self.document().setModified(False)
|
||||
|
||||
|
||||
@property
|
||||
def modified(self):
|
||||
|
||||
return self.document().isModified()
|
||||
|
||||
def saveComponentState(self,store):
|
||||
def saveComponentState(self, store):
|
||||
if self.filename != "":
|
||||
store.setValue(self.name + "/state", self.filename)
|
||||
|
||||
if self.filename != '':
|
||||
store.setValue(self.name+'/state',self.filename)
|
||||
def restoreComponentState(self, store):
|
||||
filename = store.value(self.name + "/state")
|
||||
|
||||
def restoreComponentState(self,store):
|
||||
|
||||
filename = store.value(self.name+'/state')
|
||||
|
||||
if filename and self.filename == '':
|
||||
if filename and self.filename == "":
|
||||
try:
|
||||
self.load_from_file(filename)
|
||||
except IOError:
|
||||
self._logger.warning(f'could not open {filename}')
|
||||
|
||||
self._logger.warning(f"could not open {filename}")
|
||||
|
||||
def get_imported_module_paths(self, module_path):
|
||||
|
||||
finder = ModuleFinder([os.path.dirname(module_path)])
|
||||
imported_modules = []
|
||||
|
||||
try:
|
||||
finder.run_script(module_path)
|
||||
except SyntaxError as err:
|
||||
self._logger.warning(f'Syntax error in {module_path}: {err}')
|
||||
self._logger.warning(f"Syntax error in {module_path}: {err}")
|
||||
except Exception as err:
|
||||
self._logger.warning(
|
||||
f'Cannot determine imported modules in {module_path}: {type(err).__name__} {err}'
|
||||
f"Cannot determine imported modules in {module_path}: {type(err).__name__} {err}"
|
||||
)
|
||||
else:
|
||||
for module_name, module in finder.modules.items():
|
||||
if module_name != '__main__':
|
||||
path = getattr(module, '__file__', None)
|
||||
if module_name != "__main__":
|
||||
path = getattr(module, "__file__", None)
|
||||
if path is not None and os.path.isfile(path):
|
||||
imported_modules.append(path)
|
||||
|
||||
@@ -280,7 +292,6 @@ class Editor(CodeEditor,ComponentMixin):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
from PySide6.QtWidgets import (
|
||||
QTreeWidget,
|
||||
QTreeWidgetItem,
|
||||
QAction,
|
||||
QMenu,
|
||||
QWidget,
|
||||
QAbstractItemView,
|
||||
)
|
||||
from PySide6.QtCore import Qt, pyqtSlot, pyqtSignal
|
||||
from PySide6.QtGui import QAction
|
||||
from PySide6.QtCore import Qt, Slot as pyqtSlot, Signal as pyqtSignal
|
||||
from pyqtgraph.parametertree import Parameter, ParameterTree
|
||||
|
||||
from OCP.AIS import AIS_Line
|
||||
@@ -114,7 +114,8 @@ class ObjectTree(QWidget, ComponentMixin):
|
||||
],
|
||||
)
|
||||
|
||||
sigObjectsAdded = pyqtSignal([list], [list, bool])
|
||||
sigObjectsAdded = pyqtSignal(list)
|
||||
sigObjectsAdded2 = pyqtSignal(list, bool)
|
||||
sigObjectsRemoved = pyqtSignal(list)
|
||||
sigCQObjectSelected = pyqtSignal(object)
|
||||
sigAISObjectsSelected = pyqtSignal(list)
|
||||
|
||||
@@ -2,7 +2,7 @@ from sys import platform
|
||||
|
||||
|
||||
from PySide6.QtWidgets import QWidget, QApplication
|
||||
from PySide6.QtCore import pyqtSlot, pyqtSignal, Qt, QEvent
|
||||
from PySide6.QtCore import Slot as pyqtSlot, Signal as pyqtSignal, Qt, QEvent
|
||||
|
||||
import OCP
|
||||
|
||||
@@ -15,161 +15,144 @@ from OCP.Quantity import Quantity_Color, Quantity_TOC_RGB as TOC_RGB
|
||||
|
||||
ZOOM_STEP = 0.9
|
||||
|
||||
|
||||
|
||||
class OCCTWidget(QWidget):
|
||||
|
||||
sigObjectSelected = pyqtSignal(list)
|
||||
|
||||
def __init__(self,parent=None):
|
||||
|
||||
super(OCCTWidget,self).__init__(parent)
|
||||
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(OCCTWidget, self).__init__(parent)
|
||||
|
||||
self.setAttribute(Qt.WA_NativeWindow)
|
||||
self.setAttribute(Qt.WA_PaintOnScreen)
|
||||
self.setAttribute(Qt.WA_NoSystemBackground)
|
||||
|
||||
|
||||
self._initialized = False
|
||||
self._needs_update = False
|
||||
|
||||
#OCCT secific things
|
||||
|
||||
# OCCT secific things
|
||||
self.display_connection = Aspect_DisplayConnection()
|
||||
self.graphics_driver = OpenGl_GraphicDriver(self.display_connection)
|
||||
|
||||
|
||||
self.viewer = V3d_Viewer(self.graphics_driver)
|
||||
self.view = self.viewer.CreateView()
|
||||
self.context = AIS_InteractiveContext(self.viewer)
|
||||
|
||||
#Trihedorn, lights, etc
|
||||
|
||||
# Trihedorn, lights, etc
|
||||
self.prepare_display()
|
||||
|
||||
|
||||
def prepare_display(self):
|
||||
|
||||
view = self.view
|
||||
|
||||
|
||||
params = view.ChangeRenderingParams()
|
||||
params.NbMsaaSamples = 8
|
||||
params.IsAntialiasingEnabled = True
|
||||
|
||||
|
||||
view.TriedronDisplay(
|
||||
Aspect_TypeOfTriedronPosition.Aspect_TOTP_RIGHT_LOWER,
|
||||
Quantity_Color(), 0.1)
|
||||
|
||||
view.ZBufferTriedronSetup(Quantity_Color(*(0.2, 0.0, 0.0), TOC_RGB))
|
||||
Aspect_TypeOfTriedronPosition.Aspect_TOTP_RIGHT_LOWER, Quantity_Color(), 0.1
|
||||
)
|
||||
|
||||
view.ZBufferTriedronSetup(Quantity_Color(*(0.2, 0.0, 0.0), TOC_RGB))
|
||||
|
||||
viewer = self.viewer
|
||||
|
||||
|
||||
viewer.SetDefaultLights()
|
||||
viewer.SetLightOn()
|
||||
|
||||
|
||||
ctx = self.context
|
||||
|
||||
|
||||
ctx.SetDisplayMode(AIS_DisplayMode.AIS_Shaded, True)
|
||||
ctx.DefaultDrawer().SetFaceBoundaryDraw(True)
|
||||
|
||||
|
||||
def wheelEvent(self, event):
|
||||
|
||||
delta = event.angleDelta().y()
|
||||
factor = ZOOM_STEP if delta<0 else 1/ZOOM_STEP
|
||||
|
||||
factor = ZOOM_STEP if delta < 0 else 1 / ZOOM_STEP
|
||||
|
||||
self.view.SetZoom(factor)
|
||||
|
||||
def mousePressEvent(self,event):
|
||||
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
pos = event.pos()
|
||||
|
||||
|
||||
if event.button() == Qt.LeftButton:
|
||||
self.view.StartRotation(pos.x(), pos.y())
|
||||
elif event.button() == Qt.RightButton:
|
||||
self.view.StartZoomAtPoint(pos.x(), pos.y())
|
||||
|
||||
|
||||
self.old_pos = pos
|
||||
|
||||
def mouseMoveEvent(self,event):
|
||||
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
pos = event.pos()
|
||||
x,y = pos.x(),pos.y()
|
||||
|
||||
x, y = pos.x(), pos.y()
|
||||
|
||||
if event.buttons() == Qt.LeftButton:
|
||||
self.view.Rotation(x,y)
|
||||
|
||||
self.view.Rotation(x, y)
|
||||
|
||||
elif event.buttons() == Qt.MiddleButton:
|
||||
self.view.Pan(x - self.old_pos.x(),
|
||||
self.old_pos.y() - y, theToStart=True)
|
||||
|
||||
self.view.Pan(x - self.old_pos.x(), self.old_pos.y() - y, theToStart=True)
|
||||
|
||||
elif event.buttons() == Qt.RightButton:
|
||||
self.view.Pan(x - self.old_pos.x(),
|
||||
self.old_pos.y() - y, theToStart=True)
|
||||
|
||||
self.view.Pan(x - self.old_pos.x(), self.old_pos.y() - y, theToStart=True)
|
||||
|
||||
self.old_pos = pos
|
||||
|
||||
def mouseReleaseEvent(self,event):
|
||||
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() == Qt.LeftButton:
|
||||
pos = event.pos()
|
||||
x,y = pos.x(),pos.y()
|
||||
|
||||
self.context.MoveTo(x,y,self.view,True)
|
||||
|
||||
x, y = pos.x(), pos.y()
|
||||
|
||||
self.context.MoveTo(x, y, self.view, True)
|
||||
|
||||
self._handle_selection()
|
||||
|
||||
|
||||
def _handle_selection(self):
|
||||
|
||||
self.context.Select(True)
|
||||
self.context.InitSelected()
|
||||
|
||||
|
||||
selected = []
|
||||
if self.context.HasSelectedShape():
|
||||
selected.append(self.context.SelectedShape())
|
||||
|
||||
|
||||
self.sigObjectSelected.emit(selected)
|
||||
|
||||
def paintEngine(self):
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def paintEvent(self, event):
|
||||
|
||||
if not self._initialized:
|
||||
self._initialize()
|
||||
else:
|
||||
self.view.Redraw()
|
||||
|
||||
def showEvent(self, event):
|
||||
|
||||
super(OCCTWidget,self).showEvent(event)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
|
||||
super(OCCTWidget,self).resizeEvent(event)
|
||||
|
||||
self.view.MustBeResized()
|
||||
|
||||
def _initialize(self):
|
||||
super(OCCTWidget, self).showEvent(event)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(OCCTWidget, self).resizeEvent(event)
|
||||
|
||||
self.view.MustBeResized()
|
||||
|
||||
def _initialize(self):
|
||||
wins = {
|
||||
'darwin' : self._get_window_osx,
|
||||
'linux' : self._get_window_linux,
|
||||
'win32': self._get_window_win
|
||||
"darwin": self._get_window_osx,
|
||||
"linux": self._get_window_linux,
|
||||
"win32": self._get_window_win,
|
||||
}
|
||||
|
||||
self.view.SetWindow(wins.get(platform,self._get_window_linux)(self.winId()))
|
||||
self.view.SetWindow(wins.get(platform, self._get_window_linux)(self.winId()))
|
||||
|
||||
self._initialized = True
|
||||
|
||||
def _get_window_win(self,wid):
|
||||
|
||||
|
||||
def _get_window_win(self, wid):
|
||||
from OCP.WNT import WNT_Window
|
||||
|
||||
|
||||
print(wid)
|
||||
return WNT_Window(wid.ascapsule())
|
||||
|
||||
def _get_window_linux(self,wid):
|
||||
|
||||
def _get_window_linux(self, wid):
|
||||
from OCP.Xw import Xw_Window
|
||||
|
||||
return Xw_Window(self.display_connection,int(wid))
|
||||
|
||||
def _get_window_osx(self,wid):
|
||||
|
||||
|
||||
return Xw_Window(self.display_connection, int(wid))
|
||||
|
||||
def _get_window_osx(self, wid):
|
||||
from OCP.Cocoa import Cocoa_Window
|
||||
|
||||
|
||||
return Cocoa_Window(wid.ascapsule())
|
||||
|
||||
@@ -1,97 +1,89 @@
|
||||
from traceback import extract_tb, format_exception_only
|
||||
|
||||
from PySide6.QtWidgets import (QWidget, QTreeWidget, QTreeWidgetItem, QAction,
|
||||
QLabel)
|
||||
from PySide6.QtCore import Qt, pyqtSlot, pyqtSignal
|
||||
from PySide6.QtWidgets import QWidget, QTreeWidget, QTreeWidgetItem, QLabel
|
||||
from PySide6.QtGui import QAction
|
||||
from PySide6.QtCore import Qt, Slot as pyqtSlot, Signal as pyqtSignal
|
||||
|
||||
from ..mixins import ComponentMixin
|
||||
from ..utils import layout
|
||||
|
||||
class TracebackTree(QTreeWidget):
|
||||
|
||||
name = 'Traceback Viewer'
|
||||
|
||||
def __init__(self,parent):
|
||||
|
||||
super(TracebackTree,self).__init__(parent)
|
||||
class TracebackTree(QTreeWidget):
|
||||
name = "Traceback Viewer"
|
||||
|
||||
def __init__(self, parent):
|
||||
super(TracebackTree, self).__init__(parent)
|
||||
self.setHeaderHidden(False)
|
||||
self.setItemsExpandable(False)
|
||||
self.setRootIsDecorated(False)
|
||||
self.setContextMenuPolicy(Qt.ActionsContextMenu)
|
||||
|
||||
|
||||
self.setColumnCount(3)
|
||||
self.setHeaderLabels(['File','Line','Code'])
|
||||
|
||||
|
||||
self.setHeaderLabels(["File", "Line", "Code"])
|
||||
|
||||
self.root = self.invisibleRootItem()
|
||||
|
||||
class TracebackPane(QWidget,ComponentMixin):
|
||||
|
||||
|
||||
class TracebackPane(QWidget, ComponentMixin):
|
||||
sigHighlightLine = pyqtSignal(int)
|
||||
|
||||
def __init__(self,parent):
|
||||
|
||||
super(TracebackPane,self).__init__(parent)
|
||||
|
||||
|
||||
def __init__(self, parent):
|
||||
super(TracebackPane, self).__init__(parent)
|
||||
|
||||
self.tree = TracebackTree(self)
|
||||
self.current_exception = QLabel(self)
|
||||
self.current_exception.setStyleSheet(\
|
||||
"QLabel {color : red; }");
|
||||
|
||||
layout(self,
|
||||
(self.current_exception,
|
||||
self.tree),
|
||||
self)
|
||||
|
||||
self.current_exception.setStyleSheet("QLabel {color : red; }")
|
||||
|
||||
layout(self, (self.current_exception, self.tree), self)
|
||||
|
||||
self.tree.currentItemChanged.connect(self.handleSelection)
|
||||
|
||||
@pyqtSlot(object,str)
|
||||
def addTraceback(self,exc_info,code):
|
||||
|
||||
|
||||
@pyqtSlot(object, str)
|
||||
def addTraceback(self, exc_info, code):
|
||||
self.tree.clear()
|
||||
|
||||
|
||||
if exc_info:
|
||||
t,exc,tb = exc_info
|
||||
|
||||
t, exc, tb = exc_info
|
||||
|
||||
root = self.tree.root
|
||||
code = code.splitlines()
|
||||
tb = [t for t in extract_tb(tb) if '<string>' in t.filename] #ignore highest frames (debug, exec)
|
||||
|
||||
tb = [
|
||||
t for t in extract_tb(tb) if "<string>" in t.filename
|
||||
] # ignore highest frames (debug, exec)
|
||||
|
||||
for el in tb:
|
||||
#workaround of the traceback module
|
||||
if el.line == '':
|
||||
line = code[el.lineno-1].strip()
|
||||
# workaround of the traceback module
|
||||
if el.line == "":
|
||||
line = code[el.lineno - 1].strip()
|
||||
else:
|
||||
line = el.line
|
||||
|
||||
root.addChild(QTreeWidgetItem([el.filename,
|
||||
str(el.lineno),
|
||||
line]))
|
||||
|
||||
root.addChild(QTreeWidgetItem([el.filename, str(el.lineno), line]))
|
||||
|
||||
exc_name = t.__name__
|
||||
exc_msg = str(exc)
|
||||
exc_msg = exc_msg.replace('<', '<').replace('>', '>') #replace <>
|
||||
exc_msg = exc_msg.replace("<", "<").replace(">", ">") # replace <>
|
||||
|
||||
self.current_exception.setText("<b>{}</b>: {}".format(exc_name, exc_msg))
|
||||
|
||||
self.current_exception.\
|
||||
setText('<b>{}</b>: {}'.format(exc_name,exc_msg))
|
||||
|
||||
# handle the special case of a SyntaxError
|
||||
if t is SyntaxError:
|
||||
root.addChild(QTreeWidgetItem(
|
||||
[exc.filename,
|
||||
str(exc.lineno),
|
||||
exc.text.strip() if exc.text else '']
|
||||
))
|
||||
if t is SyntaxError:
|
||||
root.addChild(
|
||||
QTreeWidgetItem(
|
||||
[
|
||||
exc.filename,
|
||||
str(exc.lineno),
|
||||
exc.text.strip() if exc.text else "",
|
||||
]
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.current_exception.setText('')
|
||||
self.current_exception.setText("")
|
||||
|
||||
@pyqtSlot(QTreeWidgetItem,QTreeWidgetItem)
|
||||
def handleSelection(self,item,*args):
|
||||
|
||||
@pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
|
||||
def handleSelection(self, item, *args):
|
||||
if item:
|
||||
f,line = item.data(0,0),int(item.data(1,0))
|
||||
|
||||
if '<string>' in f:
|
||||
f, line = item.data(0, 0), int(item.data(1, 0))
|
||||
|
||||
if "<string>" in f:
|
||||
self.sigHighlightLine.emit(line)
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
from PySide6.QtWidgets import QWidget, QDialog, QTreeWidgetItem, QApplication, QAction
|
||||
from PySide6.QtWidgets import QWidget, QDialog, QTreeWidgetItem, QApplication
|
||||
|
||||
from PySide6.QtCore import pyqtSlot, pyqtSignal
|
||||
from PySide6.QtGui import QIcon
|
||||
from PySide6.QtCore import Slot as pyqtSlot, Signal as pyqtSignal
|
||||
from PySide6.QtGui import QIcon, QAction
|
||||
|
||||
from OCP.Graphic3d import Graphic3d_Camera, Graphic3d_StereoMode, Graphic3d_NOM_JADE,\
|
||||
Graphic3d_MaterialAspect
|
||||
from OCP.AIS import AIS_Shaded,AIS_WireFrame, AIS_ColoredShape, AIS_Axis
|
||||
from OCP.Graphic3d import (
|
||||
Graphic3d_Camera,
|
||||
Graphic3d_StereoMode,
|
||||
Graphic3d_NOM_JADE,
|
||||
Graphic3d_MaterialAspect,
|
||||
)
|
||||
from OCP.AIS import AIS_Shaded, AIS_WireFrame, AIS_ColoredShape, AIS_Axis
|
||||
from OCP.Aspect import Aspect_GDM_Lines, Aspect_GT_Rectangular
|
||||
from OCP.Quantity import Quantity_NOC_BLACK as BLACK, Quantity_TOC_RGB as TOC_RGB,\
|
||||
Quantity_Color
|
||||
from OCP.Quantity import (
|
||||
Quantity_NOC_BLACK as BLACK,
|
||||
Quantity_TOC_RGB as TOC_RGB,
|
||||
Quantity_Color,
|
||||
)
|
||||
from OCP.Geom import Geom_Axis1Placement
|
||||
from OCP.gp import gp_Ax3, gp_Dir, gp_Pnt, gp_Ax1
|
||||
|
||||
@@ -25,30 +32,66 @@ import qtawesome as qta
|
||||
DEFAULT_EDGE_COLOR = Quantity_Color(BLACK)
|
||||
DEFAULT_EDGE_WIDTH = 2
|
||||
|
||||
class OCCViewer(QWidget,ComponentMixin):
|
||||
|
||||
name = '3D Viewer'
|
||||
class OCCViewer(QWidget, ComponentMixin):
|
||||
name = "3D Viewer"
|
||||
|
||||
preferences = Parameter.create(name='Pref',children=[
|
||||
{'name': 'Fit automatically', 'type': 'bool', 'value': True},
|
||||
{'name': 'Use gradient', 'type': 'bool', 'value': False},
|
||||
{'name': 'Background color', 'type': 'color', 'value': (95,95,95)},
|
||||
{'name': 'Background color (aux)', 'type': 'color', 'value': (30,30,30)},
|
||||
{'name': 'Default object color', 'type': 'color', 'value': "#FF0"},
|
||||
{'name': 'Deviation', 'type': 'float', 'value': 1e-5, 'dec': True, 'step': 1},
|
||||
{'name': 'Angular deviation', 'type': 'float', 'value': 0.1, 'dec': True, 'step': 1},
|
||||
{'name': 'Projection Type', 'type': 'list', 'value': 'Orthographic',
|
||||
'values': ['Orthographic', 'Perspective', 'Stereo', 'MonoLeftEye', 'MonoRightEye']},
|
||||
{'name': 'Stereo Mode', 'type': 'list', 'value': 'QuadBuffer',
|
||||
'values': ['QuadBuffer', 'Anaglyph', 'RowInterlaced', 'ColumnInterlaced',
|
||||
'ChessBoard', 'SideBySide', 'OverUnder']}])
|
||||
IMAGE_EXTENSIONS = 'png'
|
||||
preferences = Parameter.create(
|
||||
name="Pref",
|
||||
children=[
|
||||
{"name": "Fit automatically", "type": "bool", "value": True},
|
||||
{"name": "Use gradient", "type": "bool", "value": False},
|
||||
{"name": "Background color", "type": "color", "value": (95, 95, 95)},
|
||||
{"name": "Background color (aux)", "type": "color", "value": (30, 30, 30)},
|
||||
{"name": "Default object color", "type": "color", "value": "#FF0"},
|
||||
{
|
||||
"name": "Deviation",
|
||||
"type": "float",
|
||||
"value": 1e-5,
|
||||
"dec": True,
|
||||
"step": 1,
|
||||
},
|
||||
{
|
||||
"name": "Angular deviation",
|
||||
"type": "float",
|
||||
"value": 0.1,
|
||||
"dec": True,
|
||||
"step": 1,
|
||||
},
|
||||
{
|
||||
"name": "Projection Type",
|
||||
"type": "list",
|
||||
"value": "Orthographic",
|
||||
"values": [
|
||||
"Orthographic",
|
||||
"Perspective",
|
||||
"Stereo",
|
||||
"MonoLeftEye",
|
||||
"MonoRightEye",
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stereo Mode",
|
||||
"type": "list",
|
||||
"value": "QuadBuffer",
|
||||
"values": [
|
||||
"QuadBuffer",
|
||||
"Anaglyph",
|
||||
"RowInterlaced",
|
||||
"ColumnInterlaced",
|
||||
"ChessBoard",
|
||||
"SideBySide",
|
||||
"OverUnder",
|
||||
],
|
||||
},
|
||||
],
|
||||
)
|
||||
IMAGE_EXTENSIONS = "png"
|
||||
|
||||
sigObjectSelected = pyqtSignal(list)
|
||||
|
||||
def __init__(self,parent=None):
|
||||
|
||||
super(OCCViewer,self).__init__(parent)
|
||||
def __init__(self, parent=None):
|
||||
super(OCCViewer, self).__init__(parent)
|
||||
ComponentMixin.__init__(self)
|
||||
|
||||
self.canvas = OCCTWidget()
|
||||
@@ -56,15 +99,18 @@ class OCCViewer(QWidget,ComponentMixin):
|
||||
|
||||
self.create_actions(self)
|
||||
|
||||
self.layout_ = layout(self,
|
||||
[self.canvas,],
|
||||
top_widget=self,
|
||||
margin=0)
|
||||
self.setup_default_drawer() #misspelled in original
|
||||
self.layout_ = layout(
|
||||
self,
|
||||
[
|
||||
self.canvas,
|
||||
],
|
||||
top_widget=self,
|
||||
margin=0,
|
||||
)
|
||||
self.setup_default_drawer() # misspelled in original
|
||||
self.updatePreferences()
|
||||
|
||||
def setup_default_drawer(self):
|
||||
|
||||
def setup_default_drawer(self):
|
||||
# set the default color and material
|
||||
material = Graphic3d_MaterialAspect(Graphic3d_NOM_JADE)
|
||||
|
||||
@@ -76,99 +122,129 @@ class OCCViewer(QWidget,ComponentMixin):
|
||||
line_aspect = self.canvas.context.DefaultDrawer().FaceBoundaryAspect()
|
||||
line_aspect.SetWidth(DEFAULT_EDGE_WIDTH)
|
||||
line_aspect.SetColor(DEFAULT_EDGE_COLOR)
|
||||
|
||||
def updatePreferences(self,*args):
|
||||
|
||||
color1 = to_occ_color(self.preferences['Background color'])
|
||||
color2 = to_occ_color(self.preferences['Background color (aux)'])
|
||||
def updatePreferences(self, *args):
|
||||
color1 = to_occ_color(self.preferences["Background color"])
|
||||
color2 = to_occ_color(self.preferences["Background color (aux)"])
|
||||
|
||||
if not self.preferences['Use gradient']:
|
||||
if not self.preferences["Use gradient"]:
|
||||
color2 = color1
|
||||
self.canvas.view.SetBgGradientColors(color1,color2,theToUpdate=True)
|
||||
|
||||
self.canvas.view.SetBgGradientColors(color1, color2, theToUpdate=True)
|
||||
|
||||
self.canvas.update()
|
||||
|
||||
|
||||
ctx = self.canvas.context
|
||||
ctx.SetDeviationCoefficient(self.preferences['Deviation'])
|
||||
ctx.SetDeviationAngle(self.preferences['Angular deviation'])
|
||||
ctx.SetDeviationCoefficient(self.preferences["Deviation"])
|
||||
ctx.SetDeviationAngle(self.preferences["Angular deviation"])
|
||||
|
||||
v = self._get_view()
|
||||
camera = v.Camera()
|
||||
projection_type = self.preferences['Projection Type']
|
||||
camera.SetProjectionType(getattr(Graphic3d_Camera, f'Projection_{projection_type}',
|
||||
Graphic3d_Camera.Projection_Orthographic))
|
||||
projection_type = self.preferences["Projection Type"]
|
||||
camera.SetProjectionType(
|
||||
getattr(
|
||||
Graphic3d_Camera,
|
||||
f"Projection_{projection_type}",
|
||||
Graphic3d_Camera.Projection_Orthographic,
|
||||
)
|
||||
)
|
||||
|
||||
# onle relevant for stereo projection
|
||||
stereo_mode = self.preferences['Stereo Mode']
|
||||
stereo_mode = self.preferences["Stereo Mode"]
|
||||
params = v.ChangeRenderingParams()
|
||||
params.StereoMode = getattr(Graphic3d_StereoMode, f'Graphic3d_StereoMode_{stereo_mode}',
|
||||
Graphic3d_StereoMode.Graphic3d_StereoMode_QuadBuffer)
|
||||
params.StereoMode = getattr(
|
||||
Graphic3d_StereoMode,
|
||||
f"Graphic3d_StereoMode_{stereo_mode}",
|
||||
Graphic3d_StereoMode.Graphic3d_StereoMode_QuadBuffer,
|
||||
)
|
||||
|
||||
def create_actions(self,parent):
|
||||
|
||||
self._actions = \
|
||||
{'View' : [QAction(qta.icon('fa.arrows-alt'),
|
||||
'Fit (Shift+F1)',
|
||||
parent,
|
||||
shortcut='shift+F1',
|
||||
triggered=self.fit),
|
||||
QAction(QIcon(':/images/icons/isometric_view.svg'),
|
||||
'Iso (Shift+F2)',
|
||||
parent,
|
||||
shortcut='shift+F2',
|
||||
triggered=self.iso_view),
|
||||
QAction(QIcon(':/images/icons/top_view.svg'),
|
||||
'Top (Shift+F3)',
|
||||
parent,
|
||||
shortcut='shift+F3',
|
||||
triggered=self.top_view),
|
||||
QAction(QIcon(':/images/icons/bottom_view.svg'),
|
||||
'Bottom (Shift+F4)',
|
||||
parent,
|
||||
shortcut='shift+F4',
|
||||
triggered=self.bottom_view),
|
||||
QAction(QIcon(':/images/icons/front_view.svg'),
|
||||
'Front (Shift+F5)',
|
||||
parent,
|
||||
shortcut='shift+F5',
|
||||
triggered=self.front_view),
|
||||
QAction(QIcon(':/images/icons/back_view.svg'),
|
||||
'Back (Shift+F6)',
|
||||
parent,
|
||||
shortcut='shift+F6',
|
||||
triggered=self.back_view),
|
||||
QAction(QIcon(':/images/icons/left_side_view.svg'),
|
||||
'Left (Shift+F7)',
|
||||
parent,
|
||||
shortcut='shift+F7',
|
||||
triggered=self.left_view),
|
||||
QAction(QIcon(':/images/icons/right_side_view.svg'),
|
||||
'Right (Shift+F8)',
|
||||
parent,
|
||||
shortcut='shift+F8',
|
||||
triggered=self.right_view),
|
||||
QAction(qta.icon('fa.square-o'),
|
||||
'Wireframe (Shift+F9)',
|
||||
parent,
|
||||
shortcut='shift+F9',
|
||||
triggered=self.wireframe_view),
|
||||
QAction(qta.icon('fa.square'),
|
||||
'Shaded (Shift+F10)',
|
||||
parent,
|
||||
shortcut='shift+F10',
|
||||
triggered=self.shaded_view)],
|
||||
'Tools' : [QAction(icon('screenshot'),
|
||||
'Screenshot',
|
||||
parent,
|
||||
triggered=self.save_screenshot)]}
|
||||
def create_actions(self, parent):
|
||||
self._actions = {
|
||||
"View": [
|
||||
QAction(
|
||||
qta.icon("fa.arrows-alt"),
|
||||
"Fit (Shift+F1)",
|
||||
parent,
|
||||
shortcut="shift+F1",
|
||||
triggered=self.fit,
|
||||
),
|
||||
QAction(
|
||||
QIcon(":/images/icons/isometric_view.svg"),
|
||||
"Iso (Shift+F2)",
|
||||
parent,
|
||||
shortcut="shift+F2",
|
||||
triggered=self.iso_view,
|
||||
),
|
||||
QAction(
|
||||
QIcon(":/images/icons/top_view.svg"),
|
||||
"Top (Shift+F3)",
|
||||
parent,
|
||||
shortcut="shift+F3",
|
||||
triggered=self.top_view,
|
||||
),
|
||||
QAction(
|
||||
QIcon(":/images/icons/bottom_view.svg"),
|
||||
"Bottom (Shift+F4)",
|
||||
parent,
|
||||
shortcut="shift+F4",
|
||||
triggered=self.bottom_view,
|
||||
),
|
||||
QAction(
|
||||
QIcon(":/images/icons/front_view.svg"),
|
||||
"Front (Shift+F5)",
|
||||
parent,
|
||||
shortcut="shift+F5",
|
||||
triggered=self.front_view,
|
||||
),
|
||||
QAction(
|
||||
QIcon(":/images/icons/back_view.svg"),
|
||||
"Back (Shift+F6)",
|
||||
parent,
|
||||
shortcut="shift+F6",
|
||||
triggered=self.back_view,
|
||||
),
|
||||
QAction(
|
||||
QIcon(":/images/icons/left_side_view.svg"),
|
||||
"Left (Shift+F7)",
|
||||
parent,
|
||||
shortcut="shift+F7",
|
||||
triggered=self.left_view,
|
||||
),
|
||||
QAction(
|
||||
QIcon(":/images/icons/right_side_view.svg"),
|
||||
"Right (Shift+F8)",
|
||||
parent,
|
||||
shortcut="shift+F8",
|
||||
triggered=self.right_view,
|
||||
),
|
||||
QAction(
|
||||
qta.icon("fa.square-o"),
|
||||
"Wireframe (Shift+F9)",
|
||||
parent,
|
||||
shortcut="shift+F9",
|
||||
triggered=self.wireframe_view,
|
||||
),
|
||||
QAction(
|
||||
qta.icon("fa.square"),
|
||||
"Shaded (Shift+F10)",
|
||||
parent,
|
||||
shortcut="shift+F10",
|
||||
triggered=self.shaded_view,
|
||||
),
|
||||
],
|
||||
"Tools": [
|
||||
QAction(
|
||||
icon("screenshot"),
|
||||
"Screenshot",
|
||||
parent,
|
||||
triggered=self.save_screenshot,
|
||||
)
|
||||
],
|
||||
}
|
||||
|
||||
def toolbarActions(self):
|
||||
|
||||
return self._actions['View']
|
||||
|
||||
return self._actions["View"]
|
||||
|
||||
def clear(self):
|
||||
|
||||
self.displayed_shapes = []
|
||||
self.displayed_ais = []
|
||||
self.canvas.context.EraseAll(True)
|
||||
@@ -176,199 +252,167 @@ class OCCViewer(QWidget,ComponentMixin):
|
||||
context.PurgeDisplay()
|
||||
context.RemoveAll(True)
|
||||
|
||||
def _display(self,shape):
|
||||
|
||||
def _display(self, shape):
|
||||
ais = make_AIS(shape)
|
||||
self.canvas.context.Display(shape,True)
|
||||
self.canvas.context.Display(shape, True)
|
||||
|
||||
self.displayed_shapes.append(shape)
|
||||
self.displayed_ais.append(ais)
|
||||
|
||||
#self.canvas._display.Repaint()
|
||||
# self.canvas._display.Repaint()
|
||||
|
||||
@pyqtSlot(object)
|
||||
def display(self,ais):
|
||||
|
||||
def display(self, ais):
|
||||
context = self._get_context()
|
||||
context.Display(ais,True)
|
||||
context.Display(ais, True)
|
||||
|
||||
if self.preferences['Fit automatically']: self.fit()
|
||||
if self.preferences["Fit automatically"]:
|
||||
self.fit()
|
||||
|
||||
@pyqtSlot(list)
|
||||
@pyqtSlot(list,bool)
|
||||
def display_many(self,ais_list,fit=None):
|
||||
|
||||
@pyqtSlot(list, bool)
|
||||
def display_many(self, ais_list, fit=None):
|
||||
context = self._get_context()
|
||||
for ais in ais_list:
|
||||
context.Display(ais,True)
|
||||
context.Display(ais, True)
|
||||
|
||||
if self.preferences['Fit automatically'] and fit is None:
|
||||
if self.preferences["Fit automatically"] and fit is None:
|
||||
self.fit()
|
||||
elif fit:
|
||||
self.fit()
|
||||
|
||||
@pyqtSlot(QTreeWidgetItem,int)
|
||||
def update_item(self,item,col):
|
||||
|
||||
@pyqtSlot(QTreeWidgetItem, int)
|
||||
def update_item(self, item, col):
|
||||
ctx = self._get_context()
|
||||
if item.checkState(0):
|
||||
ctx.Display(item.ais,True)
|
||||
ctx.Display(item.ais, True)
|
||||
else:
|
||||
ctx.Erase(item.ais,True)
|
||||
ctx.Erase(item.ais, True)
|
||||
|
||||
@pyqtSlot(list)
|
||||
def remove_items(self,ais_items):
|
||||
|
||||
def remove_items(self, ais_items):
|
||||
ctx = self._get_context()
|
||||
for ais in ais_items: ctx.Erase(ais,True)
|
||||
for ais in ais_items:
|
||||
ctx.Erase(ais, True)
|
||||
|
||||
@pyqtSlot()
|
||||
def redraw(self):
|
||||
|
||||
self._get_viewer().Redraw()
|
||||
|
||||
def fit(self):
|
||||
|
||||
self.canvas.view.FitAll()
|
||||
|
||||
def iso_view(self):
|
||||
|
||||
v = self._get_view()
|
||||
v.SetProj(1,-1,1)
|
||||
v.SetProj(1, -1, 1)
|
||||
v.SetTwist(0)
|
||||
|
||||
def bottom_view(self):
|
||||
|
||||
v = self._get_view()
|
||||
v.SetProj(0,0,-1)
|
||||
v.SetProj(0, 0, -1)
|
||||
v.SetTwist(0)
|
||||
|
||||
def top_view(self):
|
||||
|
||||
v = self._get_view()
|
||||
v.SetProj(0,0,1)
|
||||
v.SetProj(0, 0, 1)
|
||||
v.SetTwist(0)
|
||||
|
||||
def front_view(self):
|
||||
|
||||
v = self._get_view()
|
||||
v.SetProj(0,-1,0)
|
||||
v.SetProj(0, -1, 0)
|
||||
v.SetTwist(0)
|
||||
|
||||
def back_view(self):
|
||||
|
||||
v = self._get_view()
|
||||
v.SetProj(0,1,0)
|
||||
v.SetProj(0, 1, 0)
|
||||
v.SetTwist(0)
|
||||
|
||||
def left_view(self):
|
||||
|
||||
v = self._get_view()
|
||||
v.SetProj(-1,0,0)
|
||||
v.SetProj(-1, 0, 0)
|
||||
v.SetTwist(0)
|
||||
|
||||
def right_view(self):
|
||||
|
||||
v = self._get_view()
|
||||
v.SetProj(1,0,0)
|
||||
v.SetProj(1, 0, 0)
|
||||
v.SetTwist(0)
|
||||
|
||||
def shaded_view(self):
|
||||
|
||||
c = self._get_context()
|
||||
c.SetDisplayMode(AIS_Shaded, True)
|
||||
|
||||
def wireframe_view(self):
|
||||
|
||||
c = self._get_context()
|
||||
c.SetDisplayMode(AIS_WireFrame, True)
|
||||
|
||||
def show_grid(self,
|
||||
step=1.,
|
||||
size=10.+1e-6,
|
||||
color1=(.7,.7,.7),
|
||||
color2=(0,0,0)):
|
||||
|
||||
def show_grid(
|
||||
self, step=1.0, size=10.0 + 1e-6, color1=(0.7, 0.7, 0.7), color2=(0, 0, 0)
|
||||
):
|
||||
viewer = self._get_viewer()
|
||||
viewer.ActivateGrid(Aspect_GT_Rectangular,
|
||||
Aspect_GDM_Lines)
|
||||
viewer.ActivateGrid(Aspect_GT_Rectangular, Aspect_GDM_Lines)
|
||||
viewer.SetRectangularGridGraphicValues(size, size, 0)
|
||||
viewer.SetRectangularGridValues(0, 0, step, step, 0)
|
||||
grid = viewer.Grid()
|
||||
grid.SetColors(Quantity_Color(*color1,TOC_RGB),
|
||||
Quantity_Color(*color2,TOC_RGB))
|
||||
grid.SetColors(
|
||||
Quantity_Color(*color1, TOC_RGB), Quantity_Color(*color2, TOC_RGB)
|
||||
)
|
||||
|
||||
def hide_grid(self):
|
||||
|
||||
viewer = self._get_viewer()
|
||||
viewer.DeactivateGrid()
|
||||
|
||||
@pyqtSlot(bool,float)
|
||||
@pyqtSlot(bool, float)
|
||||
@pyqtSlot(bool)
|
||||
def toggle_grid(self,
|
||||
value : bool,
|
||||
dim : float = 10.):
|
||||
|
||||
def toggle_grid(self, value: bool, dim: float = 10.0):
|
||||
if value:
|
||||
self.show_grid(step=dim/20,size=dim+1e-9)
|
||||
self.show_grid(step=dim / 20, size=dim + 1e-9)
|
||||
else:
|
||||
self.hide_grid()
|
||||
|
||||
@pyqtSlot(gp_Ax3)
|
||||
def set_grid_orientation(self,orientation : gp_Ax3):
|
||||
|
||||
def set_grid_orientation(self, orientation: gp_Ax3):
|
||||
viewer = self._get_viewer()
|
||||
viewer.SetPrivilegedPlane(orientation)
|
||||
|
||||
def show_axis(self,origin = (0,0,0), direction=(0,0,1)):
|
||||
|
||||
ax_placement = Geom_Axis1Placement(gp_Ax1(gp_Pnt(*origin),
|
||||
gp_Dir(*direction)))
|
||||
def show_axis(self, origin=(0, 0, 0), direction=(0, 0, 1)):
|
||||
ax_placement = Geom_Axis1Placement(gp_Ax1(gp_Pnt(*origin), gp_Dir(*direction)))
|
||||
ax = AIS_Axis(ax_placement)
|
||||
self._display_ais(ax)
|
||||
|
||||
def save_screenshot(self):
|
||||
|
||||
fname = get_save_filename(self.IMAGE_EXTENSIONS)
|
||||
if fname != '':
|
||||
self._get_view().Dump(fname)
|
||||
|
||||
def _display_ais(self,ais):
|
||||
if fname != "":
|
||||
self._get_view().Dump(fname)
|
||||
|
||||
def _display_ais(self, ais):
|
||||
self._get_context().Display(ais)
|
||||
|
||||
|
||||
def _get_view(self):
|
||||
|
||||
return self.canvas.view
|
||||
|
||||
def _get_viewer(self):
|
||||
|
||||
return self.canvas.viewer
|
||||
|
||||
def _get_context(self):
|
||||
|
||||
return self.canvas.context
|
||||
|
||||
@pyqtSlot(list)
|
||||
def handle_selection(self,obj):
|
||||
|
||||
def handle_selection(self, obj):
|
||||
self.sigObjectSelected.emit(obj)
|
||||
|
||||
@pyqtSlot(list)
|
||||
def set_selected(self,ais):
|
||||
|
||||
def set_selected(self, ais):
|
||||
ctx = self._get_context()
|
||||
ctx.ClearSelected(False)
|
||||
|
||||
for obj in ais:
|
||||
ctx.AddOrRemoveSelected(obj,False)
|
||||
ctx.AddOrRemoveSelected(obj, False)
|
||||
|
||||
self.redraw()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# pass
|
||||
import sys
|
||||
from OCP.BRepPrimAPI import BRepPrimAPI_MakeBox
|
||||
|
||||
@@ -379,10 +423,10 @@ if __name__ == "__main__":
|
||||
dlg.setFixedHeight(400)
|
||||
dlg.setFixedWidth(600)
|
||||
|
||||
layout(dlg,(viewer,),dlg)
|
||||
layout(dlg, (viewer,), dlg)
|
||||
dlg.show()
|
||||
|
||||
box = BRepPrimAPI_MakeBox(20,20,30)
|
||||
box = BRepPrimAPI_MakeBox(20, 20, 30)
|
||||
box_ais = AIS_ColoredShape(box.Shape())
|
||||
viewer.display(box_ais)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user