Example #1
0
    def create_drop_indicator_widget(drop_area):
        layout = QLabel()
        layout.setObjectName('DropAreaLabel')
        metric = (layout.fontMetrics().height()) * 2.0
        size = QSizeF(metric, metric)
        layout.setPixmap(
            DropOverlay.create_drop_indicator_pixmap(palette=layout.palette(),
                                                     size=size,
                                                     drop_area=drop_area))

        return layout
Example #2
0
class UIVariable(QWidget, IPropertiesViewSupport):
    def __init__(self, rawVariable, variablesWidget, parent=None):
        super(UIVariable, self).__init__(parent)
        self._rawVariable = rawVariable
        self.variablesWidget = variablesWidget
        # ui
        self.horizontalLayout = QHBoxLayout(self)
        self.horizontalLayout.setSpacing(1)
        self.horizontalLayout.setContentsMargins(1, 1, 1, 1)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.widget = TypeWidget(
            findPinClassByType(self._rawVariable.dataType).color(), self)
        self.widget.setObjectName("widget")
        self.horizontalLayout.addWidget(self.widget)
        self.labelName = QLabel(self)
        self.labelName.setStyleSheet("background:transparent")
        self.labelName.setObjectName("labelName")
        self.horizontalLayout.addWidget(self.labelName)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        # find refs
        self.pbFindRefs = QPushButton("")
        self.pbFindRefs.setIcon(
            QtGui.QIcon(":/searching-magnifying-glass.png"))
        self.pbFindRefs.setObjectName("pbFindRefs")
        self.horizontalLayout.addWidget(self.pbFindRefs)
        self.pbFindRefs.clicked.connect(self.onFindRefsClicked)
        #  kill variable
        self.pbKill = QPushButton("")
        self.pbKill.setIcon(QtGui.QIcon(":/delete_icon.png"))
        self.pbKill.setObjectName("pbKill")
        self.horizontalLayout.addWidget(self.pbKill)
        self.pbKill.clicked.connect(self.onKillClicked)

        QtCore.QMetaObject.connectSlotsByName(self)
        self.setName(self._rawVariable.name)
        self._rawVariable.setWrapper(self)

    def onStructureChanged(self, name):
        self._rawVariable.structure = PinStructure[name]
        self.variablesWidget.pyFlowInstance.onRequestFillProperties(
            self.createPropertiesWidget)
        EditorHistory().saveState("Change variable struct", modify=True)

    def setDataType(self, dataType):
        self.dataType = dataType
        self._rawVariable.dataType = dataType
        EditorHistory().saveState("Change variable data type", modify=True)

    def createPropertiesWidget(self, propertiesWidget):
        baseCategory = CollapsibleFormWidget(headName="Base", modify=True)
        # name
        le_name = QLineEdit(self._rawVariable.name)
        le_name.returnPressed.connect(lambda: self.setName(le_name.text()))
        baseCategory.addWidget("Name", le_name)

        # data type
        cbTypes = EnumComboBox([
            pin.__name__ for pin in getAllPinClasses() if pin.IsValuePin()
            if pin.__name__ != "AnyPin"
        ])
        cbTypes.setCurrentIndex(cbTypes.findText(self.dataType))
        cbTypes.setEditable(False)
        cbTypes.changeCallback.connect(self.setDataType)
        propertiesWidget.addWidget(baseCategory)

        # structure type
        cbStructure = EnumComboBox(
            [i.name for i in (PinStructure.Single, PinStructure.Array)])
        cbStructure.setEditable(False)
        cbStructure.setCurrentIndex(
            cbStructure.findText(self._rawVariable.structure.name))
        cbStructure.changeCallback.connect(self.onStructureChanged)
        propertiesWidget.addWidget(baseCategory)
        baseCategory.addWidget("Type", cbTypes)
        baseCategory.addWidget("Structure", cbStructure)

        valueCategory = CollapsibleFormWidget(headName="Value")

        # current value
        if self._rawVariable.structure == PinStructure.Single:
            if not type(self._rawVariable.value) in {list, set, dict, tuple}:

                def valSetter(x):
                    self._rawVariable.value = x

                w = createInputWidget(
                    self._rawVariable.dataType, valSetter,
                    getPinDefaultValueByType(self._rawVariable.dataType))
                if w:
                    w.setWidgetValue(self._rawVariable.value)
                    w.setObjectName(self._rawVariable.name)
                    valueCategory.addWidget(self._rawVariable.name, w)

        # access level
        cb = QComboBox()
        cb.addItem('public', 0)
        cb.addItem('private', 1)
        cb.addItem('protected', 2)

        def accessLevelChanged(x):
            self._rawVariable.accessLevel = AccessLevel[x]
            EditorHistory().saveState("Change variable access level",
                                      modify=True)

        cb.currentTextChanged.connect(accessLevelChanged)
        cb.setCurrentIndex(self._rawVariable.accessLevel)
        valueCategory.addWidget('Access level', cb)
        propertiesWidget.addWidget(valueCategory)

    def onFindRefsClicked(self):
        from PyFlow.App import PyFlow
        refs = [n.getWrapper() for n in self._rawVariable.findRefs()]
        app = self.variablesWidget.pyFlowInstance
        if "Search results" not in [
                t.name() for t in app.getRegisteredTools()
        ]:
            app.invokeDockToolByName("PyFlowBase", "Search results")
        self.variablesWidget.pyFlowInstance.getCanvas(
        ).requestShowSearchResults.emit(refs)

    def onKillClicked(self):
        # check refs and ask user what to do
        refs = self._rawVariable.findRefs()
        if len(refs) > 0:
            item, accepted = QInputDialog.getItem(
                None,
                'Decide!',
                'What to do with getters and setters in canvas?',
                ['kill', 'leave'],
                editable=False)
            if accepted:
                self.variablesWidget.killVar(self)
                if item == 'kill':
                    for i in refs:
                        i.kill()
                elif item == 'leave':
                    for i in refs:
                        i.var = None
        else:
            self.variablesWidget.killVar(self)

    @property
    def dataType(self):
        return self._rawVariable.dataType

    @dataType.setter
    def dataType(self, value):
        self._rawVariable.dataType = value
        self.widget.color = findPinClassByType(
            self._rawVariable.dataType).color()
        self.widget.update()
        self.variablesWidget.onUpdatePropertyView(self)

    @property
    def packageName(self):
        return self._rawVariable.packageName

    @property
    def accessLevel(self):
        return self._rawVariable.accessLevel

    @accessLevel.setter
    def accessLevel(self, value):
        self._rawVariable.accessLevel = value

    @property
    def uid(self):
        return self._rawVariable.uid

    @uid.setter
    def uid(self, value):
        self._rawVariable.uid = value
        if self._rawVariable.uid in self.graph.getVars():
            self.graph.getVars().pop(self._rawVariable.uid)
            self.graph.getVars()[self._rawVariable.uid] = self._rawVariable

    @staticmethod
    def jsonTemplate():
        template = {
            'name': None,
            'uuid': None,
            'value': None,
            'type': None,
            'package': None,
            'accessLevel': None
        }
        return template

    def serialize(self):
        pinClass = findPinClassByType(self._rawVariable.dataType)

        template = UIVariable.jsonTemplate()
        template['name'] = self._rawVariable.name
        template['uuid'] = str(self._rawVariable.uid)

        if self._rawVariable.dataType == "AnyPin":
            # don't save any variables
            # value will be calculated for this type of variables
            template['value'] = None
        else:
            template['value'] = json.dumps(self._rawVariable.value,
                                           cls=pinClass.jsonEncoderClass())

        template['type'] = self._rawVariable.dataType
        template['package'] = self._rawVariable.packageName
        template['accessLevel'] = self._rawVariable.accessLevel.value
        return template

    @staticmethod
    def deserialize(data, graph):
        pinClass = findPinClassByType(data['dataType'])

        varUid = uuid.UUID(data['uuid'])
        var = graph.getApp().variablesWidget.createVariable(
            dataType=data['dataType'],
            accessLevel=AccessLevel(data['accessLevel']),
            uid=varUid)
        var.setName(data['name'])
        var.setDataType(data['dataType'])

        if data['dataType'] == 'AnyPin':
            var.value = getPinDefaultValueByType('AnyPin')
        else:
            var.value = json.loads(data['value'],
                                   cls=pinClass.jsonDecoderClass())

        return var

    @property
    def value(self):
        return self._rawVariable.value

    @value.setter
    def value(self, data):
        self._rawVariable.value = data

    def mousePressEvent(self, event):
        super(UIVariable, self).mousePressEvent(event)
        self.variablesWidget.onUpdatePropertyView(self)

    def setName(self, name):
        self._rawVariable.name = name
        self.labelName.setText(self._rawVariable.name)
