Buttons for enabling the 3D preview (unstable)
This commit is contained in:
parent
27a54983eb
commit
8baac59832
|
@ -64,9 +64,7 @@ class DocumentObjectToolTipWidget(QtGui.QWidget):
|
|||
|
||||
# Tried hiding/detaching the preview to prevent it from disappearing when changing its contents
|
||||
#self.preview.viewer.stopAnimating()
|
||||
self.preview.viewer.getViewer().setSceneGraph(obj.ViewObject.RootNode)
|
||||
self.preview.viewer.setCameraOrientation(App.Rotation(1,1,0, 0.2))
|
||||
self.preview.viewer.fitAll()
|
||||
self.preview.showSceneGraph(obj.ViewObject.RootNode)
|
||||
|
||||
setParent(self)
|
||||
# Let the GUI recompute the side of the description based on its horizontal size.
|
||||
|
|
117
SafeViewer.py
117
SafeViewer.py
|
@ -1,53 +1,113 @@
|
|||
from PySide import QtGui
|
||||
import FreeCAD
|
||||
|
||||
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."""
|
||||
enabled = FreeCAD.ParamGet('User parameter:BaseApp/Preferences/Mod/SearchBar').GetBool('PreviewEnabled', False)
|
||||
instances = []
|
||||
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()
|
||||
SafeViewer.instances.append(self)
|
||||
self.init_parent = parent
|
||||
self.instance_enabled = False # Has this specific instance been enabled?
|
||||
if SafeViewer.enabled:
|
||||
self.displaying_warning = False
|
||||
self.enable()
|
||||
else:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
self.displaying_warning = True
|
||||
self.lbl_warning = QtGui.QTextEdit()
|
||||
self.lbl_warning.setReadOnly(True)
|
||||
self.lbl_warning.setAlignment(QtCore.Qt.AlignTop)
|
||||
self.lbl_warning.setText("Warning: the 3D preview has some stability issues. It can cause FreeCAD to crash (usually when quitting the application) and could in theory cause data loss, inside and outside of FreeCAD.")
|
||||
self.btn_enable_for_this_session = QtGui.QPushButton('Enable 3D preview for this session')
|
||||
self.btn_enable_for_this_session.clicked.connect(self.enable_for_this_session)
|
||||
self.btn_enable_for_future_sessions = QtGui.QPushButton('Enable 3D preview for future sessions')
|
||||
self.btn_enable_for_future_sessions.clicked.connect(self.enable_for_future_sessions)
|
||||
self.setLayout(QtGui.QVBoxLayout())
|
||||
self.layout().addWidget(self.lbl_warning)
|
||||
self.layout().addWidget(self.btn_enable_for_this_session)
|
||||
self.layout().addWidget(self.btn_enable_for_future_sessions)
|
||||
|
||||
def enable_for_this_session(self):
|
||||
if not SafeViewer.enabled:
|
||||
for instance in SafeViewer.instances:
|
||||
instance.enable()
|
||||
|
||||
# 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)
|
||||
def enable_for_future_sessions(self):
|
||||
if not SafeViewer.enabled:
|
||||
# Store in prefs
|
||||
FreeCAD.ParamGet('User parameter:BaseApp/Preferences/Mod/SearchBar').SetBool('PreviewEnabled', True)
|
||||
# Then enable as usual
|
||||
self.enable_for_this_session()
|
||||
|
||||
self.private_widget = self.oldGraphicsViewParent
|
||||
self.private_widget.setParent(parent)
|
||||
def enable(self):
|
||||
if not self.instance_enabled:
|
||||
import FreeCADGui
|
||||
# TODO: use a mutex wrapping the entire method, if possible
|
||||
SafeViewer.enabled = True
|
||||
self.instance_enabled = True # Has this specific instance been enabled?
|
||||
|
||||
self.setLayout(QtGui.QVBoxLayout())
|
||||
self.layout().addWidget(self.private_widget)
|
||||
self.layout().setContentsMargins(0,0,0,0)
|
||||
if (self.displaying_warning):
|
||||
self.layout().removeWidget(self.lbl_warning)
|
||||
self.layout().removeWidget(self.btn_enable_for_this_session)
|
||||
self.layout().removeWidget(self.btn_enable_for_future_sessions)
|
||||
|
||||
def fin(slf):
|
||||
slf.finalizer()
|
||||
self.viewer = FreeCADGui.createViewer()
|
||||
self.graphicsView = self.viewer.graphicsView()
|
||||
self.oldGraphicsViewParent = self.graphicsView.parent()
|
||||
self.oldGraphicsViewParentParent = self.oldGraphicsViewParent.parent()
|
||||
self.oldGraphicsViewParentParentParent = self.oldGraphicsViewParentParent.parent()
|
||||
|
||||
import weakref
|
||||
weakref.finalize(self, fin, self)
|
||||
# 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.destroyed.connect(self.finalizer)
|
||||
self.private_widget = self.oldGraphicsViewParent
|
||||
self.private_widget.setParent(self.init_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
|
||||
if SafeViewer.enabled:
|
||||
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.init_parent = None
|
||||
self.hiddenQMDIArea = None
|
||||
|
||||
def showSceneGraph(self, g):
|
||||
import FreeCAD as App
|
||||
if SafeViewer.enabled:
|
||||
self.viewer.getViewer().setSceneGraph(g)
|
||||
self.viewer.setCameraOrientation(App.Rotation(1,1,0, 0.2))
|
||||
self.viewer.fitAll()
|
||||
|
||||
"""
|
||||
# Example use:
|
||||
from PySide import QtGui
|
||||
import pivy
|
||||
from SafeViewer import SafeViewer
|
||||
sv = SafeViewer()
|
||||
def mk(v):
|
||||
w = QtGui.QMainWindow()
|
||||
oldFocus = QtGui.QApplication.focusWidget()
|
||||
|
@ -66,6 +126,5 @@ def mk(v):
|
|||
sv.viewer.getViewer().setSceneGraph(myCustomNode)
|
||||
sv.viewer.fitAll()
|
||||
return w
|
||||
sv = SafeViewer()
|
||||
ww=mk(sv)
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue
Block a user