def onUpdatePropertyView(self, formLayout): # name le_name = QLineEdit(self.getName()) le_name.setReadOnly(True) if self.label().IsRenamable(): le_name.setReadOnly(False) le_name.returnPressed.connect(lambda: self.setName(le_name.text())) formLayout.addRow("Name", le_name) # uid leUid = QLineEdit(str(self.uid)) leUid.setReadOnly(True) #formLayout.addRow("Uuid", leUid) # type leType = QLineEdit(self.__class__.__name__) leType.setReadOnly(True) formLayout.addRow("Type", leType) # pos #le_pos = QLineEdit("{0} x {1}".format(self.pos().x(), self.pos().y())) #formLayout.addRow("Pos", le_pos) # inputs if len([i for i in self.inputs.values()]) != 0: for inp in self.inputs.values(): dataSetter = inp.call if inp.dataType == DataTypes.Exec else inp.setData if not inp.hasConnections(): w = getInputWidget(inp.dataType, dataSetter, inp.defaultValue(), inp.getUserStruct()) if w: w.setWidgetValue(inp.currentData()) w.setObjectName(inp.getName()) formLayout.addRow(inp.name, w) if inp.hasConnections(): w.setEnabled(False) w.hide() if self.asGraphSides: # outputs if len([i for i in self.outputs.values()]) != 0: for out in self.outputs.values(): dataSetter = out.call if out.dataType == DataTypes.Exec else out.setData w = getInputWidget(out.dataType, dataSetter, out.defaultValue(), out.getUserStruct()) if w: w.setWidgetValue(out.currentData()) w.setObjectName(out.getName()) formLayout.addRow(out.name, w) if out.hasConnections(): w.setEnabled(True) doc_lb = QLabel() doc_lb.setStyleSheet("background-color: black;") doc_lb.setText("Description") #formLayout.addRow("", doc_lb) doc = QTextBrowser() doc.setOpenExternalLinks(True) doc.setHtml(self.description())
def onUpdatePropertyView(self, formLayout): # name le_name = QLineEdit(self.getName()) le_name.setReadOnly(True) if self.label().IsRenamable(): le_name.setReadOnly(False) le_name.returnPressed.connect(lambda: self.setName(le_name.text())) formLayout.addRow("Name", le_name) # uid leUid = QLineEdit(str(self.uid)) leUid.setReadOnly(True) formLayout.addRow("Uuid", leUid) # type leType = QLineEdit(self.__class__.__name__) leType.setReadOnly(True) formLayout.addRow("Type", leType) # pos le_pos = QLineEdit("{0} x {1}".format(self.pos().x(), self.pos().y())) formLayout.addRow("Pos", le_pos) pb = QPushButton("...") pb.clicked.connect(self.onChangeColor) formLayout.addRow("Color", pb) doc_lb = QLabel() doc_lb.setStyleSheet("background-color: black;") doc_lb.setText("Description") formLayout.addRow("", doc_lb) doc = QTextBrowser() doc.setOpenExternalLinks(True) doc.setHtml(self.description()) formLayout.addRow("", doc)
class DockTitleBar(QWidget, object): def __init__(self, dock_widget, renamable=False): super(DockTitleBar, self).__init__(dock_widget) self._renamable = renamable main_layout = QHBoxLayout() main_layout.setContentsMargins(0, 0, 0, 1) self.setLayout(main_layout) self._buttons_box = QGroupBox('') self._buttons_box.setObjectName('Docked') self._buttons_layout = QHBoxLayout() self._buttons_layout.setSpacing(1) self._buttons_layout.setMargin(2) self._buttons_box.setLayout(self._buttons_layout) main_layout.addWidget(self._buttons_box) self._title_label = QLabel(self) self._title_label.setStyleSheet('background: transparent') self._title_edit = QLineEdit(self) self._title_edit.setVisible(False) self._button_size = QSize(14, 14) self._dock_btn = QToolButton(self) self._dock_btn.setIcon(resources.icon('restore_window', theme='color')) self._dock_btn.setMaximumSize(self._button_size) self._dock_btn.setAutoRaise(True) self._close_btn = QToolButton(self) self._close_btn.setIcon(resources.icon('close_window', theme='color')) self._close_btn.setMaximumSize(self._button_size) self._close_btn.setAutoRaise(True) self._buttons_layout.addSpacing(2) self._buttons_layout.addWidget(self._title_label) self._buttons_layout.addWidget(self._title_edit) self._buttons_layout.addStretch() self._buttons_layout.addSpacing(5) self._buttons_layout.addWidget(self._dock_btn) self._buttons_layout.addWidget(self._close_btn) self._buttons_box.mouseDoubleClickEvent = self.mouseDoubleClickEvent self._buttons_box.mousePressEvent = self.mousePressEvent self._buttons_box.mouseMoveEvent = self.mouseMoveEvent self._buttons_box.mouseReleaseEvent = self.mouseReleaseEvent dock_widget.featuresChanged.connect(self._on_dock_features_changed) self._title_edit.editingFinished.connect(self._on_finish_edit) self._dock_btn.clicked.connect(self._on_dock_btn_clicked) self._close_btn.clicked.connect(self._on_close_btn_clicked) self._on_dock_features_changed(dock_widget.features()) self.set_title(dock_widget.windowTitle()) dock_widget.installEventFilter(self) dock_widget.topLevelChanged.connect(self._on_change_floating_style) @property def renamable(self): return self._renamable @renamable.setter def renamable(self, flag): self._renamable = flag def eventFilter(self, obj, event): if event.type() == QEvent.WindowTitleChange: self.set_title(obj.windowTitle()) return super(DockTitleBar, self).eventFilter(obj, event) def mouseMoveEvent(self, event): event.ignore() def mousePressEvent(self, event): event.ignore() def mouseReleaseEvent(self, event): event.ignore() def mouseDoubleClickEvent(self, event): if event.pos().x() <= self._title_label.width() and self._renamable: self._start_edit() else: super(DockTitleBar, self).mouseDoubleClickEvent(event) def update(self, *args, **kwargs): self._on_change_floating_style(self.parent().isFloating()) super(DockTitleBar, self).update(*args, **kwargs) def set_title(self, title): self._title_label.setText(title) self._title_edit.setText(title) def add_button(self, button): button.setAutoRaise(True) button.setMaximumSize(self._button_size) self._buttons_layout.insertWidget(5, button) def _start_edit(self): self._title_label.hide() self._title_edit.show() self._title_edit.setFocus() def _finish_edit(self): self._title_edit.hide() self._title_label.show() self.parent().setWindowTitle(self._title_edit.text()) def _on_dock_features_changed(self, features): if not features & QDockWidget.DockWidgetVerticalTitleBar: self._close_btn.setVisible(features & QDockWidget.DockWidgetClosable) self._dock_btn.setVisible(features & QDockWidget.DockWidgetFloatable) else: raise ValueError('Vertical title bar is not supported!') def _on_finish_edit(self): self._finish_edit() def _on_dock_btn_clicked(self): self.parent().setFloating(not self.parent().isFloating()) def _on_close_btn_clicked(self): self.parent().toggleViewAction().setChecked(False) self.parent().close() def _on_change_floating_style(self, state): pass
class BaseColorDialog(BaseDialog, object): def_title = 'Select Color' maya_colors = [(.467, .467, .467), (.000, .000, .000), (.247, .247, .247), (.498, .498, .498), (0.608, 0, 0.157), (0, 0.016, 0.373), (0, 0, 1), (0, 0.275, 0.094), (0.145, 0, 0.263), (0.78, 0, 0.78), (0.537, 0.278, 0.2), (0.243, 0.133, 0.122), (0.6, 0.145, 0), (1, 0, 0), (0, 1, 0), (0, 0.255, 0.6), (1, 1, 1), (1, 1, 0), (0.388, 0.863, 1), (0.263, 1, 0.635), (1, 0.686, 0.686), (0.89, 0.675, 0.475), (1, 1, 0.384), (0, 0.6, 0.325), (0.627, 0.412, 0.188), (0.62, 0.627, 0.188), (0.408, 0.627, 0.188), (0.188, 0.627, 0.365), (0.188, 0.627, 0.627), (0.188, 0.404, 0.627), (0.435, 0.188, 0.627), (0.627, 0.188, 0.404)] def __init__(self, name='MayaColorDialog', parent=None, **kwargs): parent = parent or dcc.get_main_window() super(BaseColorDialog, self).__init__(name=name, parent=parent, **kwargs) self._color = None def get_color(self): return self._color color = property(get_color) def ui(self): self.color_buttons = list() super(BaseColorDialog, self).ui() grid_layout = layouts.GridLayout() grid_layout.setAlignment(Qt.AlignTop) self.main_layout.addLayout(grid_layout) color_index = 0 for i in range(0, 4): for j in range(0, 8): color_btn = QPushButton() color_btn.setMinimumHeight(35) color_btn.setMinimumWidth(35) self.color_buttons.append(color_btn) color_btn.setStyleSheet( 'background-color:rgb(%s,%s,%s);' % (self.maya_colors[color_index][0] * 255, self.maya_colors[color_index][1] * 255, self.maya_colors[color_index][2] * 255)) grid_layout.addWidget(color_btn, i, j) color_index += 1 selected_color_layout = layouts.HorizontalLayout() self.main_layout.addLayout(selected_color_layout) self.color_slider = QSlider(Qt.Horizontal) self.color_slider.setMinimum(0) self.color_slider.setMaximum(31) self.color_slider.setValue(2) self.color_slider.setStyleSheet( "QSlider::groove:horizontal {border: 1px solid #999999;height: 25px; /* the groove expands " "to the size of the slider by default. by giving it a height, it has a fixed size */background: " "qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);margin: 2px 0;}" "QSlider::handle:horizontal {background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4," " stop:1 #8f8f8f);border: 1px solid #5c5c5c;width: 10px;margin: -2px 0; /* handle is placed by " "default on the contents rect of the groove. Expand outside the groove */border-radius: 1px;}" ) selected_color_layout.addWidget(self.color_slider) color_label_layout = layouts.HorizontalLayout(margins=(10, 10, 10, 10)) self.main_layout.addLayout(color_label_layout) self.color_lbl = QLabel() self.color_lbl.setStyleSheet( "border: 1px solid black; background-color:rgb(0, 0, 0);") self.color_lbl.setMinimumWidth(45) self.color_lbl.setMaximumWidth(80) self.color_lbl.setMinimumHeight(80) self.color_lbl.setAlignment(Qt.AlignCenter) color_label_layout.addWidget(self.color_lbl) bottom_layout = layouts.HorizontalLayout() bottom_layout.setAlignment(Qt.AlignRight) self.main_layout.addLayout(bottom_layout) self.ok_btn = QPushButton('Ok') self.cancel_btn = QPushButton('Cancel') bottom_layout.addLayout(dividers.DividerLayout()) bottom_layout.addWidget(self.ok_btn) bottom_layout.addWidget(self.cancel_btn) def setup_signals(self): for i, btn in enumerate(self.color_buttons): btn.clicked.connect(partial(self._on_set_color, i)) self.color_slider.valueChanged.connect(self._on_set_color) self.ok_btn.clicked.connect(self._on_ok_btn) self.cancel_btn.clicked.connect(self._on_cancel_btn) def _on_set_color(self, color_index): self.color_lbl.setStyleSheet('background-color:rgb(%s,%s,%s);' % (self.maya_colors[color_index][0] * 255, self.maya_colors[color_index][1] * 255, self.maya_colors[color_index][2] * 255)) self.color_slider.setValue(color_index) def _on_set_slider(self, color_index): self._set_color(color_index=color_index) def _on_ok_btn(self): self._color = self.color_slider.value() self.close() def _on_cancel_btn(self): self._color = None self.close()
def _addPin(self, pinDirection, dataType, foo, hideLabel=False, bCreateInputWidget=True, name='', index=-1, userStructClass=ENone, defaultValue=None): # check if pins with this name already exists and get uniq name name = self.getUniqPinName(name) p = CreatePin(name, self, dataType, pinDirection, userStructClass=userStructClass) if defaultValue is not None: p.setDefaultValue(defaultValue) self.graph().pins[p.uid] = p if pinDirection == PinDirection.Input and foo is not None: p.call = foo connector_name = QGraphicsProxyWidget() connector_name.setObjectName('{0}PinConnector'.format(name)) connector_name.setContentsMargins(0, 0, 0, 0) lblName = name if hideLabel: lblName = '' p.bLabelHidden = True lbl = QLabel(lblName) p.nameChanged.connect(lbl.setText) lbl.setContentsMargins(0, 0, 0, 0) lbl.setAttribute(QtCore.Qt.WA_TranslucentBackground) font = QtGui.QFont('Consolas') color = Colors.PinNameColor font.setPointSize(6) lbl.setFont(font) style = 'color: rgb({0}, {1}, {2}, {3});'.format( color.red(), color.green(), color.blue(), color.alpha()) lbl.setStyleSheet(style) connector_name.setWidget(lbl) if pinDirection == PinDirection.Input: container = self.addContainer(pinDirection) if hideLabel: container.setMinimumWidth(15) lbl.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) container.layout().addItem(p) p._container = container container.layout().addItem(connector_name) self.inputs[p.uid] = p self.inputsLayout.insertItem(index, container) container.adjustSize() elif pinDirection == PinDirection.Output: container = self.addContainer(pinDirection) if hideLabel: container.setMinimumWidth(15) lbl.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTop) container.layout().addItem(connector_name) container.layout().addItem(p) p._container = container self.outputs[p.uid] = p self.outputsLayout.insertItem(index, container) container.adjustSize() p.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) # create member if created in runtime if not hasattr(self, name): setattr(self, name, p) return p
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)