Skip to content

Commit fd2fd4d

Browse files
authored
Merge pull request #428 from jack-mil/menu_func_paths#427
Interpret function file path in menu data relative to menu json
2 parents 1239e5e + cd3fc57 commit fd2fd4d

File tree

4 files changed

+84
-58
lines changed

4 files changed

+84
-58
lines changed

NodeGraphQt/base/graph.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import json
55
import os
66
import re
7+
from pathlib import Path
78

89
from Qt import QtCore, QtWidgets
910

@@ -775,14 +776,15 @@ def get_context_menu(self, menu):
775776
"""
776777
return self._context_menu.get(menu)
777778

778-
def _deserialize_context_menu(self, menu, menu_data):
779+
def _deserialize_context_menu(self, menu, menu_data, anchor_path=None):
779780
"""
780781
Populate context menu from a dictionary.
781782
782783
Args:
783784
menu (NodeGraphQt.NodeGraphMenu or NodeGraphQt.NodesMenu):
784785
parent context menu.
785786
menu_data (list[dict] or dict): serialized menu data.
787+
anchor_path (str or None): directory to interpret file paths relative to (optional)
786788
"""
787789
if not menu:
788790
raise ValueError('No context menu named: "{}"'.format(menu))
@@ -792,6 +794,10 @@ def _deserialize_context_menu(self, menu, menu_data):
792794

793795
nodes_menu = self.get_context_menu('nodes')
794796

797+
anchor = Path(anchor_path).resolve()
798+
if anchor.is_file():
799+
anchor = anchor.parent
800+
795801
def build_menu_command(menu, data):
796802
"""
797803
Create menu command from serialized data.
@@ -801,14 +807,16 @@ def build_menu_command(menu, data):
801807
menu object.
802808
data (dict): serialized menu command data.
803809
"""
804-
full_path = os.path.abspath(data['file'])
805-
base_dir, file_name = os.path.split(full_path)
806-
base_name = os.path.basename(base_dir)
807-
file_name, _ = file_name.split('.')
810+
func_path = Path(data['file'])
811+
if not func_path.is_absolute():
812+
func_path = anchor.joinpath(func_path)
813+
814+
base_name = func_path.parent.name
815+
file_name = func_path.stem
808816

809817
mod_name = '{}.{}'.format(base_name, file_name)
810818

811-
spec = importlib.util.spec_from_file_location(mod_name, full_path)
819+
spec = importlib.util.spec_from_file_location(mod_name, func_path)
812820
mod = importlib.util.module_from_spec(spec)
813821
sys.modules[mod_name] = mod
814822
spec.loader.exec_module(mod)
@@ -832,12 +840,12 @@ def build_menu_command(menu, data):
832840
elif item_type == 'menu':
833841
sub_menu = menu.add_menu(menu_data['label'])
834842
items = menu_data.get('items', [])
835-
self._deserialize_context_menu(sub_menu, items)
843+
self._deserialize_context_menu(sub_menu, items, anchor_path)
836844
elif isinstance(menu_data, list):
837845
for item_data in menu_data:
838-
self._deserialize_context_menu(menu, item_data)
846+
self._deserialize_context_menu(menu, item_data, anchor_path)
839847

840-
def set_context_menu(self, menu_name, data):
848+
def set_context_menu(self, menu_name, data, anchor_path=None):
841849
"""
842850
Populate a context menu from serialized data.
843851
@@ -875,11 +883,12 @@ def run_test(graph):
875883
Args:
876884
menu_name (str): name of the parent context menu to populate under.
877885
data (dict): serialized menu data.
886+
anchor_path (str or None): directory to interpret file paths relative to (optional)
878887
"""
879888
context_menu = self.get_context_menu(menu_name)
880-
self._deserialize_context_menu(context_menu, data)
889+
self._deserialize_context_menu(context_menu, data, anchor_path)
881890

882-
def set_context_menu_from_file(self, file_path, menu=None):
891+
def set_context_menu_from_file(self, file_path, menu='graph'):
883892
"""
884893
Populate a context menu from a serialized json file.
885894
@@ -892,16 +901,16 @@ def set_context_menu_from_file(self, file_path, menu=None):
892901
menu (str): name of the parent context menu to populate under.
893902
file_path (str): serialized menu commands json file.
894903
"""
895-
file_path = os.path.abspath(file_path)
904+
file = Path(file_path).resolve()
896905

897906
menu = menu or 'graph'
898-
if not os.path.isfile(file_path):
899-
raise IOError('file doesn\'t exists: "{}"'.format(file_path))
907+
if not file.is_file():
908+
raise IOError('file doesn\'t exist: "{}"'.format(file))
900909

901-
with open(file_path) as f:
910+
with file.open() as f:
902911
data = json.load(f)
903912
context_menu = self.get_context_menu(menu)
904-
self._deserialize_context_menu(context_menu, data)
913+
self._deserialize_context_menu(context_menu, data, file)
905914

906915
def disable_context_menu(self, disabled=True, name='all'):
907916
"""

examples/basic_example.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/python
22
# -*- coding: utf-8 -*-
3-
import os
43
import signal
4+
from pathlib import Path
55

66
from Qt import QtCore, QtWidgets
77

@@ -12,11 +12,12 @@
1212
NodesPaletteWidget
1313
)
1414

15-
# import example nodes from the "example_nodes" package
16-
from nodes import basic_nodes, custom_ports_node, group_node, widget_nodes
15+
# import example nodes from the "nodes" sub-package
16+
from examples.nodes import basic_nodes, custom_ports_node, group_node, widget_nodes
1717

18-
if __name__ == '__main__':
18+
BASE_PATH = Path(__file__).parent.resolve()
1919

20+
def main():
2021
# handle SIGINT to make the app terminate on CTRL+C
2122
signal.signal(signal.SIGINT, signal.SIG_DFL)
2223

@@ -26,7 +27,8 @@
2627
graph = NodeGraph()
2728

2829
# set up context menu for the node graph.
29-
graph.set_context_menu_from_file('../examples/hotkeys/hotkeys.json')
30+
hotkey_path = Path(BASE_PATH, 'hotkeys', 'hotkeys.json')
31+
graph.set_context_menu_from_file(hotkey_path, 'graph')
3032

3133
# registered example nodes.
3234
graph.register_nodes([
@@ -53,9 +55,7 @@
5355
# create node and set a custom icon.
5456
n_basic_b = graph.create_node(
5557
'nodes.basic.BasicNodeB', name='custom icon')
56-
n_basic_b.set_icon(
57-
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'star.png')
58-
)
58+
n_basic_b.set_icon(Path(BASE_PATH, 'star.png'))
5959

6060
# create node with the custom port shapes.
6161
n_custom_ports = graph.create_node(
@@ -140,3 +140,7 @@ def display_properties_bin(node):
140140
# nodes_palette.show()
141141

142142
app.exec()
143+
144+
145+
if __name__ == '__main__':
146+
main()

examples/hotkeys/hotkey_functions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ def clear_session(graph):
9393
if graph.question_dialog('Clear Current Session?', 'Clear Session'):
9494
graph.clear_session()
9595

96+
def quit_qt(graph):
97+
"""
98+
Quit the Qt application.
99+
"""
100+
from Qt import QtCore
101+
QtCore.QCoreApplication.quit()
96102

97103
def clear_undo(graph):
98104
"""

0 commit comments

Comments
 (0)