Skip to content

Commit 6e249cd

Browse files
committed
Merge branch 'master' of https://github.com/jchanvfx/NodeGraphQt into auto_layout_func_into_graph
2 parents 733c08f + 17f1a53 commit 6e249cd

File tree

11 files changed

+96
-95
lines changed

11 files changed

+96
-95
lines changed

NodeGraphQt/base/factory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def register_node(self, node, alias=None):
6767
register the node.
6868
6969
Args:
70-
node (Node): node item
70+
node (NodeGraphQt.NodeObject): node object.
7171
alias (str): custom alias for the node identifier (optional).
7272
"""
7373
if node is None:

NodeGraphQt/base/graph.py

Lines changed: 50 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -17,52 +17,16 @@
1717
from .model import NodeGraphModel
1818
from .node import NodeObject, BaseNode, BackdropNode
1919
from .port import Port
20-
from ..constants import (
21-
DRAG_DROP_ID,
22-
NODE_LAYOUT_DIRECTION, NODE_LAYOUT_VERTICAL, NODE_LAYOUT_HORIZONTAL,
23-
PIPE_LAYOUT_CURVED, PIPE_LAYOUT_STRAIGHT, PIPE_LAYOUT_ANGLE,
24-
IN_PORT, OUT_PORT,
25-
VIEWER_GRID_LINES
26-
)
20+
from ..constants import (URI_SCHEME, URN_SCHEME,
21+
PIPE_LAYOUT_CURVED,
22+
PIPE_LAYOUT_STRAIGHT,
23+
PIPE_LAYOUT_ANGLE,
24+
IN_PORT, OUT_PORT,
25+
VIEWER_GRID_LINES)
2726
from ..widgets.node_space_bar import node_space_bar
2827
from ..widgets.viewer import NodeViewer
2928

3029

31-
class QWidgetDrops(QtWidgets.QWidget):
32-
33-
def __init__(self):
34-
super(QWidgetDrops, self).__init__()
35-
self.setAcceptDrops(True)
36-
self.setWindowTitle("NodeGraphQt")
37-
self.setStyleSheet('''
38-
QWidget {
39-
background-color: rgb(55,55,55);
40-
color: rgb(200,200,200);
41-
border-width: 0px;
42-
}''')
43-
44-
def dragEnterEvent(self, event):
45-
if event.mimeData().hasUrls:
46-
event.accept()
47-
else:
48-
event.ignore()
49-
50-
def dragMoveEvent(self, event):
51-
if event.mimeData().hasUrls:
52-
event.accept()
53-
else:
54-
event.ignore()
55-
56-
def dropEvent(self, event):
57-
if event.mimeData().hasUrls:
58-
event.setDropAction(QtCore.Qt.CopyAction)
59-
event.accept()
60-
for url in event.mimeData().urls():
61-
self.import_session(url.toLocalFile())
62-
else:
63-
event.ignore()
64-
65-
6630
class NodeGraph(QtCore.QObject):
6731
"""
6832
The ``NodeGraph`` class is the main controller for managing all nodes
@@ -316,23 +280,41 @@ def _on_node_data_dropped(self, data, pos):
316280
"""
317281
called when data has been dropped on the viewer.
318282
283+
Example Identifiers:
284+
URI = ngqt://path/to/node/session.graph
285+
URN = ngqt::node:com.nodes.MyNode1;node:com.nodes.MyNode2
286+
319287
Args:
320288
data (QtCore.QMimeData): mime data.
321289
pos (QtCore.QPoint): scene position relative to the drop.
322290
"""
323-
324-
# don't emit signal for internal widget drops.
325-
if data.hasFormat('text/plain'):
326-
if data.text().startswith('<${}>:'.format(DRAG_DROP_ID)):
327-
node_ids = data.text()[len('<${}>:'.format(DRAG_DROP_ID)):]
328-
x, y = pos.x(), pos.y()
329-
for node_id in node_ids.split(','):
330-
self.create_node(node_id, pos=[x, y])
331-
x += 20
332-
y += 20
333-
return
334-
335-
self.data_dropped.emit(data, pos)
291+
uri_regex = re.compile('{}(?:/*)([\w/]+)(\\.\w+)'.format(URI_SCHEME))
292+
urn_regex = re.compile('{}([\w\\.:;]+)'.format(URN_SCHEME))
293+
if data.hasFormat('text/uri-list'):
294+
for url in data.urls():
295+
local_file = url.toLocalFile()
296+
if local_file:
297+
try:
298+
self.import_session(local_file)
299+
continue
300+
except Exception as e:
301+
pass
302+
303+
url_str = url.toString()
304+
uri_search = uri_regex.search(url_str)
305+
urn_search = urn_regex.search(url_str)
306+
if uri_search:
307+
path = uri_search.group(1)
308+
ext = uri_search.group(2)
309+
self.import_session('{}{}'.format(path, ext))
310+
elif urn_search:
311+
search_str = urn_search.group(1)
312+
node_ids = sorted(re.findall('node:([\w\\.]+)', search_str))
313+
for node_id in node_ids:
314+
x, y = pos.x(), pos.y()
315+
self.create_node(node_id, pos=[x, y])
316+
x += 20
317+
y += 20
336318

