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
50 changes: 41 additions & 9 deletions NodeGraphQt/base/graph.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import os
import re
Expand All @@ -13,6 +14,8 @@
from NodeGraphQt.base.model import NodeGraphModel
from NodeGraphQt.base.node import NodeObject
from NodeGraphQt.base.port import Port
from NodeGraphQt.constants import DRAG_DROP_ID
from NodeGraphQt.widgets.node_list import NodeListWidget
from NodeGraphQt.widgets.properties_bin import PropertiesBinWidget
from NodeGraphQt.widgets.viewer import NodeViewer

Expand Down Expand Up @@ -45,7 +48,9 @@ def __init__(self, parent=None, tab_search_key='tab'):
self._viewer = NodeViewer(parent)
self._node_factory = NodeFactory()
self._undo_stack = QtWidgets.QUndoStack(self)
self._properties_bin = PropertiesBinWidget()

self._properties_bin = None
self._nodes_list = None

tab = QtWidgets.QAction('Search Nodes', self)
tab.setShortcut(tab_search_key)
Expand All @@ -65,10 +70,6 @@ def _wire_signals(self):
self._viewer.node_selected.connect(self._on_node_selected)
self._viewer.data_dropped.connect(self._on_node_data_dropped)

# wire up properties bin widget.
self._properties_bin.property_changed.connect(
self._on_property_changed)

def _toggle_tab_search(self):
"""
toggle the tab search widget.
Expand Down Expand Up @@ -99,7 +100,8 @@ def _on_node_double_clicked(self, node_id):
node_id (str): node id emitted by the viewer.
"""
node = self.get_node_by_id(node_id)
self._properties_bin.add_node(node)
if self._properties_bin:
self._properties_bin.add_node(node)

self.node_double_clicked.emit(node)

Expand All @@ -122,6 +124,18 @@ def _on_node_data_dropped(self, data, pos):
data (QtCore.QMimeData): mime data.
pos (QtCore.QPoint): scene position relative to the drop.
"""

# don't emit signal for internal widget drops.
if data.hasFormat('text/plain'):
if data.text().startswith('<${}>:'.format(DRAG_DROP_ID)):
node_ids = data.text()[len('<${}>:'.format(DRAG_DROP_ID)):]
x, y = pos.x(), pos.y()
for node_id in node_ids.split(','):
self.create_node(node_id, pos=[x, y])
x += 20
y += 20
return

self.data_dropped.emit(data, pos)

def _on_nodes_moved(self, node_data):
Expand Down Expand Up @@ -222,13 +236,31 @@ def scene(self):

def properties_bin(self):
"""
Return the node properties bin widget.
Initializes the node properties bin widget when first called.

Returns:
PropBinWidget: widget.
"""
PropBinWidget: the initialized widget.
"""
if self._properties_bin is None:
self._properties_bin = PropertiesBinWidget()
# wire up widget.
self._properties_bin.property_changed.connect(
self._on_property_changed
)
return self._properties_bin

def nodes_list(self):
"""
Initializes the nodes list widget when first called.

Returns:
NodeListWidget: the initialized widget.
"""
if self._nodes_list is None:
self._nodes_list = NodeListWidget()
self._nodes_list.set_node_factory(self._node_factory)
return self._nodes_list

