Exemple #1
0
class ActionTreeWindow(PulseWindow):
    """
    A standalone window that contains an ActionTreeWidget
    and an ActionPaletteWidget.
    """

    OBJECT_NAME = 'pulseActionTreeWindow'
    PREFERRED_SIZE = QtCore.QSize(400, 300)
    STARTING_SIZE = QtCore.QSize(400, 300)
    MINIMUM_SIZE = QtCore.QSize(400, 300)

    WINDOW_MODULE = 'pulse.views.actiontree'

    def __init__(self, parent=None):
        super(ActionTreeWindow, self).__init__(parent=parent)

        self.setWindowTitle('Pulse Action Tree')

        layout = QtWidgets.QVBoxLayout(self)
        self.setLayout(layout)

        self.actionTree = ActionTreeWidget(self)
        layout.addWidget(self.actionTree)

        self.actionPalette = ActionPaletteWidget(self)
        layout.addWidget(self.actionPalette)

        layout.setStretch(layout.indexOf(self.actionTree), 2)
        layout.setStretch(layout.indexOf(self.actionPalette), 1)
Exemple #2
0
    def parent(self, index):
        if not index.isValid():
            return QtCore.QModelIndex()

        thisStep = self.stepForIndex(index)
        parentStep = thisStep.parent if thisStep else None
        if not parentStep or parentStep == self._blueprint.rootStep:
            return QtCore.QModelIndex()

        return self.createIndex(parentStep.indexInParent(), 0, parentStep)
Exemple #3
0
    def index(self, row, column, parent):  # override
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()

        parentItem = self.getItem(parent)

        childItem = parentItem.child(row)
        if childItem:
            return self.createIndex(row, column, childItem)
        else:
            return QtCore.QModelIndex()
Exemple #4
0
    def parent(self, index):  # override
        if not index.isValid():
            return QtCore.QModelIndex()

        childItem = index.internalPointer()
        parentItem = childItem.parent()

        if parentItem == self.rootItem:
            return QtCore.QModelIndex()

        return self.createIndex(parentItem.row(), 0, parentItem)
Exemple #5
0
    def index(self, row, column, parent=QtCore.QModelIndex()):
        """
        Create a QModelIndex for a row, column, and parent index
        """
        if parent.isValid() and column != 0:
            return QtCore.QModelIndex()

        parentStep = self.stepForIndex(parent)
        if parentStep and parentStep.canHaveChildren:
            step = parentStep.getChildAt(row)
            return self.createIndex(row, column, step)

        return QtCore.QModelIndex()
Exemple #6
0
    def parent(self, index):
        if not index.isValid():
            return QtCore.QModelIndex()

        childStep = self.stepForIndex(index)
        if childStep:
            parentStep = childStep.parent
        else:
            return QtCore.QModelIndex()

        if parentStep is None or parentStep == self._blueprint.rootStep:
            return QtCore.QModelIndex()

        return self.createIndex(parentStep.indexInParent(), 0, parentStep)
Exemple #7
0
 def __init__(self, index, parent=None):
     super(BuildActionProxyForm, self).__init__(parent=parent)
     self.index = QtCore.QPersistentModelIndex(index)
     self.hasVariantsUi = False
     self.setupUi(self)
     self.updateVariantFormList()
     self.index.model().dataChanged.connect(self.onModelDataChanged)
Exemple #8
0
    def createAttrForm(self, actionData, attr, parent):
        isVariant = False
        # duck type of actionProxy
        if hasattr(actionData, 'isVariantAttr'):
            isVariant = actionData.isVariantAttr(attr['name'])

        if isVariant:
            attrForm = BatchAttrForm.createForm(self.index,
                                                attr,
                                                parent=parent)
        else:
            attrForm = ActionAttrForm.createForm(self.index,
                                                 attr,
                                                 self.variantIndex,
                                                 parent=parent)

        attrForm.isBatchForm = isVariant

        # add toggle variant button to label layout
        toggleVariantBtn = QtWidgets.QPushButton(parent)
        toggleVariantBtn.setCheckable(True)
        toggleVariantBtn.setText("·")
        toggleVariantBtn.setFixedSize(QtCore.QSize(14, 20))
        attrForm.labelLayout.insertWidget(0, toggleVariantBtn)
        attrForm.labelLayout.setAlignment(toggleVariantBtn, QtCore.Qt.AlignTop)
        toggleVariantBtn.clicked.connect(
            partial(self.toggleIsVariantAttr, attr['name']))

        attrForm.toggleVariantBtn = toggleVariantBtn
        return attrForm
