SearchBar/SafeViewer.py
2021-10-04 00:28:06 +01:00

72 lines
2.4 KiB
Python

from PySide import QtGui
class SafeViewer(QtGui.QWidget):
"""FreeCAD uses a modified version of QuarterWidget, so the import pivy.quarter one will cause segfaults.
FreeCAD's FreeCADGui.createViewer() puts the viewer widget inside an MDI window, and detaching it without causing segfaults on exit is tricky.
This class contains some kludges to extract the viewer as a standalone widget and destroy it safely."""
def __init__(self, parent = None):
super(SafeViewer, self).__init__()
import FreeCADGui
self.viewer = FreeCADGui.createViewer()
self.graphicsView = self.viewer.graphicsView()
self.oldGraphicsViewParent = self.graphicsView.parent()
self.oldGraphicsViewParentParent = self.oldGraphicsViewParent.parent()
self.oldGraphicsViewParentParentParent = self.oldGraphicsViewParentParent.parent()
# Avoid segfault but still hide the undesired window by moving it to a new hidden MDI area.
self.hiddenQMDIArea = QtGui.QMdiArea()
self.hiddenQMDIArea.addSubWindow(self.oldGraphicsViewParentParentParent)
self.private_widget = self.oldGraphicsViewParent
self.private_widget.setParent(parent)
self.setLayout(QtGui.QVBoxLayout())
self.layout().addWidget(self.private_widget)
self.layout().setContentsMargins(0,0,0,0)
def fin(slf):
slf.finalizer()
import weakref
weakref.finalize(self, fin, self)
self.destroyed.connect(self.finalizer)
def finalizer(self):
# Cleanup in an order that doesn't cause a segfault:
self.private_widget.setParent(self.oldGraphicsViewParentParent)
self.oldGraphicsViewParentParentParent.close()
self.oldGraphicsViewParentParentParent = None
self.oldGraphicsViewParentParent = None
self.oldGraphicsViewParent = None
self.graphicsView = None
self.viewer = None
#self.parent = None
self.hiddenQMDIArea = None
"""
# Example use:
from PySide import QtGui
import pivy
def mk(v):
w = QtGui.QMainWindow()
oldFocus = QtGui.QApplication.focusWidget()
sv.widget.setParent(w)
oldFocus.setFocus()
w.show()
col = pivy.coin.SoBaseColor()
col.rgb = (1, 0, 0)
trans = pivy.coin.SoTranslation()
trans.translation.setValue([0, 0, 0])
cub = pivy.coin.SoCube()
myCustomNode = pivy.coin.SoSeparator()
myCustomNode.addChild(col)
myCustomNode.addChild(trans)
myCustomNode.addChild(cub)
sv.viewer.getViewer().setSceneGraph(myCustomNode)
sv.viewer.fitAll()
return w
sv = SafeViewer()
ww=mk(sv)
"""