def undo_stack(self):
"""
Returns the undo stack used in the node graph
Expand Down
2 changes: 2 additions & 0 deletions NodeGraphQt/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@

SCENE_AREA = 8000.0

DRAG_DROP_ID = 'n0deGraphQT'

# === PATHS ===

BASE_PATH = os.path.dirname(os.path.abspath(__file__))
Expand Down
25 changes: 22 additions & 3 deletions NodeGraphQt/qgraphics/port.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,8 @@ def paint(self, painter, option, widget):
painter.save()

rect = QtCore.QRectF(0.0, 0.8, self._width, self._height)
painter.setBrush(QtGui.QColor(0, 0, 0, 200))
painter.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0, 255), 1.8))
path = QtGui.QPainterPath()
path.addEllipse(rect)
painter.drawPath(path)

if self._hovered:
color = QtGui.QColor(*PORT_HOVER_COLOR)
Expand All @@ -76,6 +73,28 @@ def paint(self, painter, option, widget):
painter.setPen(pen)
painter.drawEllipse(self.boundingRect())

if self.connected_pipes and not self._hovered:
painter.setBrush(border_color)
w = self._width / 2.5
h = self._height / 2.5
rect = QtCore.QRectF(self.boundingRect().center().x() - w / 2,
self.boundingRect().center().y() - h / 2,
w, h)
painter.drawEllipse(rect)
elif self._hovered:
if self.multi_connection:
painter.setBrush(color)
w = self._width / 1.8
h = self._height / 1.8
else:
painter.setBrush(border_color)
w = self._width / 3.5
h = self._height / 3.5
rect = QtCore.QRectF(self.boundingRect().center().x() - w / 2,
self.boundingRect().center().y() - h / 2,
w, h)
painter.drawEllipse(rect)

painter.restore()

def itemChange(self, change, value):
Expand Down
94 changes: 94 additions & 0 deletions NodeGraphQt/widgets/node_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from NodeGraphQt import QtWidgets, QtCore
from NodeGraphQt.constants import DRAG_DROP_ID


TYPE_NODE = QtWidgets.QTreeWidgetItem.UserType + 1
TYPE_CATEGORY = QtWidgets.QTreeWidgetItem.UserType + 2


class BaseListWidgetItem(QtWidgets.QListWidgetItem):

def __eq__(self, other):
return id(self) == id(other)


class NodeListWidget(QtWidgets.QTreeWidget):

def __init__(self, parent=None):
super(NodeListWidget, self).__init__(parent)
self.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly)
self.setHeaderHidden(True)
self._factory = None
self._custom_labels = {}

def mimeData(self, items):
node_ids = ','.join(i.toolTip(0) for i in items)
mime_data = super(NodeListWidget, self).mimeData(items)
mime_data.setText('<${}>:{}'.format(DRAG_DROP_ID, node_ids))
return mime_data

def _build_tree(self):
"""
Populate the node tree.
"""
self.clear()
categories = set()
node_types = {}
for name, node_ids in self._factory.names.items():
for nid in node_ids:
categories.add('.'.join(nid.split('.')[:-1]))
node_types[nid] = name

category_items = {}
for category in sorted(categories):
if category in self._custom_labels.keys():
label = self._custom_labels[category]
else:
label = '- {}'.format(category)
cat_item = QtWidgets.QTreeWidgetItem(
self, [label], type=TYPE_CATEGORY
)
cat_item.setFirstColumnSpanned(True)
cat_item.setFlags(QtCore.Qt.ItemIsEnabled)
self.addTopLevelItem(cat_item)
cat_item.setExpanded(True)
category_items[category] = cat_item

for node_id, node_name in node_types.items():
category = '.'.join(node_id.split('.')[:-1])
category_item = category_items[category]

item = QtWidgets.QTreeWidgetItem(
category_item, [node_name], type=TYPE_NODE
)
item.setToolTip(0, node_id)

category_item.addChild(item)


def set_node_factory(self, factory):
"""
Set current node factory.

Args:
factory (NodeFactory): node factory.
"""
self._factory = factory

def set_category_label(self, category, label):
"""
Set custom display label for a node category.

Args:
category (str): node identifier category eg. "nodeGraphQt.nodes"
label (str): custom display label.
"""
self._custom_labels[category] = label

def update(self):
"""
Update and refresh the node list widget.
"""
self._build_tree()
1 change: 1 addition & 0 deletions NodeGraphQt/widgets/viewer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os

from NodeGraphQt import QtGui, QtCore, QtWidgets
Expand Down
13 changes: 11 additions & 2 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,25 @@ def __init__(self):
viewer.resize(1100, 800)
viewer.show()


# show the properties bin when a node is "double clicked" in the graph.
properties_bin = graph.properties_bin()
properties_bin.setWindowFlags(QtCore.Qt.Tool)

def show_prop_bin(node):
if not properties_bin.isVisible():
properties_bin.show()

graph.node_double_clicked.connect(show_prop_bin)


# show the nodes list when a node is "double clicked" in the graph.
node_list = graph.nodes_list()
def show_nodes_list(node):
if not node_list.isVisible():
node_list.update()
node_list.show()
graph.node_double_clicked.connect(show_nodes_list)


# registered nodes.
reg_nodes = [
Backdrop, MyNode,
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
PySide2>=5.12
Qt.py>=1.2.0.b2
python>=3.6