Skip to content

Commit 26b09f7

Browse files
committed
add : node menu can add by node class, the command can alse inherit by class relationship
1 parent a6f4d89 commit 26b09f7

File tree

7 files changed

+74
-34
lines changed

7 files changed

+74
-34
lines changed

NodeGraphQt/base/menu.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,24 +161,32 @@ class NodesMenu(NodeGraphMenu):
161161
nodes_menu = node_graph.get_context_menu('nodes')
162162
"""
163163

164-
def add_command(self, name, func=None, node_type=None):
164+
def add_command(self, name, func=None, node_type=None, node_class=None):
165165
"""
166166
Re-implemented to add a command to the specified node type menu.
167167
168168
Args:
169169
name (str): command name.
170170
func (function): command function eg. "func(``graph``, ``node``)".
171171
node_type (str): specified node type for the command.
172+
node_class (class): specified node class for the command.
172173
173174
Returns:
174175
NodeGraphQt.NodeGraphCommand: the appended command.
175176
"""
176-
if not node_type:
177-
raise NodeMenuError('Node type not specified!')
177+
if not node_type and not node_class:
178+
raise NodeMenuError('Node type or Node class not specified!')
179+
if node_class:
180+
node_type = node_class.__name__
178181

179182
node_menu = self.qmenu.get_menu(node_type)
180183
if not node_menu:
181184
node_menu = BaseMenu(node_type, self.qmenu)
185+
186+
if node_class:
187+
node_menu.node_class = node_class
188+
node_menu.graph = self._graph
189+
182190
self.qmenu.addMenu(node_menu)
183191

184192
if not self.qmenu.isEnabled():
@@ -190,6 +198,14 @@ def add_command(self, name, func=None, node_type=None):
190198
action.setShortcutVisibleInContextMenu(True)
191199
if func:
192200
action.executed.connect(func)
201+
202+
if node_class:
203+
node_menus = self.qmenu.get_menus(node_class)
204+
if node_menu in node_menus:
205+
node_menus.remove(node_menu)
206+
for menu in node_menus:
207+
menu.addAction(action)
208+
193209
qaction = node_menu.addAction(action)
194210
return NodeGraphCommand(self._graph, qaction)
195211

NodeGraphQt/widgets/actions.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ class BaseMenu(QtWidgets.QMenu):
88
def __init__(self, *args, **kwargs):
99
super(BaseMenu, self).__init__(*args, **kwargs)
1010
self.setStyleSheet(STYLE_QMENU)
11+
self.node_class = None
12+
self.graph = None
1113

1214
# disable for issue #142
1315
# def hideEvent(self, event):
@@ -16,11 +18,26 @@ def __init__(self, *args, **kwargs):
1618
# if hasattr(a, 'node_id'):
1719
# a.node_id = None
1820

19-
def get_menu(self, name):
21+
def get_menu(self, name,node_id=None):
2022
for action in self.actions():
21-
if action.menu() and action.menu().title() == name:
22-
return action.menu()
23-
23+
menu = action.menu()
24+
if not menu:
25+
continue
26+
if menu.title() == name:
27+
return menu
28+
if node_id and menu.node_class:
29+
node = menu.graph.get_node_by_id(node_id)
30+
if isinstance(node,menu.node_class):
31+
return menu
32+
33+
def get_menus(self,node_class):
34+
menus = []
35+
for action in self.actions():
36+
menu = action.menu()
37+
if menu.node_class:
38+
if issubclass(menu.node_class,node_class):
39+
menus.append(menu)
40+
return menus
2441

2542
class GraphAction(QtWidgets.QAction):
2643

NodeGraphQt/widgets/viewer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ def contextMenuEvent(self, event):
167167
nodes = [i for i in items if isinstance(i, AbstractNodeItem)]
168168
if nodes:
169169
node = nodes[0]
170-
ctx_menu = self._ctx_node_menu.get_menu(node.type_)
170+
ctx_menu = self._ctx_node_menu.get_menu(node.type_,node.id)
171171
if ctx_menu:
172172
for action in ctx_menu.actions():
173173
if not action.menu():

example_auto_nodes/input_nodes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from NodeGraphQt import QtCore
2-
from.node_base.auto_node import AutoNode
2+
from .node_base.auto_node import AutoNode
33
import os
44

55
class FloatInputNode(AutoNode):

example_auto_nodes/module_nodes.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from example_auto_nodes.node_base.module_node import (ModuleNode,
2-
get_functions_from_module,
3-
get_functions_from_type)
1+
from .node_base.module_node import (ModuleNode,
2+
get_functions_from_module,
3+
get_functions_from_type)
44

55
import math
66
import os
@@ -31,7 +31,7 @@ class MathModuleNode(ModuleNode):
3131
module_functions = get_functions_from_type(math)
3232

3333
def __init__(self):
34-
super(MathModuleNode, self).__init__()
34+
super(MathModuleNode, self).__init__(float, float)
3535
self.defaultValue = 0.0
3636

3737

@@ -52,6 +52,7 @@ class osModuleNode(ModuleNode):
5252
def __init__(self):
5353
super(osModuleNode, self).__init__()
5454

55+
5556
class sysModuleNode(ModuleNode):
5657
"""
5758
sys module node.
@@ -82,8 +83,7 @@ class randomModuleNode(ModuleNode):
8283
# set the initial default node name.
8384
NODE_NAME = 'random module'
8485