Example #3
0
class VariableBase(QWidget):
    ## executed when value been set
    valueChanged = QtCore.Signal()
    ## executed when name been changed
    nameChanged = QtCore.Signal(str)
    ## executed when variable been killed
    killed = QtCore.Signal()
    ## executed when variable data type been changed
    dataTypeChanged = QtCore.Signal(int)
    ## executed when variable access level been changed
    accessLevelChanged = QtCore.Signal(int)

    def __init__(self,
                 name,
                 value,
                 graph,
                 varsListWidget,
                 dataType=DataTypes.Bool,
                 uid=None):
        super(VariableBase, self).__init__()
        self._accessLevel = AccessLevel.public
        # ui
        self.horizontalLayout = QHBoxLayout(self)
        self.horizontalLayout.setSpacing(1)
        self.horizontalLayout.setContentsMargins(1, 1, 1, 1)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.widget = TypeWidget(Colors.Bool, self)
        self.widget.setObjectName("widget")
        self.horizontalLayout.addWidget(self.widget)
        self.labelName = QLabel(self)
        self.labelName.setObjectName("labelName")
        self.horizontalLayout.addWidget(self.labelName, 1)
        spacerItem = QSpacerItem(1, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)

        QtCore.QMetaObject.connectSlotsByName(self)
        # body
        self.varsListWidget = varsListWidget
        self.name = None
        self._value = value
        self.dataType = dataType
        self._uid = uid
        if self._uid is None:
            self._uid = uuid4()
        self.graph = graph
        self.setName(name)
        self.types = [
            v.name for v in list(DataTypes)
            if v not in [DataTypes.Reference, DataTypes.Exec, DataTypes.Enum]
        ]
        self.graph.vars[self.uid] = self

    @property
    def accessLevel(self):
        return self._accessLevel

    @accessLevel.setter
    def accessLevel(self, value):
        self._accessLevel = value
        self.accessLevelChanged.emit(value)

    @property
    def uid(self):
        return self._uid

    @uid.setter
    def uid(self, value):
        self._uid = value
        if self._uid in self.graph.vars:
            self.graph.vars.pop(self._uid)
            self.graph.vars[self._uid] = self

    @staticmethod
    def jsonTemplate():
        template = {'name': None, 'uuid': None, 'value': None, 'type': None}
        return template

    def serialize(self):
        template = VariableBase.jsonTemplate()
        template['name'] = self.name
        template['uuid'] = str(self.uid)
        template['value'] = self.value
        template['type'] = int(self.dataType)
        template['accessLevel'] = int(self.accessLevel)
        return template

    @staticmethod
    def deserialize(data, graph):
        var = graph.parent.variablesWidget.createVariable(
            uuid.UUID(data['uuid']))
        var.setName(data['name'])
        var.setDataType(data['type'])
        var.value = data['value']
        var.accessLevel = data['accessLevel']
        return var

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, data):
        self._value = data
        self.valueChanged.emit()

    ## Changes variable data type and updates [TypeWidget](@ref PyFlow.Core.Variable.TypeWidget) color
    # @bug in the end of this method we clear undo stack, but we should not. We do this because undo redo goes crazy
    def setDataType(self, dataType, _bJustSpawned=False):
        self.dataType = dataType
        #print self.dataType
        try:
            self.widget.color = Pins.findPinClassByType(self.dataType).color()

            self.value = Pins.findPinClassByType(
                self.dataType).pinDataTypeHint()[1]
        except:
            pass
        self.widget.update()
        if _bJustSpawned:
            return
        self.dataTypeChanged.emit(self.dataType)
        self.graph.undoStack.clear()
        self.graph.tryFillPropertiesView(self)

    def mousePressEvent(self, event):
        QWidget.mousePressEvent(self, event)
        self.graph.tryFillPropertiesView(self)

    def setName(self, name):
        self.labelName.setText(name)
        self.name = name
        self.nameChanged.emit(str(name))

    def onUpdatePropertyView(self, formLayout):
        # name
        le_name = QLineEdit(self.name)
        le_name.returnPressed.connect(lambda: self.setName(le_name.text()))
        formLayout.addRow("Name", le_name)

        # data type
        cbTypes = VarTypeComboBox(self)
        formLayout.addRow("Type", cbTypes)

        # current value
        def valSetter(x):
            self.value = x

        w = InputWidgets.getInputWidget(
            self.dataType, valSetter,
            Pins.getPinDefaultValueByType(self.dataType), None)
        if w:
            w.setWidgetValue(self.value)
            w.setObjectName(self.name)
            formLayout.addRow(self.name, w)
        # access level
        cb = QComboBox()
        cb.addItem('public', 0)
        cb.addItem('private', 1)
        cb.addItem('protected', 2)

        def accessLevelChanged(x):
            self.accessLevel = x

        cb.currentIndexChanged[int].connect(accessLevelChanged)
        cb.setCurrentIndex(self.accessLevel)
        formLayout.addRow('Access level', cb)