Exemple #9
0
    def setupUi(self, parent):
        self.setupDefaultFormUi(parent)

        hlayout = QtWidgets.QHBoxLayout(parent)
        hlayout.setSpacing(4)

        self.listWidget = QtWidgets.QListWidget(parent)
        self.listWidget.setSortingEnabled(True)
        self.listWidget.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                      QtWidgets.QSizePolicy.Fixed)
        self.listWidget.setSelectionMode(
            QtWidgets.QAbstractItemView.SelectionMode.ExtendedSelection)
        self.listWidget.itemSelectionChanged.connect(
            self.onItemSelectionChanged)
        hlayout.addWidget(self.listWidget)

        self.pickButton = QtWidgets.QPushButton(parent)
        self.pickButton.setIcon(viewutils.getIcon("select.png"))
        self.pickButton.setFixedSize(QtCore.QSize(20, 20))
        self.pickButton.clicked.connect(self.setFromSelection)
        hlayout.addWidget(self.pickButton)
        hlayout.setAlignment(self.pickButton, QtCore.Qt.AlignTop)

        self.setDefaultFormLayout(hlayout)

        if self._isValueTypeValid(self.attrValue):
            self._setFormValue(self.attrValue)
Exemple #10
0
    def setupVariantsUi(self, parent, layout):
        # variant header
        variantHeader = QtWidgets.QFrame(parent)
        variantHeader.setStyleSheet(
            ".QFrame{ background-color: rgb(255, 255, 255, 15); border-radius: 2px }"
        )
        layout.addWidget(variantHeader)

        variantHeaderLayout = QtWidgets.QHBoxLayout(variantHeader)
        variantHeaderLayout.setContentsMargins(10, 4, 4, 4)
        variantHeaderLayout.setSpacing(4)

        self.variantsLabel = QtWidgets.QLabel(variantHeader)
        self.variantsLabel.setText("Variants: ")
        variantHeaderLayout.addWidget(self.variantsLabel)

        spacer = QtWidgets.QSpacerItem(20, 4, QtWidgets.QSizePolicy.Expanding,
                                       QtWidgets.QSizePolicy.Minimum)
        layout.addItem(spacer)

        # add variant button
        addVariantBtn = QtWidgets.QPushButton(variantHeader)
        addVariantBtn.setText('+')
        addVariantBtn.setFixedSize(QtCore.QSize(20, 20))
        addVariantBtn.clicked.connect(self.addVariant)
        variantHeaderLayout.addWidget(addVariantBtn)

        # variant list layout
        self.variantListLayout = QtWidgets.QVBoxLayout(parent)
        self.variantListLayout.setContentsMargins(0, 0, 0, 0)
        self.variantListLayout.setSpacing(4)
        layout.addLayout(self.variantListLayout)
Exemple #11
0
 def insertRows(self, row, count, parent=QtCore.QModelIndex()):
     self.beginInsertRows(parent, row, row + count - 1)
     step = self.stepForIndex(parent)
     for _ in range(count):
         step.insertChild(row, BuildStep())
     self.endInsertRows()
     return True
