Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions NodeGraphQt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,34 @@ def __init__(self):
'"NodeGraphQt.vendor.Qt ({})"'.format(qtpy_ver))

from .base.graph import NodeGraph
from .base.menu import Menu, MenuCommand
from .base.menu import NodesMenu, NodeGraphMenu, NodeGraphCommand
from .base.node import NodeObject, BaseNode, BackdropNode
from .base.port import Port
from .pkg_info import __version__ as VERSION
from .pkg_info import __license__ as LICENSE

# functions
from .base.actions import setup_context_menu
from .base.utils import setup_context_menu

# widgets
from .widgets.node_tree import NodeTreeWidget
from .widgets.properties_bin import PropertiesBinWidget

__version__ = VERSION
__all__ = [
'BackdropNode', 'BaseNode', 'LICENSE', 'Menu', 'MenuCommand', 'NodeGraph',
'NodeObject', 'NodeTreeWidget', 'Port', 'PropertiesBinWidget', 'VERSION',
'constants', 'setup_context_menu'
'BackdropNode',
'BaseNode',
'LICENSE',
'NodeGraph',
'NodeGraphCommand',
'NodeGraphMenu',
'NodeObject',
'NodeTreeWidget',
'NodesMenu',
'Port',
'PropertiesBinWidget',
'VERSION',
'constants',
'setup_context_menu'
]

70 changes: 61 additions & 9 deletions NodeGraphQt/base/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
NodeMovedCmd,
PortConnectedCmd)
from NodeGraphQt.base.factory import NodeFactory
from NodeGraphQt.base.menu import Menu
from NodeGraphQt.base.menu import NodeGraphMenu, NodesMenu
from NodeGraphQt.base.model import NodeGraphModel
from NodeGraphQt.base.node import NodeObject
from NodeGraphQt.base.port import Port
Expand Down Expand Up @@ -391,23 +391,75 @@ def end_undo(self):

def context_menu(self):
"""
Returns the node graph root context menu object.
Returns the main context menu from the node graph.

Note:
This is a convenience function to
:meth:`NodeGraphQt.NodeGraph.get_context_menu`
with the arg ``menu="graph"``

Returns:
NodeGraphQt.NodeGraphMenu: context menu object.
"""
return self.get_context_menu('graph')

def context_nodes_menu(self):
"""
Returns the main context menu for the nodes.

Note:
This is a convenience function to
:meth:`NodeGraphQt.NodeGraph.get_context_menu`
with the arg ``menu="nodes"``

Returns:
Menu: context menu object.
NodeGraphQt.NodesMenu: context menu object.
"""
return Menu(self._viewer, self._viewer.context_menu())
return self.get_context_menu('nodes')

def disable_context_menu(self, disabled=True):
def get_context_menu(self, menu):
"""
Disable/Enable node graph context menu.
Returns the context menu specified by the name.

Menu types:
"graph" - context menu from the node graph.
"nodes" - context menu for the nodes.

Args:
menu (str): menu name.

Returns:
NodeGraphMenu or NodesMenu: context menu object.
"""
menus = self._viewer.context_menus()
if menus.get(menu):
if menu == 'graph':
return NodeGraphMenu(self, menus[menu])
elif menu == 'nodes':
return NodesMenu(self, menus[menu])

def disable_context_menu(self, disabled=True, name='all'):
"""
Disable/Enable context menus from the node graph.

Menu Types:
- ``"all"`` all context menus from the node graph.
- ``"graph"`` context menu from the node graph.
- ``"nodes"`` context menu for the nodes.

Args:
disabled (bool): true to enable context menu.
name (str): menu name. (default: ``"all"``)
"""
menu = self._viewer.context_menu()
menu.setDisabled(disabled)
menu.setVisible(not disabled)
if name == 'all':
for k, menu in self._viewer.context_menus().items():
menu.setDisabled(disabled)
menu.setVisible(not disabled)
return
menus = self._viewer.context_menus()
if menus.get(name):
menus[name].setDisabled(disabled)
menus[name].setVisible(not disabled)

def acyclic(self):
"""
Expand Down
167 changes: 134 additions & 33 deletions NodeGraphQt/base/menu.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
#!/usr/bin/python
from distutils.version import LooseVersion

from NodeGraphQt import QtGui, QtCore, QtWidgets
from NodeGraphQt.widgets.stylesheet import STYLE_QMENU
from NodeGraphQt import QtGui, QtCore
from NodeGraphQt.errors import NodeMenuError
from NodeGraphQt.widgets.actions import BaseMenu, GraphAction, NodeAction


class Menu(object):
class NodeGraphMenu(object):
"""
base class for a menu item.
The ``NodeGraphMenu`` is the context menu triggered from the node graph.

example to accessing the node graph context menu.

.. code-block:: python
:linenos:

from NodeGraphQt import NodeGraph

node_graph = NodeGraph()

# get the context menu for the node graph.
context_menu = node_graph.get_context_menu('graph')
"""

def __init__(self, viewer, qmenu):
self.__viewer = viewer
self.__qmenu = qmenu
def __init__(self, graph, qmenu):
self._graph = graph
self._qmenu = qmenu

def __repr__(self):
cls_name = self.__class__.__name__
return '<{}("{}") object at {}>'.format(cls_name, self.name(), hex(id(self)))
return '<{}("{}") object at {}>'.format(
self.__class__.__name__, self.name(), hex(id(self)))

@property
def qmenu(self):
return self.__qmenu
"""
The underlying qmenu.