337319
def _on_nodes_moved(self, node_data):
338320
"""
@@ -451,9 +433,7 @@ def widget(self):
451433
PySide2.QtWidgets.QWidget: node graph widget.
452434
"""
453435
if self._widget is None:
454-
self._widget = QWidgetDrops()
455-
self._widget.import_session = self.import_session
456-
436+
self._widget = QtWidgets.QWidget()
457437
layout = QtWidgets.QVBoxLayout(self._widget)
458438
layout.setContentsMargins(0, 0, 0, 0)
459439
layout.setSpacing(0)
@@ -848,7 +828,7 @@ def registered_nodes(self):
848828

849829
def register_node(self, node, alias=None):
850830
"""
851-
Register the node to the node graph vendor.
831+
Register the node to the :meth:`NodeGraph.node_factory
852832
853833
Args:
854834
node (NodeGraphQt.NodeObject): node.
@@ -857,6 +837,16 @@ def register_node(self, node, alias=None):
857837
self._node_factory.register_node(node, alias)
858838
self._viewer.rebuild_tab_search()
859839

840+
def register_nodes(self, nodes):
841+
"""
842+
Register the nodes to the :meth:`NodeGraph.node_factory
843+
844+
Args:
845+
nodes (list[NodeGraphQt.NodeObject]): list of nodes.
846+
"""
847+
[self._node_factory.register_node(n) for n in nodes]
848+
self._viewer.rebuild_tab_search()
849+
860850
def create_node(self, node_type, name=None, selected=True, color=None,
861851
text_color=None, pos=None):
862852
"""
@@ -1436,7 +1426,7 @@ def import_session(self, file_path):
14361426

14371427
file_path = file_path.strip()
14381428
if not os.path.isfile(file_path):
1439-
raise IOError('file does not exist.')
1429+
raise IOError('file does not exist: {}'.format(file_path))
14401430

14411431
try:
14421432
with open(file_path) as data_file:

NodeGraphQt/base/node.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -976,28 +976,32 @@ def delete_output(self, port):
976976

977977
def set_ports(self, port_data):
978978
"""
979-
Set node input and output ports.
979+
Set node input and output ports from specified port data.
980+
981+
example port data:
982+
{
983+
'input_ports':
984+
[{
985+
'name': 'input',
986+
'multi_connection': True,
987+
'display_name': 'Input',
988+
'data_type': 'NoneType',
989+
'locked': False
990+
}],
991+
'output_ports':
992+
[{
993+
'name': 'output',
994+
'multi_connection': True,
995+
'display_name': 'Output',
996+
'data_type': 'NoneType',
997+
'locked': False
998+
}]
999+
}
9801000
9811001
Args:
9821002
port_data(dict): port data.
9831003
"""
9841004

985-
# port data eg.
986-
# {
987-
# 'input_ports':
988-
# [{'name': ...,
989-
# 'multi_connection': ...,
990-
# 'display_name': ...,
991-
# 'data_type': ...
992-
# }, ...],
993-
# 'output_ports':
994-
# [{'name': ...,
995-
# 'multi_connection': ...,
996-
# 'display_name': ...,
997-
# 'data_type': ...
998-
# }, ...]
999-
# }
1000-
10011005
for port in self._inputs:
10021006
self._view.delete_input(port.view)
10031007
port.model.node = None

NodeGraphQt/constants.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@
9999
VIEWER_GRID_COLOR = (45, 45, 45)
100100
VIEWER_GRID_SIZE = 50
101101

102-
DRAG_DROP_ID = 'n0deGraphQT'
102+
URI_SCHEME = 'ngqt://'
103+
URN_SCHEME = 'ngqt::'
103104

104105
# === PATHS ===
105106

NodeGraphQt/widgets/node_tree.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# -*- coding: utf-8 -*-
33
from Qt import QtWidgets, QtCore
44

5-
from ..constants import DRAG_DROP_ID
5+
from ..constants import URN_SCHEME
66

77
TYPE_NODE = QtWidgets.QTreeWidgetItem.UserType + 1
88
TYPE_CATEGORY = QtWidgets.QTreeWidgetItem.UserType + 2
@@ -40,9 +40,10 @@ def __repr__(self):
4040
return '<{} object at {}>'.format(self.__class__.__name__, hex(id(self)))
4141

4242
def mimeData(self, items):
43-
node_ids = ','.join(i.toolTip(0) for i in items)
43+
node_ids = ['node:{}'.format(i.toolTip(0)) for i in items]
44+
node_urn = URN_SCHEME + ';'.join(node_ids)
4445
mime_data = super(NodeTreeWidget, self).mimeData(items)
45-
mime_data.setText('<${}>:{}'.format(DRAG_DROP_ID, node_ids))
46+
mime_data.setUrls([node_urn])
4647
return mime_data
4748

4849
def _build_tree(self):

NodeGraphQt/widgets/viewer.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,11 @@ def mouseMoveEvent(self, event):
425425
if isinstance(item, Pipe) and item.isVisible():
426426
if not item.input_port:
427427
continue
428-
if not item.input_port.node is node and \
429-
not item.output_port.node is node:
428+
port_node_check = all([
429+
not item.input_port.node is node,
430+
not item.output_port.node is node
431+
])
432+
if port_node_check:
430433
item.setSelected(True)
431434
self.COLLIDING_state = True
432435
break
@@ -446,18 +449,18 @@ def wheelEvent(self, event):
446449

447450
def dropEvent(self, event):
448451
pos = self.mapToScene(event.pos())
449-
event.setDropAction(QtCore.Qt.MoveAction)
452+
event.setDropAction(QtCore.Qt.CopyAction)
450453
self.data_dropped.emit(
451454
event.mimeData(), QtCore.QPoint(pos.x(), pos.y()))
452455

453456
def dragEnterEvent(self, event):
454-
if event.mimeData().hasFormat('text/plain'):
457+
if event.mimeData().hasFormat('text/uri-list'):
455458
event.accept()
456459
else:
457460
event.ignore()
458461

459462
def dragMoveEvent(self, event):
460-
if event.mimeData().hasFormat('text/plain'):
463+
if event.mimeData().hasFormat('text/uri-list'):
461464
event.accept()
462465
else:
463466
event.ignore()

example.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,15 @@ def show_nodes_list(node):
168168

169169

170170
# registered nodes.
171-
reg_nodes = [
171+
nodes_to_reg = [
172172
BackdropNode, MyNode,
173173
basic_nodes.FooNode,
174174
basic_nodes.BarNode,
175175
widget_nodes.DropdownMenuNode,
176176
widget_nodes.TextInputNode,
177177
widget_nodes.CheckboxNode
178178
]
179-
for n in reg_nodes:
180-
graph.register_node(n)
179+
graph.register_nodes(nodes_to_reg)
181180

182181
my_node = graph.create_node(
183182
'com.chantasticvfx.MyNode',

example_auto_nodes/node_base/module_node.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ def __init__(self, defaultInputType=None, defaultOutputType=None):
5555
self.add_output('output')
5656
self.create_property('output', None)
5757

58-
self.view.widgets['funcs'].widget.setCurrentIndex(0)
59-
self.add_function(None, self.view.widgets['funcs'].widget.currentText())
58+
self.view.widgets['funcs'].get_custom_widget().setCurrentIndex(0)
59+
self.add_function(
60+
None, self.view.widgets['funcs'].get_custom_widget().currentText())
6061

6162
def is_function(self, obj):
6263
if inspect.isfunction(self.func) or inspect.isbuiltin(self.func):

example_nodes/math_node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def __init__(self):
3232
self.create_property('output', None)
3333
self.trigger_type = 'no_inPorts'
3434

35-
self.view.widgets['funcs'].widget.setCurrentIndex(2)
35+
self.view.widgets['funcs'].get_custom_widget().setCurrentIndex(2)
3636

3737
def addFunction(self, prop, func):
3838
"""

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
PySide2>=5.12
21
Qt.py>=1.2.0

0 commit comments

Comments
 (0)