Exemple #12
0
    def data(self, column, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            if isinstance(self.buildItem, pulse.BuildGroup):
                return '{0} ({1})'.format(self.buildItem.getDisplayName(),
                                          self.buildItem.getChildCount())
            elif isinstance(self.buildItem, pulse.BatchBuildAction):
                return '{0} (x{1})'.format(self.buildItem.getDisplayName(),
                                           self.buildItem.getActionCount())
            else:
                return self.buildItem.getDisplayName()

        elif role == QtCore.Qt.EditRole:
            return self.buildItem.getDisplayName()

        elif role == QtCore.Qt.DecorationRole:
            iconFile = self.buildItem.getIconFile()
            if iconFile:
                return QtGui.QIcon(iconFile)

        elif role == QtCore.Qt.SizeHintRole:
            return QtCore.QSize(0, 20)

        elif role == QtCore.Qt.ForegroundRole:
            color = self.buildItem.getColor()
            if color:
                return QtGui.QColor(*[c * 255 for c in color])
Exemple #13
0
class CollapsibleFrame(QtWidgets.QFrame):
    """
    A QFrame that can be collapsed when clicked.
    """

    collapsedChanged = QtCore.Signal(bool)

    def __init__(self, parent):
        super(CollapsibleFrame, self).__init__(parent)
        self._isCollapsed = False

    def mouseReleaseEvent(self, QMouseEvent):
        if QMouseEvent.button() == QtCore.Qt.MouseButton.LeftButton:
            self.setIsCollapsed(not self._isCollapsed)
        else:
            return super(CollapsibleFrame, self).mouseReleaseEvent(QMouseEvent)

    def setIsCollapsed(self, newCollapsed):
        """
        Set the collapsed state of this frame.
        """
        self._isCollapsed = newCollapsed
        self.collapsedChanged.emit(self._isCollapsed)

    def isCollapsed(self):
        """
        Return True if the frame is currently collapsed.
        """
        return self._isCollapsed
Exemple #14
0
    def createStepsForSelection(self):
        """
        Create new BuildSteps in the hierarchy at the
        current selection and return the new model indexes.
        """
        if self.blueprintModel.isReadOnly():
            return

        selIndexes = self.selectionModel.selectedIndexes()
        if not selIndexes:
            selIndexes = [QtCore.QModelIndex()]

        model = self.selectionModel.model()

        def getParentAndInsertIndex(index):
            step = model.stepForIndex(index)
            print('step', step)
            if step.canHaveChildren:
                print('inserting at num children')
                return index, step.numChildren()
            else:
                print('inserting at selected + 1')
                return model.parent(index), index.row() + 1

        newIndexes = []
        for index in selIndexes:
            parentIndex, insertIndex = getParentAndInsertIndex(index)
            if self.model.insertRows(insertIndex, 1, parentIndex):
                newIndex = self.model.index(insertIndex, 0, parentIndex)
                newIndexes.append(newIndex)

        return newIndexes
Exemple #15
0
class ActionForm(BuildItemForm):
    """
    Form for editing Actions that displays an attr form
    for every attribute on the action.
    """

    convertToBatchClicked = QtCore.Signal()

    def setupUi(self, parent):
        super(ActionForm, self).setupUi(parent)

        # add batch conversion button to header
        convertToBatchBtn = QtWidgets.QPushButton(parent)
        convertToBatchBtn.setIcon(
            viewutils.getIcon("convertActionToBatch.png"))
        convertToBatchBtn.setFixedSize(QtCore.QSize(18, 18))
        convertToBatchBtn.clicked.connect(self.convertToBatchClicked.emit)
        self.headerLayout.addWidget(convertToBatchBtn)

    def setupContentUi(self, parent):
        for attr in self.buildItem.config['attrs']:
            attrValue = getattr(self.buildItem, attr['name'])
            attrForm = ActionAttrForm.createForm(attr,
                                                 attrValue,
                                                 parent=parent)
            attrForm.valueChanged.connect(
                partial(self.attrValueChanged, attrForm))
            self.mainLayout.addWidget(attrForm)

    def attrValueChanged(self, attrForm, attrValue, isValueValid):
        setattr(self.buildItem, attrForm.attr['name'], attrValue)
        self.buildItemChanged.emit()
Exemple #16
0
    def setupDefaultFormUi(self, parent):
        """
        Optional UI setup that builds a standardized layout.
        Includes a form layout and a label with the attributes name.
        Should be called at the start of setupUi if desired.
        """
        self.formLayout = QtWidgets.QFormLayout(parent)
        # margin that will give us some visible area of
        # the frame that can change color based on valid state
        self.formLayout.setMargin(2)
        self.formLayout.setFieldGrowthPolicy(
            QtWidgets.QFormLayout.ExpandingFieldsGrow)
        self.formLayout.setLabelAlignment(QtCore.Qt.AlignRight
                                          | QtCore.Qt.AlignTop
                                          | QtCore.Qt.AlignTrailing)
        self.formLayout.setHorizontalSpacing(10)

        # attribute name
        self.labelLayout = QtWidgets.QHBoxLayout(parent)

        self.label = QtWidgets.QLabel(parent)
        self.label.setMinimumSize(
            QtCore.QSize(self.LABEL_WIDTH, self.LABEL_HEIGHT))
        self.label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing
                                | QtCore.Qt.AlignTop)
        # add some space above the label so it lines up
        self.label.setMargin(2)
        self.label.setText(pulse.names.toTitle(self.attr['name']))
        self.labelLayout.addWidget(self.label)

        self.formLayout.setLayout(0, QtWidgets.QFormLayout.LabelRole,
                                  self.labelLayout)