Example #4
0
class UIVariable(QWidget, IPropertiesViewSupport):
    def __init__(self, rawVariable, variablesWidget, parent=None):
        super(UIVariable, self).__init__(parent)
        self._rawVariable = rawVariable
        self.variablesWidget = variablesWidget

        # ui
        self.horizontalLayout = QHBoxLayout(self)
        self.horizontalLayout.setSpacing(1)
        self.horizontalLayout.setContentsMargins(1, 1, 1, 1)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.widget = TypeWidget(
            findPinClassByType(self._rawVariable.dataType).color(), self)
        self.widget.setObjectName("widget")
        self.horizontalLayout.addWidget(self.widget)
        self.labelName = QLabel(self)
        self.labelName.setObjectName("labelName")
        self.horizontalLayout.addWidget(self.labelName)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        # find refs
        self.pbFindRefs = QPushButton("")
        self.pbFindRefs.setIcon(
            QtGui.QIcon(RESOURCES_DIR + "/searching-magnifying-glass.png"))
        self.pbFindRefs.setObjectName("pbFindRefs")
        self.horizontalLayout.addWidget(self.pbFindRefs)
        self.pbFindRefs.clicked.connect(self.onFindRefsClicked)
        #  kill variable
        self.pbKill = QPushButton("")
        self.pbKill.setIcon(QtGui.QIcon(RESOURCES_DIR + "/delete_icon.png"))
        self.pbKill.setObjectName("pbKill")
        self.horizontalLayout.addWidget(self.pbKill)
        self.pbKill.clicked.connect(self.onKillClicked)

        QtCore.QMetaObject.connectSlotsByName(self)
        self.setName(self._rawVariable.name)

    def createPropertiesWidget(self, propertiesWidget):
        baseCategory = CollapsibleFormWidget(headName="Base")
        # name
        le_name = QLineEdit(self._rawVariable.name)
        le_name.returnPressed.connect(lambda: self.setName(le_name.text()))
        baseCategory.addWidget("Name", le_name)

        # data type
        cbTypes = VarTypeComboBox(self)
        baseCategory.addWidget("Type", cbTypes)
        propertiesWidget.addWidget(baseCategory)

        valueCategory = CollapsibleFormWidget(headName="Value")

        # current value
        def valSetter(x):
            self._rawVariable.value = x

        w = createInputWidget(
            self._rawVariable.dataType, valSetter,
            getPinDefaultValueByType(self._rawVariable.dataType))
        if w:
            w.setWidgetValue(self._rawVariable.value)
            w.setObjectName(self._rawVariable.name)
            valueCategory.addWidget(self._rawVariable.name, w)

        # access level
        cb = QComboBox()
        cb.addItem('public', 0)
        cb.addItem('private', 1)
        cb.addItem('protected', 2)

        def accessLevelChanged(x):
            self._rawVariable.accessLevel = AccessLevel[x]

        cb.currentTextChanged.connect(accessLevelChanged)
        cb.setCurrentIndex(self._rawVariable.accessLevel)
        valueCategory.addWidget('Access level', cb)
        propertiesWidget.addWidget(valueCategory)

    def onFindRefsClicked(self):
        refs = self._rawVariable.findRefs()
        print(refs)

    def onKillClicked(self):
        # check refs and ask user what to do
        refs = self._rawVariable.findRefs()
        if len(refs) > 0:
            item, accepted = QInputDialog.getItem(
                None,
                'Decide!',
                'What to do with getters and setters in canvas?',
                ['kill', 'leave'],
                editable=False)
            if accepted:
                if item == 'kill':
                    self.variablesWidget.killVar(self)
                elif item == 'leave':
                    # mark node as invalid
                    # TODO: For future. Like in ue4, if variable is removed, it can be recreated from node (e.g. promote to variable)
                    print('leave')
        else:
            self.variablesWidget.killVar(self)

    @property
    def dataType(self):
        return self._rawVariable.dataType

    @dataType.setter
    def dataType(self, value):
        self._rawVariable.dataType = value

    @property
    def packageName(self):
        return self._rawVariable.packageName

    @property
    def accessLevel(self):
        return self._rawVariable.accessLevel

    @accessLevel.setter
    def accessLevel(self, value):
        self._rawVariable.accessLevel = value

    @property
    def uid(self):
        return self._rawVariable.uid

    @uid.setter
    def uid(self, value):
        self._rawVariable.uid = value
        if self._rawVariable.uid in self.graph.vars:
            self.graph.vars.pop(self._rawVariable.uid)
            self.graph.vars[self._rawVariable.uid] = self._rawVariable

    @staticmethod
    def jsonTemplate():
        template = {
            'name': None,
            'uuid': None,
            'value': None,
            'type': None,
            'package': None,
            'accessLevel': None
        }
        return template

    def serialize(self):
        pinClass = findPinClassByType(self._rawVariable.dataType)

        template = UIVariable.jsonTemplate()
        template['name'] = self._rawVariable.name
        template['uuid'] = str(self._rawVariable.uid)

        if self._rawVariable.dataType == "AnyPin":
            # don't save any variables
            # value will be calculated for this type of variables
            template['value'] = None
        else:
            template['value'] = json.dumps(self._rawVariable.value,
                                           cls=pinClass.jsonEncoderClass())

        template['type'] = self._rawVariable.dataType
        template['package'] = self._rawVariable.packageName
        template['accessLevel'] = self._rawVariable.accessLevel.value
        return template

    @staticmethod
    def deserialize(data, graph):
        pinClass = findPinClassByType(data['dataType'])

        varUid = uuid.UUID(data['uuid'])
        # TODO: this is probably bad. Too long call chain
        var = graph.parent.variablesWidget.createVariable(
            dataType=data['dataType'],
            accessLevel=AccessLevel(data['accessLevel']),
            uid=varUid)
        var.setName(data['name'])
        var.setDataType(data['dataType'])

        if data['dataType'] == 'AnyPin':
            var.value = getPinDefaultValueByType('AnyPin')
        else:
            var.value = json.loads(data['value'],
                                   cls=pinClass.jsonDecoderClass())

        return var

    @property
    def value(self):
        return self._rawVariable.value

    @value.setter
    def value(self, data):
        self._rawVariable.value = data

    # Changes variable data type and updates [TypeWidget](@ref PyFlow.Core.Variable.TypeWidget) color
    # @bug in the end of this method we clear undo stack, but we should not. We do this because undo redo goes crazy
    def setDataType(self, dataType, _bJustSpawned=False):
        self._rawVariable.dataType = dataType
        self.widget.color = findPinClassByType(self.dataType).color()
        self.widget.update()
        if _bJustSpawned:
            return
        self.variablesWidget.onUpdatePropertyView(self)

    def mousePressEvent(self, event):
        super(UIVariable, self).mousePressEvent(event)
        self.variablesWidget.onUpdatePropertyView(self)

    def setName(self, name):
        self._rawVariable.name = name
        self.labelName.setText(self._rawVariable.name)