""" Opens up a 2nd window for docking mobu and R* widgets to """ import sys from PySide import QtGui, QtCore from RS.Tools import UI from RS.Tools.UI import Application, QPrint class SecondDockableWindow(UI.QtMainWindowBase): """ Singleton class Do not instance more than one of this class!! This is the window for the second dockable window for motion builder """ def __init__(self, parent=None): """ Constructor """ super(SecondDockableWindow, self).__init__(parent=parent, title='Secondary Dockable Window') self._mobuWindow = Application.GetMainWindow() self._mouseReleaseEventCalls = [ (QtCore.QEvent.Type.Move, QtCore.QEvent.Type.NonClientAreaMouseMove), (QtCore.QEvent.Type.Move, QtCore.QEvent.Type.MouseButtonRelease) ] self._lastEvent = None self._dockWidge = [] self._dockWidgetLastEventDict = {} self.updateDockWidgets() def updateDockWidgets(self): """ Update the widgets which can dock with it from the list of motion builder child dock widgets """ dockWindows = {wid.windowTitle():wid for wid in self._mobuWindow.children() if isinstance(wid, QtGui.QDockWidget)} dockWindows.pop("Viewer") # Remove the viewer at all costs!! for win in dockWindows.itervalues(): if win not in self._dockWidge: self._setupMobuDockWidget(win) def _setupMobuDockWidget(self, dockWidget): """ Internal Method Setup a given dockwidget to work with the secondary dock Args: dockWidget (QDockWidget): A dock widget to dock with the secondary dock """ QPrint(dockWidget.windowTitle()) dockWidget.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas) dockWidget.installEventFilter(self) self._dockWidge.append(dockWidget) def eventFilter(self, target, event): """ Reimplemeted Qt's Event filter method for filtering out event methods which get triggered Args: target (QObject): The object which the filter is installed on event (QEvent): The triggering event Returns: bool """ returnVal = None if (self._dockWidgetLastEventDict.get(target, None), event.type()) in self._mouseReleaseEventCalls: self._reparent(target) returnVal = True self._dockWidgetLastEventDict[target] = event.type() if returnVal is not None: return returnVal return super(QtGui.QDockWidget, target).eventFilter(target, event) def _reparent(self, dockWidget): """ Reparents the given dock widget based off its over the secondary dock widget or not Args: dockWidget (QDockWidget): The dock widget to re-parent if needed """ currentParent = dockWidget.parent() parent = (self._mobuWindow, self)[self._isUnderCursor(self)] # The instance of the mobu QMainWindow never seems to be # the same, so a safer approach is to compare window titles if currentParent.windowTitle() != parent.windowTitle(): # We set floating to True to cancel out any docking # Changing the parent when docking results in crashes dockWidget.setFloating(True) dockWidget.setParent(parent) # We call show and setFloating to True to make sure # the widget is visible dockWidget.show() dockWidget.setFloating(True) def _isUnderCursor(self, widget): """ Checks if the mouse is under the given widget Arguments: widget (QWidget): widget to check """ pos = QtGui.QCursor.pos() corner = widget.pos() size = widget.size() isInHorizontalBoundary = corner.x() <= pos.x() <= (corner.x() + size.width()) isInVerticalBoundary = corner.y() <= pos.y() <= (corner.y() + size.height()) return isInHorizontalBoundary and isInVerticalBoundary # Make sure there is only one instance of the widget open thisModule = sys.modules[__name__] if not hasattr(thisModule, "_secondaryDockableWindow"): setattr(thisModule, "_secondaryDockableWindow", None) def Run(show=True): thisModule = sys.modules[__name__] win = getattr(thisModule, "_secondaryDockableWindow") if _secondaryDockableWindow is None: win = SecondDockableWindow() setattr(thisModule, "_secondaryDockableWindow", win) else: win.updateDockWidgets() if show: win.show() return win