Exemple #17
0
    def data(self, index, role=QtCore.Qt.DisplayRole):
        if not index.isValid():
            return

        step = self.stepForIndex(index)
        if not step:
            return

        if role == QtCore.Qt.DisplayRole:
            return step.getDisplayName()

        elif role == QtCore.Qt.EditRole:
            return step.name

        elif role == QtCore.Qt.DecorationRole:
            iconFile = step.getIconFile()
            if iconFile:
                return QtGui.QIcon(iconFile)

        elif role == QtCore.Qt.SizeHintRole:
            return QtCore.QSize(0, 20)

        elif role == QtCore.Qt.ForegroundRole:
            color = step.getColor()
            if color:
                return QtGui.QColor(*[c * 255 for c in color])
Exemple #18
0
 def mimeData(self, indexes):
     result = QtCore.QMimeData()
     itemDataList = [
         index.internalPointer().buildItem.serialize() for index in indexes
     ]
     datastr = meta.encodeMetaData(itemDataList)
     result.setData('text/plain', datastr)
     return result
Exemple #19
0
 def indexByStepPath(self, path):
     """
     Return a QModelIndex for a step by path
     """
     if self._blueprint:
         step = self._blueprint.getStepByPath(path)
         return self.indexByStep(step)
     return QtCore.QModelIndex()
Exemple #20
0
    def removeRows(self, position, rows, parent=QtCore.QModelIndex()):
        parentItem = self.getItem(parent)

        self.beginRemoveRows(parent, position, position + rows - 1)
        success = parentItem.removeChildren(position, rows)
        self.endRemoveRows()

        return success
Exemple #21
0
 def __init__(self, index, parent=None):
     """
     Args:
         index (QModelIndex): The index of the BuildStep
     """
     super(BuildStepForm, self).__init__(parent=parent)
     self.index = QtCore.QPersistentModelIndex(index)
     self.setupUi(self)
     self.index.model().dataChanged.connect(self.onModelDataChanged)
Exemple #22
0
    def dropMimeData(self, data, action, row, column, parentIndex):
        if not self.canDropMimeData(data, action, row, column, parentIndex):
            return False

        if action == QtCore.Qt.IgnoreAction:
            return True

        try:
            stepDataList = meta.decodeMetaData(str(data.data('text/plain')))
        except Exception as e:
            LOG.error(e)
            return False

        print('dropData', stepDataList, data, action, row, column, parentIndex)

        beginRow = 0
        parentPath = None

        if parentIndex.isValid():
            parentStep = self.stepForIndex(parentIndex)
            if parentStep:
                if parentStep.canHaveChildren:
                    # drop into step group
                    beginRow = parentStep.numChildren()
                    parentPath = parentStep.getFullPath()
                else:
                    # drop next to step
                    beginRow = parentIndex.row()
                    parentPath = os.path.dirname(parentStep.getFullPath())

        if not parentPath:
            parentPath = ''
            beginRow = self.rowCount(QtCore.QModelIndex())
        if row != -1:
            beginRow = row

        cmds.undoInfo(openChunk=True, chunkName='Drag Pulse Actions')
        self.isMoveActionOpen = True
        cmds.evalDeferred(self._deferredMoveUndoClose)

        # create dropped steps
        count = len(stepDataList)
        for i in range(count):
            stepDataStr = serializeAttrValue(stepDataList[i])
            newStepPath = cmds.pulseCreateStep(
                parentPath, beginRow + i, stepDataStr)
            if newStepPath:
                newStepPath = newStepPath[0]

                if action == QtCore.Qt.MoveAction:
                    # create queue of renames to perform after source
                    # steps have been removed
                    targetName = stepDataList[i].get('name', '')
                    self.dragRenameQueue.append((newStepPath, targetName))

        return True
Exemple #23
0
    def setupUi(self, parent):
        super(BatchActionForm, self).setupUi(parent)

        # add action conversion button to header
        convertToActionBtn = QtWidgets.QPushButton(parent)
        convertToActionBtn.setIcon(
            viewutils.getIcon("convertBatchToAction.png"))
        convertToActionBtn.setFixedSize(QtCore.QSize(18, 18))
        convertToActionBtn.clicked.connect(self.convertToActionClicked.emit)
        self.headerLayout.addWidget(convertToActionBtn)
Exemple #24
0
class BlueprintEditorWindow(PulseWindow):

    OBJECT_NAME = 'pulseBlueprintEditorWindow'
    PREFERRED_SIZE = QtCore.QSize(400, 300)
    STARTING_SIZE = QtCore.QSize(400, 300)
    MINIMUM_SIZE = QtCore.QSize(400, 300)

    WINDOW_MODULE = 'pulse.views.blueprinteditor'

    def __init__(self, parent=None):
        super(BlueprintEditorWindow, self).__init__(parent=parent)

        self.setWindowTitle('Pulse Blueprint Editor')

        layout = QtWidgets.QVBoxLayout(self)
        self.setLayout(layout)

        widget = BlueprintEditorWidget(self)
        layout.addWidget(widget)