85-
module_functions = get_functions_from_module(random,max_depth=2)
86-
86+
module_functions = get_functions_from_module(random, max_depth=2)
8787

8888
def __init__(self):
8989
super(randomModuleNode, self).__init__()
@@ -100,21 +100,20 @@ class numpyModuleNode(ModuleNode):
100100
# set the initial default node name.
101101
NODE_NAME = 'numpy module'
102102

103-
module_functions = get_functions_from_module(numpy,max_depth=2)
104-
103+
module_functions = get_functions_from_module(numpy, max_depth=2)
105104

106105
def __init__(self):
107106
super(numpyModuleNode, self).__init__()
108107

109-
def is_function(self,obj):
110-
result = super(numpyModuleNode,self).is_function(obj)
108+
def is_function(self, obj):
109+
result = super(numpyModuleNode, self).is_function(obj)
111110
if result:
112111
return True
113112
elif type(obj).__name__ == "ufunc":
114113
return True
115114
return False
116115

117-
def get_numpy_args(self,func):
116+
def get_numpy_args(self, func):
118117
args = []
119118
info = numpydoc.docscrape.FunctionDoc(func)
120119
for i in info["Parameters"]:
@@ -139,7 +138,7 @@ def addFunction(self, prop, func):
139138
args = self.get_numpy_args(self.func)
140139
except Exception as error:
141140
if type(self.func).__name__ == "ufunc":
142-
args = ["input"+str(i+1) for i in range(self.func.nin)]
141+
args = ["input" + str(i + 1) for i in range(self.func.nin)]
143142

144143
self.process_args(args)
145144

example_auto_nodes/node_base/auto_node.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ def rand_color(seed_type):
1616

1717

1818
class AutoNode(BaseNode):
19-
def __init__(self):
19+
def __init__(self,defaultInputType=None,defaultOutputType=None):
2020
super(AutoNode, self).__init__()
2121
self.needCook = True
22-
self.defaultValue = None
2322
self._error = False
23+
self.matchTypes = [[float, int]]
24+
self.errorColor = (200, 50, 50)
2425

2526
self.defaultColor = self.get_property("color")
26-
self.errorColor = (200,50,50)
27+
self.defaultValue = None
28+
self.defaultInputType = defaultInputType
29+
self.defaultOutputType = defaultOutputType
2730

2831
def cookNextNode(self):
2932
for nodeList in self.connected_output_nodes().values():
@@ -93,10 +96,12 @@ def set_disabled(self, mode=False):
9396
if self.input_ports():
9497
self.cook()
9598

96-
@staticmethod
97-
def checkPortType(to_port, from_port):
99+
def checkPortType(self, to_port, from_port):
98100
if hasattr(to_port,"DataType") and hasattr(from_port,"DataType"):
99101
if to_port.DataType is not from_port.DataType:
102+
for types in self.matchTypes:
103+
if to_port.DataType in types and from_port.DataType in types:
104+
return True
100105
return False
101106

102107
return True
@@ -106,10 +111,6 @@ def set_property(self, name, value):
106111
self.set_port_type(name, type(value))
107112

108113
def set_port_type(self, port, value_type):
109-
110-
if value_type is int:
111-
value_type = float
112-
113114
current_port = None
114115

115116
if type(port) is Port:
@@ -147,13 +148,17 @@ def add_input(self, name='input', data_type=None, multi_input=False, display_nam
147148
new_port = super(AutoNode, self).add_input(name, multi_input, display_name, color)
148149
if data_type:
149150
self.set_port_type(new_port, data_type)
151+
elif self.defaultInputType:
152+
self.set_port_type(new_port, self.defaultInputType)
150153
return new_port
151154

152155
def add_output(self, name='output', data_type=None, multi_output=True, display_name=True,
153156
color=None):
154157
new_port = super(AutoNode, self).add_output(name, multi_output, display_name, color)
155158
if data_type:
156159
self.set_port_type(new_port, data_type)
160+
elif self.defaultOutputType:
161+
self.set_port_type(new_port, self.defaultOutputType)
157162
return new_port
158163

159164
def _close_error(self):
@@ -162,6 +167,10 @@ def _close_error(self):
162167
self._view._tooltip_disable(False)
163168

164169
def _show_error(self,message):
170+
if not self._error:
171+
self.defaultColor = self.get_property("color")
172+
173+
self._error = True
165174
self.set_property('color', self.errorColor)
166175
tooltip = '<b>{}</b>'.format(self.name())
167176
tooltip += ' <font color="red"><br>({})</br></font>'.format(message)
@@ -172,5 +181,4 @@ def error(self,message = None):
172181
if message is None:
173182
return self._error
174183

175-
self._error = True
176184
self._show_error(message)

example_auto_nodes/node_base/module_node.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import inspect
2-
from example_auto_nodes.node_base.auto_node import AutoNode
2+
from .auto_node import AutoNode
33

44

55
def _get_functions_from_module(module, function_dict, max_depth=1, module_name=None):
@@ -44,8 +44,8 @@ class ModuleNode(AutoNode):
4444

4545
module_functions = {}
4646

47-
def __init__(self):
48-
super(ModuleNode, self).__init__()
47+
def __init__(self,defaultInputType=None,defaultOutputType=None):
48+
super(ModuleNode, self).__init__(defaultInputType,defaultOutputType)
4949
self.set_color(25, 58, 51)
5050
self.add_combo_menu('funcs', 'Functions', items=list(self.module_functions.keys()), tab='widgets')
5151

0 commit comments

Comments
 (0)