From 78bf7dcdbf1e9af50f50a39c465332773f7529e2 Mon Sep 17 00:00:00 2001 From: jchanvfx Date: Tue, 6 Apr 2021 23:44:16 +1200 Subject: [PATCH] backdrop node wrap updates. --- NodeGraphQt/base/graph.py | 23 +++++++-- NodeGraphQt/base/model.py | 3 +- NodeGraphQt/base/node.py | 46 ++++++++++++++++-- NodeGraphQt/base/utils.py | 6 ++- NodeGraphQt/qgraphics/node_backdrop.py | 67 +++++++++++++------------- NodeGraphQt/widgets/dialogs.py | 4 +- NodeGraphQt/widgets/stylesheet.py | 3 +- NodeGraphQt/widgets/viewer.py | 1 + 8 files changed, 103 insertions(+), 50 deletions(-) diff --git a/NodeGraphQt/base/graph.py b/NodeGraphQt/base/graph.py index f0ab1d5d..88f0721d 100644 --- a/NodeGraphQt/base/graph.py +++ b/NodeGraphQt/base/graph.py @@ -15,7 +15,7 @@ from .factory import NodeFactory from .menu import NodeGraphMenu, NodesMenu from .model import NodeGraphModel -from .node import NodeObject, BaseNode +from .node import NodeObject, BaseNode, BackdropNode from .port import Port from ..constants import (DRAG_DROP_ID, PIPE_LAYOUT_CURVED, @@ -182,7 +182,9 @@ def _wire_signals(self): self._viewer.moved_nodes.connect(self._on_nodes_moved) self._viewer.node_double_clicked.connect(self._on_node_double_clicked) self._viewer.node_name_changed.connect(self._on_node_name_changed) - self._viewer.insert_node.connect(self._insert_node) + self._viewer.node_backdrop_updated.connect( + self._on_node_backdrop_updated) + self._viewer.insert_node.connect(self._on_insert_node) # pass through translated signals. self._viewer.node_selected.connect(self._on_node_selected) @@ -190,7 +192,7 @@ def _wire_signals(self): self._on_node_selection_changed) self._viewer.data_dropped.connect(self._on_node_data_dropped) - def _insert_node(self, pipe, node_id, prev_node_pos): + def _on_insert_node(self, pipe, node_id, prev_node_pos): """ Slot function triggered when a selected node has collided with a pipe. @@ -344,6 +346,18 @@ def _on_nodes_moved(self, node_data): self._undo_stack.push(NodeMovedCmd(node, node.pos(), prev_pos)) self._undo_stack.endMacro() + def _on_node_backdrop_updated(self, node_id, update_property, value): + """ + called when a BackdropNode is updated. + + Args: + node_id (str): backdrop node id. + value (str): update type. + """ + backdrop = self.get_node_by_id(node_id) + if backdrop and isinstance(backdrop, BackdropNode): + backdrop.on_backdrop_updated(update_property, value) + def _on_search_triggered(self, node_type, pos): """ called when the tab search widget is triggered in the viewer. @@ -859,7 +873,7 @@ def create_node(self, node_type, name=None, selected=True, color=None, pos (list[int, int]): initial x, y position for the node (default: ``(0, 0)``). Returns: - NodeGraphQt.BaseNode: the created instance of the node. + NodeGraphQt.NodeObject: the created instance of the node. """ if not self._editable: return @@ -903,6 +917,7 @@ def format_color(clr): else: node.set_parent(None) + # update the node view from model. node.update() undo_cmd = NodeAddedCmd(self, node, node.model.pos) diff --git a/NodeGraphQt/base/model.py b/NodeGraphQt/base/model.py index 87f45ee5..4af3074c 100644 --- a/NodeGraphQt/base/model.py +++ b/NodeGraphQt/base/model.py @@ -160,8 +160,7 @@ def set_property(self, name, value): elif name in self._custom_prop.keys(): self._custom_prop[name] = value else: - self.add_property(name, value) - # raise NodePropertyError('No property "{}"'.format(name)) + raise NodePropertyError('No property "{}"'.format(name)) def get_property(self, name): if name in self.properties.keys(): diff --git a/NodeGraphQt/base/node.py b/NodeGraphQt/base/node.py index ef95ecd5..31ab5836 100644 --- a/NodeGraphQt/base/node.py +++ b/NodeGraphQt/base/node.py @@ -1,4 +1,6 @@ #!/usr/bin/python +from collections import OrderedDict + from .commands import PropertyChangedCmd from .model import NodeModel from .port import Port @@ -1107,7 +1109,7 @@ def connected_input_nodes(self): Returns: dict: {: } """ - nodes = {} + nodes = OrderedDict() for p in self.input_ports(): nodes[p] = [cp.node() for cp in p.connected_ports()] return nodes @@ -1119,7 +1121,7 @@ def connected_output_nodes(self): Returns: dict: {: } """ - nodes = {} + nodes = OrderedDict() for p in self.output_ports(): nodes[p] = [cp.node() for cp in p.connected_ports()] return nodes @@ -1212,20 +1214,54 @@ def __init__(self): self.create_property('backdrop_text', '', widget_type=NODE_PROP_QTEXTEDIT, tab='Backdrop') + def on_backdrop_updated(self, update_prop, value=None): + """ + Slot triggered by the "on_backdrop_updated" signal from + the node graph. + + Args: + update_prop (str): update property type. + value (object): update value (optional) + """ + if update_prop == 'sizer_mouse_release': + self.graph.begin_undo('resized "{}"'.format(self.name())) + self.set_property('width', value['width']) + self.set_property('height', value['height']) + self.set_pos(*value['pos']) + self.graph.end_undo() + elif update_prop == 'sizer_double_clicked': + self.graph.begin_undo('"{}" auto resize'.format(self.name())) + self.set_property('width', value['width']) + self.set_property('height', value['height']) + self.set_pos(*value['pos']) + self.graph.end_undo() + def auto_size(self): """ Auto resize the backdrop node to fit around the intersecting nodes. """ - self.view.auto_resize() + self.graph.begin_undo('"{}" auto resize'.format(self.name())) + size = self.view.calc_backdrop_size() + self.set_property('width', size['width']) + self.set_property('height', size['height']) + self.set_pos(*size['pos']) + self.graph.end_undo() def wrap_nodes(self, nodes): """ - Wrap backdrop size to fit around specified nodes. + Set the backdrop size to fit around specified nodes. Args: nodes (list[NodeGraphQt.NodeObject]): list of nodes. """ - self.view.auto_resize([n.view for n in nodes]) + if not nodes: + return + self.graph.begin_undo('"{}" wrap nodes'.format(self.name())) + size = self.view.calc_backdrop_size([n.view for n in nodes]) + self.set_property('width', size['width']) + self.set_property('height', size['height']) + self.set_pos(*size['pos']) + self.graph.end_undo() def nodes(self): """ diff --git a/NodeGraphQt/base/utils.py b/NodeGraphQt/base/utils.py index 5ccdc71c..000381c3 100644 --- a/NodeGraphQt/base/utils.py +++ b/NodeGraphQt/base/utils.py @@ -86,8 +86,10 @@ def setup_context_menu(graph): edit_menu.add_separator() - edit_menu.add_command('Layout Graph Up Stream', _layout_graph_up, 'L') - edit_menu.add_command('Layout Graph Down Stream', _layout_graph_down, 'Ctrl+L') + edit_menu.add_command( + 'Layout Nodes Up Stream', _layout_graph_up, 'L') + edit_menu.add_command( + 'Layout Nodes Down Stream', _layout_graph_down, 'Ctrl+L') edit_menu.add_separator() diff --git a/NodeGraphQt/qgraphics/node_backdrop.py b/NodeGraphQt/qgraphics/node_backdrop.py index 8acbc968..b0f47a2d 100644 --- a/NodeGraphQt/qgraphics/node_backdrop.py +++ b/NodeGraphQt/qgraphics/node_backdrop.py @@ -53,6 +53,19 @@ def itemChange(self, change, value): def mouseDoubleClickEvent(self, event): item = self.parentItem() item.on_sizer_double_clicked() + super(BackdropSizer, self).mouseDoubleClickEvent(event) + + def mousePressEvent(self, event): + self.__prev_xy = (self.pos().x(), self.pos().y()) + super(BackdropSizer, self).mousePressEvent(event) + + def mouseReleaseEvent(self, event): + current_xy = (self.pos().x(), self.pos().y()) + if current_xy != self.__prev_xy: + item = self.parentItem() + item.on_sizer_pos_mouse_release() + del self.__prev_xy + super(BackdropSizer, self).mouseReleaseEvent(event) def paint(self, painter, option, widget): """ @@ -143,8 +156,18 @@ def on_sizer_pos_changed(self, pos): self._width = pos.x() + self._sizer.size self._height = pos.y() + self._sizer.size + def on_sizer_pos_mouse_release(self): + size = { + 'pos': self.xy_pos, + 'width': self._width, + 'height': self._height} + self.viewer().node_backdrop_updated.emit( + self.id, 'sizer_mouse_release', size) + def on_sizer_double_clicked(self): - self.auto_resize() + size = self.calc_backdrop_size() + self.viewer().node_backdrop_updated.emit( + self.id, 'sizer_double_clicked', size) def paint(self, painter, option, widget): """ @@ -217,39 +240,17 @@ def get_nodes(self, inc_intersects=False): nodes.append(item) return nodes - def auto_resize(self, nodes=None): + def calc_backdrop_size(self, nodes=None): nodes = nodes or self.get_nodes(True) - if nodes: - padding = 40 - nodes_rect = self._combined_rect(nodes) - self.xy_pos = [nodes_rect.x() - padding, nodes_rect.y() - padding] - self._sizer.set_pos(nodes_rect.width() + (padding * 2), - nodes_rect.height() + (padding * 2)) - return - - width, height = self._min_size - self._sizer.set_pos(width, height) - - def pre_init(self, viewer, pos=None): - """ - Called before node has been added into the scene. - - Args: - viewer (NodeGraphQt.widgets.viewer.NodeViewer): main viewer. - pos (tuple): cursor pos. - """ - nodes = viewer.selected_nodes() - if nodes: - padding = 40 - scene = viewer.scene() - group = scene.createItemGroup(nodes) - rect = group.boundingRect() - scene.destroyItemGroup(group) - self.xy_pos = [rect.x() - padding, rect.y() - padding] - self._sizer.set_pos(rect.width() + (padding * 2), - rect.height() + (padding * 2)) - else: - self.xy_pos = pos + padding = 40 + nodes_rect = self._combined_rect(nodes) + return { + 'pos': [ + nodes_rect.x() - padding, nodes_rect.y() - padding + ], + 'width': nodes_rect.width() + (padding * 2), + 'height': nodes_rect.height() + (padding * 2) + } @property def minimum_size(self): diff --git a/NodeGraphQt/widgets/dialogs.py b/NodeGraphQt/widgets/dialogs.py index 14d0855a..7d1e36ce 100644 --- a/NodeGraphQt/widgets/dialogs.py +++ b/NodeGraphQt/widgets/dialogs.py @@ -64,5 +64,5 @@ def question_dialog(text, title): dlg.setStandardButtons( QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No ) - dlg.exec_() - return bool(dlg == QtWidgets.QMessageBox.Yes) + result = dlg.exec_() + return bool(result == QtWidgets.QMessageBox.Yes) diff --git a/NodeGraphQt/widgets/stylesheet.py b/NodeGraphQt/widgets/stylesheet.py index c0ee7407..57efc895 100644 --- a/NodeGraphQt/widgets/stylesheet.py +++ b/NodeGraphQt/widgets/stylesheet.py @@ -195,8 +195,7 @@ ''' STYLE_MESSAGEBOX = ''' -QLabel{ - min-width:500 px; +QLabel{ font-size: 18px; background-color: transparent; color: rgb(200 ,200, 200); diff --git a/NodeGraphQt/widgets/viewer.py b/NodeGraphQt/widgets/viewer.py index 5f623ac9..c40312ba 100644 --- a/NodeGraphQt/widgets/viewer.py +++ b/NodeGraphQt/widgets/viewer.py @@ -38,6 +38,7 @@ class NodeViewer(QtWidgets.QGraphicsView): insert_node = QtCore.Signal(object, str, dict) need_show_tab_search = QtCore.Signal() node_name_changed = QtCore.Signal(str, str) + node_backdrop_updated = QtCore.Signal(str, str, object) # pass through signals that are translated into "NodeGraph()" signals. node_selected = QtCore.Signal(str)