class BatchAttrForm(QtWidgets.QWidget):
    """
    The base class for an attribute form designed to
    bulk edit all variants of an attribute on a batch action.
    This appears where the default attr form usually appears
    when the attribute is marked as variant.
    
    BatchAttrForms should only exist if they provide an
    easy way to bulk set different values for all variants,
    as its pointless to provide functionality for setting all
    variants to the same value (would make the attribute constant).
    """

    TYPEMAP = {}

    valuesChanged = QtCore.Signal()
    variantCountChanged = QtCore.Signal()

    @staticmethod
    def doesFormExist(attr):
        return attr['type'] in BatchAttrForm.TYPEMAP

    @staticmethod
    def createForm(action, attr, parent=None):
        """
        Create a new ActionAttrForm of the appropriate
        type based on a BuildAction attribute.

        Args:
            attr: A dict representing the config of a BuildAction attribute
        """
        attrType = attr['type']
        if attrType in BatchAttrForm.TYPEMAP:
            return BatchAttrForm.TYPEMAP[attrType](action, attr, parent=parent)

    def __init__(self, batchAction, attr, parent=None):
        super(BatchAttrForm, self).__init__(parent=parent)
        self.batchAction = batchAction
        self.attr = attr
        self.setupUi(self)

    def setupUi(self, parent):
        raise NotImplementedError
Exemple #26
0
class QuickNameWindow(PulseWindow):

    OBJECT_NAME = 'pulseQuickNameWindow'
    PREFERRED_SIZE = QtCore.QSize(400, 300)
    STARTING_SIZE = QtCore.QSize(400, 300)
    MINIMUM_SIZE = QtCore.QSize(400, 300)

    WINDOW_MODULE = 'pulse.views.quickname'

    def __init__(self, parent=None):
        super(QuickNameWindow, self).__init__(parent=parent)

        self.setWindowTitle('Quick Name Editor')

        layout = QtWidgets.QVBoxLayout(self)
        layout.setMargin(0)
        self.setLayout(layout)

        widget = QuickNameWidget(self)
        layout.addWidget(widget)
Exemple #27
0
 def createControlShapeButton(text, shapeData):
     btn = QtWidgets.QPushButton(parent)
     btn.setStatusTip("Create a new control")
     if 'icon' in shapeData:
         btn.setIcon(getIcon("controls/" + shapeData["icon"]))
         btn.setIconSize(QtCore.QSize(32, 32))
     else:
         btn.setText(text)
     btn.clicked.connect(
         cmd(pulse.controlshapes.createControlsForSelected, shapeData))
     return btn
Exemple #28
0
class CopyPastMatrixWindow(PulseWindow):

    OBJECT_NAME = 'pulseCopyPasteMatrixWindow'
    PREFERRED_SIZE = QtCore.QSize(220, 160)
    STARTING_SIZE = QtCore.QSize(220, 160)
    MINIMUM_SIZE = QtCore.QSize(220, 160)

    REQUIRED_PLUGINS = []

    WINDOW_MODULE = 'pulse.views.utilviews'

    def __init__(self, parent=None):
        super(CopyPastMatrixWindow, self).__init__(parent=parent)

        self.setWindowTitle('Copy Paste Matrix')

        layout = QtWidgets.QVBoxLayout(self)
        self.setLayout(layout)

        widget = CopyPastMatrixWidget(self)
        layout.addWidget(widget)
Exemple #29
0
    def __init__(self, index, variantIndex=-1, parent=None):
        super(BuildActionDataForm, self).__init__(parent=parent)

        self.index = QtCore.QPersistentModelIndex(index)
        self.variantIndex = variantIndex
        self.setupUi(self)

        # the map of all attr forms, indexed by attr name
        self._attrForms = {}
        self.updateAttrFormList()

        self.index.model().dataChanged.connect(self.onModelDataChanged)
Exemple #30
0
    def insertBuildItems(self,
                         position,
                         childBuildItems,
                         parent=QtCore.QModelIndex()):
        parentItem = self.getItem(parent)

        self.beginInsertRows(parent, position,
                             position + len(childBuildItems) - 1)
        success = parentItem.insertChildren(position, childBuildItems)
        self.endInsertRows()

        return success