Returns:
BaseMenu: qmenu object.
"""
return self._qmenu

def name(self):
"""
Expand All @@ -39,11 +58,11 @@ def get_menu(self, name):
name (str): name of the menu.

Returns:
NodeGraphQt.Menu: menu item.
NodeGraphQt.NodeGraphMenu: menu item.
"""
for action in self.qmenu.actions():
if action.menu() and action.menu().title() == name:
return Menu(self.__viewer, action.menu())
menu = self.qmenu.get_menu(name)
if menu:
return NodeGraphMenu(self._graph, menu)

def get_command(self, name):
"""
Expand All @@ -57,7 +76,7 @@ def get_command(self, name):
"""
for action in self.qmenu.actions():
if not action.menu() and action.text() == name:
return MenuCommand(self.__viewer, action)
return NodeGraphCommand(self._graph, action)

def all_commands(self):
"""
Expand All @@ -76,7 +95,7 @@ def get_actions(menu):
actions += get_actions(action.menu())
return actions
child_actions = get_actions(self.qmenu)
return [MenuCommand(self.__viewer, a) for a in child_actions]
return [NodeGraphCommand(self._graph, a) for a in child_actions]

def add_menu(self, name):
"""
Expand All @@ -86,34 +105,34 @@ def add_menu(self, name):
name (str): menu name.

Returns:
NodeGraphQt.Menu: the appended menu item.
NodeGraphQt.NodeGraphMenu: the appended menu item.
"""
menu = QtWidgets.QMenu(name, self.qmenu)
menu.setStyleSheet(STYLE_QMENU)
menu = BaseMenu(name, self.qmenu)
self.qmenu.addMenu(menu)
return Menu(self.__viewer, menu)
return NodeGraphMenu(self._graph, menu)

def add_command(self, name, func=None, shortcut=None):
"""
Adds a command to the menu.

Args:
name (str): command name.
func (function): command function.
shortcut (str): function shotcut key.
func (function): command function eg. "func(``graph``)".
shortcut (str): shotcut key.

Returns:
NodeGraphQt.MenuCommand: the appended command.
"""
action = QtWidgets.QAction(name, self.__viewer)
action = GraphAction(name, self._graph.viewer())
action.graph = self._graph
if LooseVersion(QtCore.qVersion()) >= LooseVersion('5.10'):
action.setShortcutVisibleInContextMenu(True)
if shortcut:
action.setShortcut(shortcut)
if func:
action.triggered.connect(func)
action.executed.connect(func)
qaction = self.qmenu.addAction(action)
return MenuCommand(self.__viewer, qaction)
return NodeGraphCommand(self._graph, qaction)

def add_separator(self):
"""
Expand All @@ -122,22 +141,104 @@ def add_separator(self):
self.qmenu.addSeparator()


class MenuCommand(object):
class NodesMenu(NodeGraphMenu):
"""
The ``NodesMenu`` is the context menu triggered from the nodes.

**Inherited from:** :class:`NodeGraphQt.NodeGraphMenu`

example for adding a command to the nodes context menu.

.. code-block:: python
:linenos:

from NodeGraphQt import BaseNode, NodeGraph

# example node.
class MyNode(BaseNode):

__identifier__ = 'com.chantasticvfx'
NODE_NAME = 'my node'

def __init__(self):
super(MyNode, self).__init__()
self.add_input('in')
self.add_output('out')

# create node graph.
node_graph = NodeGraph()

# register example node.
node_graph.register_node(MyNode)

# get the context menu for the nodes.
nodes_menu = node_graph.get_context_menu('nodes')

# create a command
def test_func(graph, node):
print('Clicked on node: {}'.format(node.name()))

nodes_menu.add_command('test',
func=test_func,
node_type='com.chantasticvfx.MyNode')

"""
base class for a menu command.

def add_command(self, name, func=None, node_type=None):
"""
Re-implemented to add a command to the specified node type menu.

Args:
name (str): command name.
func (function): command function eg. "func(``graph``, ``node``)".
node_type (str): specified node type for the command.

Returns:
NodeGraphQt.MenuCommand: the appended command.
"""
if not node_type:
raise NodeMenuError('Node type not specified!')

node_menu = self.qmenu.get_menu(node_type)
if not node_menu:
node_menu = BaseMenu(node_type, self.qmenu)
self.qmenu.addMenu(node_menu)

if not self.qmenu.isEnabled():
self.qmenu.setDisabled(False)

action = NodeAction(name, self._graph.viewer())
action.graph = self._graph
if LooseVersion(QtCore.qVersion()) >= LooseVersion('5.10'):
action.setShortcutVisibleInContextMenu(True)
if func:
action.executed.connect(func)
qaction = node_menu.addAction(action)
return NodeGraphCommand(self._graph, qaction)


class NodeGraphCommand(object):
"""
Node graph menu command.
"""

def __init__(self, viewer, qaction):
self.__viewer = viewer
self.__qaction = qaction
def __init__(self, graph, qaction):
self._graph = graph
self._qaction = qaction

def __repr__(self):
cls_name = self.__class__.__name__
return 'NodeGraphQt.{}(\'{}\')'.format(cls_name, self.name())
return '<{}("{}") object at {}>'.format(
self.__class__.__name__, self.name(), hex(id(self)))

@property
def qaction(self):
return self.__qaction
"""
The underlying qaction.

Returns:
BaseAction: qaction object.
"""
return self._qaction

def name(self):
"""
Expand Down
Loading