Source code for director.objectmodel

import os
import PythonQt
from PythonQt import QtCore, QtGui
from director.propertyset import PropertySet, PropertyAttributes, PropertyPanelHelper
from director import callbacks

[docs]class Icons(object): Directory = int(QtGui.QStyle.SP_DirIcon) Axes = ':/images/axes_icon.png' Eye = ':/images/eye_icon.png' EyeOff = ':/images/eye_icon_gray.png' Matlab = ':/images/matlab_logo.png' Robot = ':/images/robot_icon.png' Hammer = ':/images/hammer_icon.png' Laser = ':/images/laser_icon.jpg' Feet = ':/images/feet.png' Hand = ':/images/claw.png' Octomap = ':/images/octomap.jpg' Collections = ':/images/rubix_cube.jpg' @staticmethod
[docs] def getIcon(iconId): ''' Return a QIcon given an icon id as a string or int. ''' if type(iconId) == int: return QtGui.QApplication.style().standardIcon(iconId) else: return QtGui.QIcon(iconId)
[docs]class ObjectModelItem(object): REMOVED_FROM_OBJECT_MODEL = 'REMOVED_FROM_OBJECT_MODEL' def __getstate__(self): #print 'getstate called on:', self d = dict(properties=self.properties) return d def __setstate__(self, state): #print 'setstate called on:', self self._tree = None self.properties = state['properties'] def __init__(self, name, icon=Icons.Robot, properties=None): #print 'init called on:', self self._tree = None self.callbacks = callbacks.CallbackRegistry([self.REMOVED_FROM_OBJECT_MODEL]) self.properties = properties or PropertySet() self.properties.connectPropertyChanged(self._onPropertyChanged) self.properties.connectPropertyAdded(self._onPropertyAdded) self.properties.connectPropertyAttributeChanged(self._onPropertyAttributeChanged) self.addProperty('Icon', icon, attributes=PropertyAttributes(hidden=True)) self.addProperty('Deletable', True, attributes=PropertyAttributes(hidden=True)) self.addProperty('Name', name, attributes=PropertyAttributes(hidden=True))
[docs] def setIcon(self, icon): self.setProperty('Icon', icon)
[docs] def propertyNames(self): return self.properties.propertyNames()
[docs] def hasProperty(self, propertyName): return self.properties.hasProperty(propertyName)
[docs] def getProperty(self, propertyName): return self.properties.getProperty(propertyName)
[docs] def getPropertyEnumValue(self, propertyName): return self.properties.getPropertyEnumValue(propertyName)
[docs] def addProperty(self, propertyName, propertyValue, attributes=None): self.properties.addProperty(propertyName, propertyValue, attributes)
[docs] def removeProperty(self, propertyName): self.properties.removeProperty(propertyName)
[docs] def setProperty(self, propertyName, propertyValue): self.properties.setProperty(propertyName, propertyValue)
[docs] def getPropertyAttribute(self, propertyName, propertyAttribute): return self.properties.getPropertyAttribute(propertyName, propertyAttribute)
[docs] def setPropertyAttribute(self, propertyName, propertyAttribute, value): self.properties.setPropertyAttribute(propertyName, propertyAttribute, value)
def _onPropertyChanged(self, propertySet, propertyName): if self._tree is not None: self._tree._onPropertyValueChanged(self, propertyName) def _onPropertyAdded(self, propertySet, propertyName): pass def _onPropertyAttributeChanged(self, propertySet, propertyName, propertyAttribute): pass
[docs] def hasDataSet(self, dataSet): return False
[docs] def getActionNames(self): actions = ['Rename'] return actions
[docs] def onAction(self, action): if action == 'Rename': name = self.getProperty('Name') inputDialog = QtGui.QInputDialog() inputDialog.setInputMode(inputDialog.TextInput) inputDialog.setLabelText('Name:') inputDialog.setWindowTitle('Enter name') inputDialog.setTextValue(name) result = inputDialog.exec_() if result: self.rename(inputDialog.textValue())
[docs] def rename(self, name, renameChildren=True): oldName = self.getProperty('Name') if renameChildren: for child in self.children(): childName = child.getProperty('Name') if childName.startswith(oldName): child.setProperty('Name', name + childName[len(oldName):]) self.setProperty('Name', name)
[docs] def getObjectTree(self): return self._tree
[docs] def onRemoveFromObjectModel(self): pass
[docs] def connectRemovedFromObjectModel(self, func): return self.callbacks.connect(self.REMOVED_FROM_OBJECT_MODEL, func)
[docs] def disconnectRemovedFromObjectModel(self, callbackId): self.callbacks.disconnect(callbackId)
[docs] def parent(self): if self._tree is not None: return self._tree.getObjectParent(self)
[docs] def children(self): if self._tree is not None: return self._tree.getObjectChildren(self) else: return []
[docs] def findChild(self, name): if self._tree is not None: return self._tree.findChildByName(self, name)
[docs]class ContainerItem(ObjectModelItem): def __init__(self, name): ObjectModelItem.__init__(self, name, Icons.Directory) self.addProperty('Visible', True) def _onPropertyChanged(self, propertySet, propertyName): ObjectModelItem._onPropertyChanged(self, propertySet, propertyName) if propertyName == 'Visible': visible = self.getProperty(propertyName) for child in self.children(): if child.hasProperty(propertyName): child.setProperty(propertyName, visible)
[docs]class ObjectModelTree(object): ACTION_SELECTED = 'ACTION_SELECTED' OBJECT_ADDED = 'OBJECT_ADDED' OBJECT_CLICKED = 'OBJECT_CLICKED' SELECTION_CHANGED = 'SELECTION_CHANGED' def __init__(self): self._treeWidget = None self._propertiesPanel = None self._objects = {} self._blockSignals = False self.actions = [] self.callbacks = callbacks.CallbackRegistry([ self.ACTION_SELECTED, self.OBJECT_ADDED, self.OBJECT_CLICKED, self.SELECTION_CHANGED, ])
[docs] def getTreeWidget(self): return self._treeWidget
[docs] def getPropertiesPanel(self): return self._propertiesPanel
[docs] def getObjectParent(self, obj): item = self._getItemForObject(obj) if item.parent(): return self._getObjectForItem(item.parent())
[docs] def getObjectChildren(self, obj): item = self._getItemForObject(obj) return [self._getObjectForItem(item.child(i)) for i in xrange(item.childCount())]
[docs] def getTopLevelObjects(self): return [self._getObjectForItem(self._treeWidget.topLevelItem(i)) for i in xrange(self._treeWidget.topLevelItemCount)]
[docs] def getActiveObject(self): item = self._getSelectedItem() return self._objects[item] if item is not None else None
[docs] def setActiveObject(self, obj): item = self._getItemForObject(obj) if item: tree = self.getTreeWidget() tree.setCurrentItem(item) tree.scrollToItem(item) else: self.clearSelection()
[docs] def clearSelection(self): self.getTreeWidget().setCurrentItem(None)
[docs] def getObjects(self): return self._objects.values()
def _getSelectedItem(self): items = self.getTreeWidget().selectedItems() return items[0] if len(items) == 1 else None def _getItemForObject(self, obj): for item, itemObj in self._objects.iteritems(): if itemObj == obj: return item def _getObjectForItem(self, item): return self._objects[item]
[docs] def findObjectByName(self, name, parent=None): if parent: return self.findChildByName(parent, name) for obj in self._objects.values(): if obj.getProperty('Name') == name: return obj
[docs] def findChildByName(self, parent, name): for child in self.getObjectChildren(parent): if child.getProperty('Name') == name: return child
[docs] def onPropertyChanged(self, prop): if self._blockSignals: return propertiesPanel = self.getPropertiesPanel() propertySet = self.getActiveObject().properties PropertyPanelHelper.setPropertyFromPanel(prop, propertiesPanel, propertySet)
def _onTreeSelectionChanged(self): panel = self.getPropertiesPanel() self._blockSignals = True panel.clear() self._blockSignals = False obj = self.getActiveObject() if obj: self._blockSignals = True PropertyPanelHelper.addPropertiesToPanel(obj.properties, panel) self._blockSignals = False self.callbacks.process(self.SELECTION_CHANGED, self)
[docs] def updateVisIcon(self, obj): if not obj.hasProperty('Visible'): return isVisible = obj.getProperty('Visible') item = self._getItemForObject(obj) item.setIcon(1, Icons.getIcon(Icons.Eye if isVisible else Icons.EyeOff))
[docs] def updateObjectIcon(self, obj): item = self._getItemForObject(obj) item.setIcon(0, Icons.getIcon(obj.getProperty('Icon')))
[docs] def updateObjectName(self, obj): item = self._getItemForObject(obj) item.setText(0, obj.getProperty('Name'))
def _onPropertyValueChanged(self, obj, propertyName): if propertyName == 'Visible': self.updateVisIcon(obj) elif propertyName == 'Name': self.updateObjectName(obj) elif propertyName == 'Icon': self.updateObjectIcon(obj) if obj == self.getActiveObject(): self._blockSignals = True PropertyPanelHelper.onPropertyValueChanged(self.getPropertiesPanel(), obj.properties, propertyName) self._blockSignals = False def _onItemClicked(self, item, column): obj = self._objects[item] if column == 1 and obj.hasProperty('Visible'): obj.setProperty('Visible', not obj.getProperty('Visible')) self.updateVisIcon(obj) self.callbacks.process(self.OBJECT_CLICKED, self, obj) def _removeItemFromObjectModel(self, item): while item.childCount(): self._removeItemFromObjectModel(item.child(0)) try: obj = self._getObjectForItem(item) except KeyError: return obj.callbacks.process(obj.REMOVED_FROM_OBJECT_MODEL, self, obj) obj.onRemoveFromObjectModel() obj._tree = None if item.parent(): item.parent().removeChild(item) else: tree = self.getTreeWidget() tree.takeTopLevelItem(tree.indexOfTopLevelItem(item)) del self._objects[item]
[docs] def removeFromObjectModel(self, obj): if obj is None: return item = self._getItemForObject(obj) if item: self._removeItemFromObjectModel(item)
[docs] def addToObjectModel(self, obj, parentObj=None): assert obj._tree is None parentItem = self._getItemForObject(parentObj) objName = obj.getProperty('Name') item = QtGui.QTreeWidgetItem(parentItem, [objName]) item.setIcon(0, Icons.getIcon(obj.getProperty('Icon'))) obj._tree = self self._objects[item] = obj self.updateVisIcon(obj) if parentItem is None: tree = self.getTreeWidget() tree.addTopLevelItem(item) tree.expandItem(item) self.callbacks.process(self.OBJECT_ADDED, self, obj)
[docs] def collapse(self, obj): item = self._getItemForObject(obj) if item: self.getTreeWidget().collapseItem(item)
[docs] def expand(self, obj): item = self._getItemForObject(obj) if item: self.getTreeWidget().expandItem(item)
[docs] def addContainer(self, name, parentObj=None): obj = ContainerItem(name) self.addToObjectModel(obj, parentObj) return obj
[docs] def getOrCreateContainer(self, name, parentObj=None): if parentObj: containerObj = parentObj.findChild(name) else: containerObj = self.findObjectByName(name) if not containerObj: containerObj = self.addContainer(name, parentObj) return containerObj
def _onShowContextMenu(self, clickPosition): obj = self.getActiveObject() if not obj: self._onTreeContextMenu(clickPosition) else: self._onObjectContextMenu(obj, clickPosition) def _showMenu(self, actions, clickPosition): if not actions: return None globalPos = self.getTreeWidget().viewport().mapToGlobal(clickPosition) menu = QtGui.QMenu() for name in actions: if not name: menu.addSeparator() else: menu.addAction(name) selectedAction = menu.exec_(globalPos) if selectedAction is not None: return selectedAction.text else: return None def _onTreeContextMenu(self, clickPosition): selectedAction = self._showMenu(self.actions, clickPosition) if selectedAction: self.callbacks.process(self.ACTION_SELECTED, self, selectedAction) def _onObjectContextMenu(self, obj, clickPosition): actions = list(obj.getActionNames()) if obj.hasProperty('Deletable') and obj.getProperty('Deletable'): actions.append(None) actions.append('Remove') selectedAction = self._showMenu(actions, clickPosition) if selectedAction == 'Remove': self.removeFromObjectModel(obj) elif selectedAction: obj.onAction(selectedAction)
[docs] def removeSelectedItems(self): for item in self.getTreeWidget().selectedItems(): obj = self._getObjectForItem(item) if (not obj.hasProperty('Deletable')) or obj.getProperty('Deletable'): self._removeItemFromObjectModel(item)
def _filterEvent(self, obj, event): if event.type() == QtCore.QEvent.KeyPress: if event.key() == QtCore.Qt.Key_Delete: self._eventFilter.setEventHandlerResult(True) self.removeSelectedItems()
[docs] def connectSelectionChanged(self, func): return self.callbacks.connect(self.SELECTION_CHANGED, func)
[docs] def disconnectSelectionChanged(self, callbackId): self.callbacks.disconnect(callbackId)
[docs] def connectObjectAdded(self, func): return self.callbacks.connect(self.OBJECT_ADDED, func)
[docs] def disconnectObjectAdded(self, callbackId): self.callbacks.disconnect(callbackId)
[docs] def connectObjectClicked(self, func): return self.callbacks.connect(self.OBJECT_CLICKED, func)
[docs] def disconnectObjectClicked(self, func): self.callbacks.disconnect(callbackId)
[docs] def init(self, treeWidget, propertiesPanel): self._treeWidget = treeWidget self._propertiesPanel = propertiesPanel propertiesPanel.clear() propertiesPanel.setBrowserModeToWidget() propertiesPanel.connect('propertyValueChanged(QtVariantProperty*)', self.onPropertyChanged) treeWidget.setColumnCount(2) treeWidget.setHeaderLabels(['Name', '']) treeWidget.headerItem().setIcon(1, Icons.getIcon(Icons.Eye)) treeWidget.header().setVisible(True) treeWidget.header().setStretchLastSection(False) treeWidget.header().setResizeMode(0, QtGui.QHeaderView.Stretch) treeWidget.header().setResizeMode(1, QtGui.QHeaderView.Fixed) treeWidget.setColumnWidth(1, 24) treeWidget.connect('itemSelectionChanged()', self._onTreeSelectionChanged) treeWidget.connect('itemClicked(QTreeWidgetItem*, int)', self._onItemClicked) treeWidget.connect('customContextMenuRequested(const QPoint&)', self._onShowContextMenu) treeWidget.setContextMenuPolicy(PythonQt.QtCore.Qt.CustomContextMenu); self._eventFilter = PythonQt.dd.ddPythonEventFilter() self._eventFilter.addFilteredEventType(QtCore.QEvent.KeyPress) self._eventFilter.connect('handleEvent(QObject*, QEvent*)', self._filterEvent) treeWidget.installEventFilter(self._eventFilter)
####################### _t = ObjectModelTree()
[docs]def getDefaultObjectModel(): return _t
[docs]def getActiveObject(): return _t.getActiveObject()
[docs]def setActiveObject(obj): _t.setActiveObject(obj)
[docs]def clearSelection(): _t.clearSelection()
[docs]def getObjects(): return _t.getObjects()
[docs]def findObjectByName(name, parent=None): return _t.findObjectByName(name, parent)
[docs]def removeFromObjectModel(obj): _t.removeFromObjectModel(obj)
[docs]def addToObjectModel(obj, parentObj=None): _t.addToObjectModel(obj, parentObj)
[docs]def collapse(obj): _t.collapse(obj)
[docs]def expand(obj): _t.expand(obj)
[docs]def addContainer(name, parentObj=None): return _t.addContainer(name, parentObj)
[docs]def getOrCreateContainer(name, parentObj=None): return _t.getOrCreateContainer(name, parentObj)
[docs]def init(objectTree=None, propertiesPanel=None): if _t._treeWidget: return objectTree = objectTree or QtGui.QTreeWidget() propertiesPanel = propertiesPanel or PythonQt.dd.ddPropertiesPanel() _t.init(objectTree, propertiesPanel)