From 43038e7a61650872d11a64fd81f078a9fa2be1b0 Mon Sep 17 00:00:00 2001 From: arno Date: Thu, 13 Feb 2020 19:08:26 +0800 Subject: [PATCH 1/4] pass mouseClickedEvent to node widgets --- NodeGraphQt/__init__.py | 2 +- NodeGraphQt/base/model.py | 3 ++- NodeGraphQt/constants.py | 2 +- NodeGraphQt/widgets/actions.py | 4 ++-- NodeGraphQt/widgets/viewer.py | 15 ++++++++------- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/NodeGraphQt/__init__.py b/NodeGraphQt/__init__.py index 5e5ec266..06998769 100644 --- a/NodeGraphQt/__init__.py +++ b/NodeGraphQt/__init__.py @@ -30,7 +30,7 @@ # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ -**NodeGraphQt** is a node graph framework that can be implemented and re purposed +**NodeGraphQt** is a node graph Framework that can be implemented and re purposed into applications that supports **PySide2**. project: https://github.com/jchanvfx/NodeGraphQt diff --git a/NodeGraphQt/base/model.py b/NodeGraphQt/base/model.py index eb0d4f86..695fe6ca 100644 --- a/NodeGraphQt/base/model.py +++ b/NodeGraphQt/base/model.py @@ -144,7 +144,8 @@ def set_property(self, name, value): elif name in self._custom_prop.keys(): self._custom_prop[name] = value else: - raise NodePropertyError('No property "{}"'.format(name)) + self._custom_prop[name] = value + # raise NodePropertyError('No property "{}"'.format(name)) def get_property(self, name): if name in self.properties.keys(): diff --git a/NodeGraphQt/constants.py b/NodeGraphQt/constants.py index 7e5c7ae2..2d4b457c 100644 --- a/NodeGraphQt/constants.py +++ b/NodeGraphQt/constants.py @@ -4,7 +4,7 @@ from .pkg_info import __version__ from NodeGraphQt import QtWidgets -#: Current version of the NodeGraphQt framework. +#: Current version of the NodeGraphQt Framework. VERSION = __version__ # === PIPE === diff --git a/NodeGraphQt/widgets/actions.py b/NodeGraphQt/widgets/actions.py index 7b33f2b8..d11785e3 100644 --- a/NodeGraphQt/widgets/actions.py +++ b/NodeGraphQt/widgets/actions.py @@ -27,7 +27,7 @@ def get_menu(self, name, node_id=None): return menu if node_id and menu.node_class: node = menu.graph.get_node_by_id(node_id) - if isinstance(node,menu.node_class): + if isinstance(node, menu.node_class): return menu def get_menus(self, node_class): @@ -35,7 +35,7 @@ def get_menus(self, node_class): for action in self.actions(): menu = action.menu() if menu.node_class: - if issubclass(menu.node_class,node_class): + if issubclass(menu.node_class, node_class): menus.append(menu) return menus diff --git a/NodeGraphQt/widgets/viewer.py b/NodeGraphQt/widgets/viewer.py index 7d8a689a..6ca3c444 100644 --- a/NodeGraphQt/widgets/viewer.py +++ b/NodeGraphQt/widgets/viewer.py @@ -131,7 +131,7 @@ def _set_viewer_zoom(self, value, sensitivity=None, pos=None): self.scale(scale, scale, pos) def _set_viewer_pan(self, pos_x, pos_y): - speed = self._scene_range.width() * 0.002 + speed = self._scene_range.width() * 0.0015 x = -pos_x * speed y = -pos_y * speed self._scene_range.adjust(x, y, x, y) @@ -201,7 +201,7 @@ def contextMenuEvent(self, event): nodes = [i for i in items if isinstance(i, AbstractNodeItem)] if nodes: node = nodes[0] - ctx_menu = self._ctx_node_menu.get_menu(node.type_,node.id) + ctx_menu = self._ctx_node_menu.get_menu(node.type_, node.id) if ctx_menu: for action in ctx_menu.actions(): if not action.menu(): @@ -277,10 +277,11 @@ def mousePressEvent(self, event): self._rubber_band.show() # allow new live pipe with the shift modifier. - if self.LMB_state: - if (not self.SHIFT_state and not self.CTRL_state) or\ - (self.SHIFT_state and pipes): - super(NodeViewer, self).mousePressEvent(event) + # if self.LMB_state: + # if (not self.SHIFT_state and not self.CTRL_state) or\ + # (self.SHIFT_state and pipes): + if not self._LIVE_PIPE.isVisible(): + super(NodeViewer, self).mousePressEvent(event) def mouseReleaseEvent(self, event): if event.button() == QtCore.Qt.LeftButton: @@ -397,7 +398,7 @@ def wheelEvent(self, event): if delta == 0: delta = event.angleDelta().x() - self._set_viewer_zoom(delta, pos = event.pos()) + self._set_viewer_zoom(delta, pos=event.pos()) def dropEvent(self, event): pos = self.mapToScene(event.pos()) From f998135b5ad57b7313d94db12dfe0ec858cbf54b Mon Sep 17 00:00:00 2001 From: arno Date: Fri, 14 Feb 2020 13:45:56 +0800 Subject: [PATCH 2/4] small fix --- NodeGraphQt/__init__.py | 2 +- NodeGraphQt/base/graph.py | 3 ++- NodeGraphQt/constants.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/NodeGraphQt/__init__.py b/NodeGraphQt/__init__.py index 06998769..5e5ec266 100644 --- a/NodeGraphQt/__init__.py +++ b/NodeGraphQt/__init__.py @@ -30,7 +30,7 @@ # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ -**NodeGraphQt** is a node graph Framework that can be implemented and re purposed +**NodeGraphQt** is a node graph framework that can be implemented and re purposed into applications that supports **PySide2**. project: https://github.com/jchanvfx/NodeGraphQt diff --git a/NodeGraphQt/base/graph.py b/NodeGraphQt/base/graph.py index 182378f1..40150690 100644 --- a/NodeGraphQt/base/graph.py +++ b/NodeGraphQt/base/graph.py @@ -748,7 +748,7 @@ def add_node(self, node, pos=None): node_attrs[node.type_][pname].update(pattrs) self.model.set_node_common_properties(node_attrs) - node._graph = self + node.set_graph(self) node.NODE_NAME = self.get_unique_name(node.NODE_NAME) node.model._graph_model = self.model node.model.name = node.NODE_NAME @@ -980,6 +980,7 @@ def _deserialize(self, data, relative_pos=False, pos=None): nodes[n_id] = node self.add_node(node, n_data.get('pos')) + node.set_graph(self) # build the connections. for connection in data.get('connections', []): diff --git a/NodeGraphQt/constants.py b/NodeGraphQt/constants.py index 2d4b457c..7e5c7ae2 100644 --- a/NodeGraphQt/constants.py +++ b/NodeGraphQt/constants.py @@ -4,7 +4,7 @@ from .pkg_info import __version__ from NodeGraphQt import QtWidgets -#: Current version of the NodeGraphQt Framework. +#: Current version of the NodeGraphQt framework. VERSION = __version__ # === PIPE === From dd46688818f386a048c56e8e2df84850d9f66443 Mon Sep 17 00:00:00 2001 From: arno Date: Sat, 15 Feb 2020 20:24:36 +0800 Subject: [PATCH 3/4] solve NODE_PROP_BUTTON function link issue --- NodeGraphQt/base/model.py | 9 +++++++- NodeGraphQt/base/node.py | 13 +++++------ NodeGraphQt/widgets/properties.py | 8 +++++-- example_auto_nodes/node_base/auto_node.py | 27 ++++++++++++++--------- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/NodeGraphQt/base/model.py b/NodeGraphQt/base/model.py index 695fe6ca..4da929dd 100644 --- a/NodeGraphQt/base/model.py +++ b/NodeGraphQt/base/model.py @@ -92,7 +92,8 @@ def __init__(self): } def add_property(self, name, value, items=None, range=None, - widget_type=NODE_PROP, tab='Properties', ext=None): + widget_type=NODE_PROP, tab='Properties', + ext=None, funcs=None): """ add custom property. @@ -104,6 +105,7 @@ def add_property(self, name, value, items=None, range=None, widget_type (int): widget type flag. tab (str): widget tab name. ext (str) file ext for NODE_PROP_FILE + funcs (list) functions for NODE_PROP_BUTTON """ tab = tab or 'Properties' @@ -125,6 +127,8 @@ def add_property(self, name, value, items=None, range=None, self._TEMP_property_attrs[name]['range'] = range if ext: self._TEMP_property_attrs[name]['ext'] = ext + if funcs: + self._TEMP_property_attrs[name]['funcs'] = funcs else: attrs = {self.type_: {name: { 'widget_type': widget_type, @@ -136,6 +140,8 @@ def add_property(self, name, value, items=None, range=None, attrs[self.type_][name]['range'] = range if ext: attrs[self.type_][name]['ext'] = ext + if funcs: + attrs[self.type_][name]['funcs'] = funcs self._graph_model.set_node_common_properties(attrs) def set_property(self, name, value): @@ -249,6 +255,7 @@ def to_dict(self): json.dumps(v) except: to_remove.append(k) + [custom_props.pop(k) for k in to_remove] node_dict['custom'] = custom_props diff --git a/NodeGraphQt/base/node.py b/NodeGraphQt/base/node.py index 7cedb3eb..dc251ec7 100644 --- a/NodeGraphQt/base/node.py +++ b/NodeGraphQt/base/node.py @@ -237,7 +237,8 @@ def set_selected(self, selected=True): self.set_property('selected', selected) def create_property(self, name, value, items=None, range=None, - widget_type=NODE_PROP, tab=None, ext=None): + widget_type=NODE_PROP, tab=None, ext=None, + funcs=None): """ Creates a custom property to the node. @@ -269,8 +270,9 @@ def create_property(self, name, value, items=None, range=None, widget_type (int): widget flag to display in the ``PropertiesBinWidget`` tab (str): name of the widget tab to display in the properties bin. ext (str): file ext of ``NODE_PROP_FILE`` + funcs (list) list of functions for NODE_PROP_BUTTON """ - self.model.add_property(name, value, items, range, widget_type, tab, ext) + self.model.add_property(name, value, items, range, widget_type, tab, ext, funcs) def properties(self): """ @@ -567,11 +569,8 @@ def add_file_input(self, name, label='', text='', tab=None, ext="*"): tab (str): name of the widget tab to display in. ext (str): file ext """ - self.model.add_property(name, text, None, None, NODE_PROP_FILE, tab, ext) - # use create_property will cause strange error - # self.create_property( - # name, text, widget_type=NODE_PROP_FILE, tab=tab, ext=None) - + self.create_property( + name, text, widget_type=NODE_PROP_FILE, tab=tab, ext=ext) widget = NodeFilePath(self.view, name, label, text, ext) widget.value_changed.connect(lambda k, v: self.set_property(k, v)) self.view.add_widget(widget) diff --git a/NodeGraphQt/widgets/properties.py b/NodeGraphQt/widgets/properties.py index 4d5c8102..48c573e5 100644 --- a/NodeGraphQt/widgets/properties.py +++ b/NodeGraphQt/widgets/properties.py @@ -676,10 +676,12 @@ class PropButton(QtWidgets.QPushButton): def __init__(self, parent=None): super(PropButton, self).__init__(parent) - def set_value(self, value): + def set_value(self, value, node=None): # value: list of functions + if type(value) is not list: + return for func in value: - self.clicked.connect(func) + self.clicked.connect(lambda: func(node)) def get_value(self): return None @@ -876,6 +878,8 @@ def _read_node(self, node): widget.set_max(prop_range[1]) if 'ext' in common_props[prop_name].keys(): widget.set_ext(common_props[prop_name]['ext']) + if 'funcs' in common_props[prop_name].keys(): + widget.set_value(common_props[prop_name]['funcs'], node) prop_window.add_widget(prop_name, widget, value, prop_name.replace('_', ' ')) diff --git a/example_auto_nodes/node_base/auto_node.py b/example_auto_nodes/node_base/auto_node.py index 9a128270..2b85ddde 100644 --- a/example_auto_nodes/node_base/auto_node.py +++ b/example_auto_nodes/node_base/auto_node.py @@ -1,7 +1,7 @@ from NodeGraphQt.base.node import BaseNode from NodeGraphQt.base.port import Port from NodeGraphQt.constants import NODE_PROP -from NodeGraphQt import QtCore +from Qt import QtCore import hashlib import copy import time @@ -25,7 +25,7 @@ def get(self, text, Min=50, Max=200): return self.colors[text] -class AutoNode(BaseNode,QtCore.QObject): +class AutoNode(BaseNode, QtCore.QObject): cooked = QtCore.Signal() def __init__(self, defaultInputType=None, defaultOutputType=None): @@ -75,7 +75,8 @@ def cookTime(self, time): def cookNextNode(self): for nodeList in self.connected_output_nodes().values(): for n in nodeList: - n.cook() + if n is not self: + n.cook() def getData(self, port): # for custom output data @@ -125,10 +126,10 @@ def cook(self, forceCook=False): _start_time = time.time() - try: - self.run() - except Exception as error: - self.error(error) + #try: + self.run() + #except Exception as error: + # self.error(error) self._autoCook = _tmp @@ -202,8 +203,8 @@ def set_port_type(self, port, value_type): current_port.view.setToolTip('{}: {} ({}) '.format(current_port.name(), data_type_name, conn_type)) def create_property(self, name, value, items=None, range=None, - widget_type=NODE_PROP, tab=None): - super(AutoNode, self).create_property(name, value, items, range, widget_type, tab) + widget_type=NODE_PROP, tab=None, ext=None, funcs=None): + super(AutoNode, self).create_property(name, value, items, range, widget_type, tab, ext, funcs) if value is not None: self.set_port_type(name, type(value)) @@ -235,7 +236,6 @@ def set_disabled(self, mode=False): else: self.cook() - def _close_error(self): self._error = False self.set_property('color', self.defaultColor) @@ -250,7 +250,7 @@ def _show_error(self, message): tooltip = '
({})
'.format(message) self._update_tool_tip(tooltip) - def _update_tool_tip(self, message = None): + def _update_tool_tip(self, message=None): if message is None: tooltip = self._toolTip.format(self._cookTime) else: @@ -269,3 +269,8 @@ def error(self, message=None): return self._error self._show_error(message) + + def update_model(self): + if self.error(): + self.set_property('color', self.defaultColor) + super(AutoNode, self).update_model() \ No newline at end of file From fbd11e24799f3d542577636e06ddbd04951dd0df Mon Sep 17 00:00:00 2001 From: arno Date: Sun, 16 Feb 2020 20:46:17 +0800 Subject: [PATCH 4/4] add dynamic change the combobox widget menu --- NodeGraphQt/base/node.py | 15 +++++++++++++++ NodeGraphQt/qgraphics/node_base.py | 3 +++ NodeGraphQt/widgets/node_widgets.py | 4 ++++ NodeGraphQt/widgets/properties.py | 9 ++++++++- example_auto_nodes/node_base/auto_node.py | 20 +++++++++++--------- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/NodeGraphQt/base/node.py b/NodeGraphQt/base/node.py index dc251ec7..70b2e34f 100644 --- a/NodeGraphQt/base/node.py +++ b/NodeGraphQt/base/node.py @@ -704,6 +704,21 @@ def add_output(self, name='output', multi_output=True, display_name=True, self.model.outputs[port.name()] = port.model return port + def update_combo_menu(self, name, items): + if not self.has_property(name): + return + old_value = self.get_property(name) + self.set_property(name, items) + _name = '_'+name+"_" + if not self.has_property(_name): + self.create_property(_name, items) + else: + self.set_property(_name, items) + if old_value in items: + self.set_property(name, old_value) + else: + self.set_property(name, items[0]) + def inputs(self): """ Returns all the input ports from the node. diff --git a/NodeGraphQt/qgraphics/node_base.py b/NodeGraphQt/qgraphics/node_base.py index a757372c..2bae0c76 100644 --- a/NodeGraphQt/qgraphics/node_base.py +++ b/NodeGraphQt/qgraphics/node_base.py @@ -691,6 +691,9 @@ def get_widget(self, name): return widget raise NodeWidgetError('node has no widget "{}"'.format(name)) + def has_widget(self, name): + return name in self._widgets.keys() + def delete(self): for port, text in self._input_items.items(): port.delete() diff --git a/NodeGraphQt/widgets/node_widgets.py b/NodeGraphQt/widgets/node_widgets.py index 47ab743a..2a7e5c66 100644 --- a/NodeGraphQt/widgets/node_widgets.py +++ b/NodeGraphQt/widgets/node_widgets.py @@ -192,6 +192,10 @@ def value(self): @value.setter def value(self, text=''): + if type(text) is list: + self._combo.clear() + self._combo.addItems(text) + return if text != self.value: index = self._combo.findText(text, QtCore.Qt.MatchExactly) self._combo.setCurrentIndex(index) diff --git a/NodeGraphQt/widgets/properties.py b/NodeGraphQt/widgets/properties.py index 48c573e5..14248421 100644 --- a/NodeGraphQt/widgets/properties.py +++ b/NodeGraphQt/widgets/properties.py @@ -245,6 +245,9 @@ def get_value(self): return self.currentText() def set_value(self, value): + if type(value) is list: + self.set_items(value) + return if value != self.get_value(): idx = self.findText(value, QtCore.Qt.MatchExactly) self.setCurrentIndex(idx) @@ -871,7 +874,11 @@ def _read_node(self, node): widget.setMinimumHeight(min_widget_height) if prop_name in common_props.keys(): if 'items' in common_props[prop_name].keys(): - widget.set_items(common_props[prop_name]['items']) + _prop_name = '_' + prop_name + "_" + if node.has_property(_prop_name): + widget.set_items(node.get_property(_prop_name)) + else: + widget.set_items(common_props[prop_name]['items']) if 'range' in common_props[prop_name].keys(): prop_range = common_props[prop_name]['range'] widget.set_min(prop_range[0]) diff --git a/example_auto_nodes/node_base/auto_node.py b/example_auto_nodes/node_base/auto_node.py index 2b85ddde..c6b4dae5 100644 --- a/example_auto_nodes/node_base/auto_node.py +++ b/example_auto_nodes/node_base/auto_node.py @@ -1,7 +1,7 @@ from NodeGraphQt.base.node import BaseNode from NodeGraphQt.base.port import Port from NodeGraphQt.constants import NODE_PROP -from Qt import QtCore +from NodeGraphQt import QtCore import hashlib import copy import time @@ -83,10 +83,12 @@ def getData(self, port): return self.get_property(port.name()) def getInputData(self, port): - # get input data by input Port,the type of "port" can be : - # int : Port index - # str : Port name - # Port : Port object + """ + get input data by input Port,the type of "port" can be : + int : Port index + str : Port name + Port : Port object + """ if type(port) is int: to_port = self.input(port) @@ -126,10 +128,10 @@ def cook(self, forceCook=False): _start_time = time.time() - #try: - self.run() - #except Exception as error: - # self.error(error) + try: + self.run() + except Exception as error: + self.error(error) self._autoCook = _tmp