class NodeProperty(PropertyDialog): """ This class implements the 'Node property' dialog. """ def __init__(self, diagram, node, session): """ Initialize the node properties dialog. :type diagram: Diagram :type node: AbstractNode :type session: Session """ super().__init__(session) self.diagram = diagram self.node = node ############################################# # GENERAL TAB ################################# self.idLabel = QtWidgets.QLabel(self) self.idLabel.setFont(Font('Roboto', 12)) self.idLabel.setText('ID') self.idField = StringField(self) self.idField.setFont(Font('Roboto', 12)) self.idField.setFixedWidth(300) self.idField.setFocusPolicy(QtCore.Qt.NoFocus) self.idField.setReadOnly(True) self.idField.setValue(self.node.id) self.typeLabel = QtWidgets.QLabel(self) self.typeLabel.setFont(Font('Roboto', 12)) self.typeLabel.setText('Type') self.typeField = StringField(self) self.typeField.setFont(Font('Roboto', 12)) self.typeField.setFocusPolicy(QtCore.Qt.NoFocus) self.typeField.setFixedWidth(300) self.typeField.setReadOnly(True) self.typeField.setValue(node.shortName.capitalize()) self.identityLabel = QtWidgets.QLabel(self) self.identityLabel.setFont(Font('Roboto', 12)) self.identityLabel.setText('Identity') self.identityField = StringField(self) self.identityField.setFont(Font('Roboto', 12)) self.identityField.setFocusPolicy(QtCore.Qt.NoFocus) self.identityField.setFixedWidth(300) self.identityField.setReadOnly(True) self.identityField.setValue(self.node.identityName) self.neighboursLabel = QtWidgets.QLabel(self) self.neighboursLabel.setFont(Font('Roboto', 12)) self.neighboursLabel.setText('Neighbours') self.neighboursField = IntegerField(self) self.neighboursField.setFont(Font('Roboto', 12)) self.neighboursField.setFocusPolicy(QtCore.Qt.NoFocus) self.neighboursField.setFixedWidth(300) self.neighboursField.setReadOnly(True) self.neighboursField.setValue(len(self.node.adjacentNodes())) self.generalWidget = QtWidgets.QWidget() self.generalLayout = QtWidgets.QFormLayout(self.generalWidget) self.generalLayout.addRow(self.idLabel, self.idField) self.generalLayout.addRow(self.typeLabel, self.typeField) self.generalLayout.addRow(self.identityLabel, self.identityField) self.generalLayout.addRow(self.neighboursLabel, self.neighboursField) ############################################# # GEOMETRY TAB ################################# nodePos = self.node.pos() sceneRect = self.diagram.sceneRect() self.xLabel = QtWidgets.QLabel(self) self.xLabel.setFont(Font('Roboto', 12)) self.xLabel.setText('X') self.xField = SpinBox(self) self.xField.setFixedWidth(60) self.xField.setFont(Font('Roboto', 12)) self.xField.setRange(sceneRect.left(), sceneRect.right()) self.xField.setValue(int(nodePos.x())) self.yLabel = QtWidgets.QLabel(self) self.yLabel.setFont(Font('Roboto', 12)) self.yLabel.setText('Y') self.yField = SpinBox(self) self.yField.setFixedWidth(60) self.yField.setFont(Font('Roboto', 12)) self.yField.setRange(sceneRect.top(), sceneRect.bottom()) self.yField.setValue(int(nodePos.y())) self.widthLabel = QtWidgets.QLabel(self) self.widthLabel.setFont(Font('Roboto', 12)) self.widthLabel.setText('Width') self.widthField = SpinBox(self) self.widthField.setFixedWidth(60) self.widthField.setFont(Font('Roboto', 12)) self.widthField.setRange(20, sceneRect.width()) self.widthField.setReadOnly(True) self.widthField.setValue(int(self.node.width())) self.heightLabel = QtWidgets.QLabel(self) self.heightLabel.setFont(Font('Roboto', 12)) self.heightLabel.setText('Height') self.heightField = SpinBox(self) self.heightField.setFixedWidth(60) self.heightField.setFont(Font('Roboto', 12)) self.heightField.setRange(20, sceneRect.height()) self.heightField.setReadOnly(True) self.heightField.setValue(int(self.node.height())) self.geometryWidget = QtWidgets.QWidget() self.geometryLayout = QtWidgets.QFormLayout(self.geometryWidget) self.geometryLayout.addRow(self.xLabel, self.xField) self.geometryLayout.addRow(self.yLabel, self.yField) self.geometryLayout.addRow(self.widthLabel, self.widthField) self.geometryLayout.addRow(self.heightLabel, self.heightField) ############################################# # CONFIRMATION BOX ################################# self.confirmationBox = QtWidgets.QDialogButtonBox(QtCore.Qt.Horizontal, self) self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok) self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel) self.confirmationBox.setContentsMargins(10, 0, 10, 10) self.confirmationBox.setFont(Font('Roboto', 12)) ############################################# # MAIN WIDGET ################################# self.mainWidget = QtWidgets.QTabWidget(self) self.mainWidget.addTab(self.generalWidget, 'General') self.mainWidget.addTab(self.geometryWidget, 'Geometry') self.mainLayout = QtWidgets.QVBoxLayout(self) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.addWidget(self.mainWidget) self.mainLayout.addWidget(self.confirmationBox, 0, QtCore.Qt.AlignRight) self.setWindowTitle('Properties: {0}'.format(self.node)) self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy')) connect(self.confirmationBox.accepted, self.complete) connect(self.confirmationBox.rejected, self.reject) ############################################# # SLOTS ################################# @QtCore.pyqtSlot() def complete(self): """ Executed when the dialog is accepted. """ commands = [self.positionChanged()] if any(commands): self.session.undostack.beginMacro('edit {0} properties'.format(self.node.name)) for command in commands: if command: self.session.undostack.push(command) self.session.undostack.endMacro() super().accept() ############################################# # AUXILIARY METHODS ################################# def positionChanged(self): """ Move the node properly if the position has been changed. :rtype: QUndoCommand """ rect = self.diagram.sceneRect() xPos = clamp(self.xField.value(), rect.left(), rect.right()) yPos = clamp(self.yField.value(), rect.top(), rect.bottom()) pos1 = self.node.pos() pos2 = QtCore.QPointF(xPos, yPos) if pos1 != pos2: node = self.node data = { 'redo': { 'nodes': {node: {'anchors': {k: v + pos2 - pos1 for k, v in node.anchors.items()}, 'pos': pos2}}, 'edges': {}, }, 'undo': { 'nodes': {node: {'anchors': {k: v for k, v in node.anchors.items()}, 'pos': pos1}}, 'edges': {} } } return CommandNodeMove(self.diagram, data) return None
class NodeProperty(PropertyDialog): """ This class implements the 'Node property' dialog. """ def __init__(self, diagram, node, session): """ Initialize the node properties dialog. :type diagram: Diagram :type node: AbstractNode :type session: Session """ super().__init__(session) self.diagram = diagram self.node = node ############################################# # GENERAL TAB ################################# self.idLabel = QtWidgets.QLabel(self) self.idLabel.setText('ID') self.idField = StringField(self) self.idField.setFixedWidth(300) self.idField.setFocusPolicy(QtCore.Qt.NoFocus) self.idField.setReadOnly(True) self.idField.setValue(self.node.id) self.typeLabel = QtWidgets.QLabel(self) self.typeLabel.setText('Type') self.typeField = StringField(self) self.typeField.setFocusPolicy(QtCore.Qt.NoFocus) self.typeField.setFixedWidth(300) self.typeField.setReadOnly(True) self.typeField.setValue(node.shortName.capitalize()) self.identityLabel = QtWidgets.QLabel(self) self.identityLabel.setText('Identity') self.identityField = StringField(self) self.identityField.setFocusPolicy(QtCore.Qt.NoFocus) self.identityField.setFixedWidth(300) self.identityField.setReadOnly(True) self.identityField.setValue(self.node.identityName) self.neighboursLabel = QtWidgets.QLabel(self) self.neighboursLabel.setText('Neighbours') self.neighboursField = IntegerField(self) self.neighboursField.setFocusPolicy(QtCore.Qt.NoFocus) self.neighboursField.setFixedWidth(300) self.neighboursField.setReadOnly(True) self.neighboursField.setValue(len(self.node.adjacentNodes())) self.generalWidget = QtWidgets.QWidget() self.generalLayout = QtWidgets.QFormLayout(self.generalWidget) self.generalLayout.addRow(self.idLabel, self.idField) self.generalLayout.addRow(self.typeLabel, self.typeField) self.generalLayout.addRow(self.identityLabel, self.identityField) self.generalLayout.addRow(self.neighboursLabel, self.neighboursField) ############################################# # GEOMETRY TAB ################################# nodePos = self.node.pos() sceneRect = self.diagram.sceneRect() self.xLabel = QtWidgets.QLabel(self) self.xLabel.setText('X') self.xField = SpinBox(self) self.xField.setFixedWidth(60) self.xField.setRange(sceneRect.left(), sceneRect.right()) self.xField.setValue(int(nodePos.x())) self.yLabel = QtWidgets.QLabel(self) self.yLabel.setText('Y') self.yField = SpinBox(self) self.yField.setFixedWidth(60) self.yField.setRange(sceneRect.top(), sceneRect.bottom()) self.yField.setValue(int(nodePos.y())) self.widthLabel = QtWidgets.QLabel(self) self.widthLabel.setText('Width') self.widthField = SpinBox(self) self.widthField.setFixedWidth(60) self.widthField.setRange(20, sceneRect.width()) self.widthField.setReadOnly(True) self.widthField.setValue(int(self.node.width())) self.heightLabel = QtWidgets.QLabel(self) self.heightLabel.setText('Height') self.heightField = SpinBox(self) self.heightField.setFixedWidth(60) self.heightField.setRange(20, sceneRect.height()) self.heightField.setReadOnly(True) self.heightField.setValue(int(self.node.height())) self.geometryWidget = QtWidgets.QWidget() self.geometryLayout = QtWidgets.QFormLayout(self.geometryWidget) self.geometryLayout.addRow(self.xLabel, self.xField) self.geometryLayout.addRow(self.yLabel, self.yField) self.geometryLayout.addRow(self.widthLabel, self.widthField) self.geometryLayout.addRow(self.heightLabel, self.heightField) ############################################# # CONFIRMATION BOX ################################# self.confirmationBox = QtWidgets.QDialogButtonBox( QtCore.Qt.Horizontal, self) self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok) self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel) self.confirmationBox.setContentsMargins(10, 0, 10, 10) ############################################# # MAIN WIDGET ################################# self.mainWidget = QtWidgets.QTabWidget(self) self.mainWidget.addTab(self.generalWidget, 'General') self.mainWidget.addTab(self.geometryWidget, 'Geometry') self.mainLayout = QtWidgets.QVBoxLayout(self) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.addWidget(self.mainWidget) self.mainLayout.addWidget(self.confirmationBox, 0, QtCore.Qt.AlignRight) self.setWindowTitle('Properties: {0}'.format(self.node)) self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy')) connect(self.confirmationBox.accepted, self.complete) connect(self.confirmationBox.rejected, self.reject) ############################################# # SLOTS ################################# @QtCore.pyqtSlot() def complete(self): """ Executed when the dialog is accepted. """ commands = [self.positionChanged()] if any(commands): self.session.undostack.beginMacro('edit {0} properties'.format( self.node.name)) for command in commands: if command: self.session.undostack.push(command) self.session.undostack.endMacro() super().accept() ############################################# # AUXILIARY METHODS ################################# def positionChanged(self): """ Move the node properly if the position has been changed. :rtype: QUndoCommand """ rect = self.diagram.sceneRect() xPos = clamp(self.xField.value(), rect.left(), rect.right()) yPos = clamp(self.yField.value(), rect.top(), rect.bottom()) pos1 = self.node.pos() pos2 = QtCore.QPointF(xPos, yPos) if pos1 != pos2: initData = self.diagram.setupMove([self.node]) moveData = self.diagram.completeMove(initData, pos2 - pos1) return CommandNodeMove(self.diagram, initData, moveData) return None
class NodeProperty(QDialog): """ This class implements the 'Node property' dialog. """ def __init__(self, scene, node, parent=None): """ Initialize the node properties dialog. :type scene: DiagramScene :type node: AbstractNode :type parent: QWidget """ super().__init__(parent) self.node = node self.scene = scene # GENERAL self.generalWidget = QWidget() self.generalLayout = QFormLayout(self.generalWidget) self.idField = StringField(self.generalWidget) self.idField.setReadOnly(True) self.idField.setFixedWidth(300) self.idField.setValue(self.node.id) self.itemField = StringField(self.generalWidget) self.itemField.setReadOnly(True) self.itemField.setFixedWidth(300) self.itemField.setValue(node.shortname.capitalize()) self.showIdentityField = StringField(self.generalWidget) self.showIdentityField.setReadOnly(True) self.showIdentityField.setFixedWidth(300) self.showIdentityField.setValue(self.node.identity.value) self.generalLayout.addRow('ID', self.idField) self.generalLayout.addRow('Type', self.itemField) self.generalLayout.addRow('Identity', self.showIdentityField) # GEOMETRY self.geometryWidget = QWidget() self.geometryLayout = QFormLayout(self.geometryWidget) P = self.node.pos() R = self.scene.sceneRect() self.xField = SpinBox(self.geometryWidget) self.xField.setFixedWidth(60) self.xField.setRange(R.left(), R.right()) self.xField.setValue(int(P.x())) self.yField = SpinBox(self.geometryWidget) self.yField.setFixedWidth(60) self.yField.setRange(R.top(), R.bottom()) self.yField.setValue(int(P.y())) self.wField = SpinBox(self.geometryWidget) self.wField.setRange(20, R.width()) self.wField.setReadOnly(True) self.wField.setFixedWidth(60) self.wField.setValue(int(self.node.width())) self.hField = SpinBox(self.geometryWidget) self.hField.setRange(20, R.height()) self.hField.setReadOnly(True) self.hField.setFixedWidth(60) self.hField.setValue(int(self.node.height())) self.geometryLayout.addRow('X', self.xField) self.geometryLayout.addRow('Y', self.yField) self.geometryLayout.addRow('Width', self.wField) self.geometryLayout.addRow('Height', self.hField) # MAIN self.mainWidget = QTabWidget(self) self.mainWidget.addTab(self.generalWidget, 'General') self.mainWidget.addTab(self.geometryWidget, 'Geometry') self.buttonBox = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) self.mainLayout = QVBoxLayout(self) self.mainLayout.addWidget(self.mainWidget) self.mainLayout.addWidget(self.buttonBox, 0, Qt.AlignRight) self.setWindowTitle('Properties') self.setWindowIcon(QIcon(':/images/eddy')) connect(self.finished, self.completed) connect(self.buttonBox.accepted, self.accept) connect(self.buttonBox.rejected, self.reject) #################################################################################################################### # # # SLOTS # # # #################################################################################################################### @pyqtSlot(int) def completed(self, code): """ Executed when the dialog is terminated. :type code: int """ if code == QDialog.Accepted: self.positionChanged() def positionChanged(self): """ Move the node properly if the position has been changed. """ R = self.scene.sceneRect() x = clamp(self.xField.value(), R.left(), R.right()) y = clamp(self.yField.value(), R.top(), R.bottom()) pos1 = self.node.pos() pos2 = QPointF(x, y) if pos1 != pos2: commandData = { 'redo': { 'nodes': { self.node: { 'anchors': { k: v + pos2 - pos1 for k, v in self.node.anchors.items() }, 'pos': pos2, } }, 'edges': {}, }, 'undo': { 'nodes': { self.node: { 'anchors': {k: v for k, v in self.node.anchors.items()}, 'pos': pos1, } }, 'edges': {} } } self.scene.undostack.push( CommandNodeMove(scene=self.scene, data=commandData))