Skip to content

Commit 2a2b10c

Browse files
committed
Merge branch 'ArnoChenFx-master'
2 parents 5ae89ca + 364ac78 commit 2a2b10c

File tree

11 files changed

+204
-28
lines changed

11 files changed

+204
-28
lines changed

NodeGraphQt/base/commands.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ def __init__(self, graph, node):
139139
self.node = node
140140
self.inputs = []
141141
self.outputs = []
142+
142143
if hasattr(self.node, 'inputs'):
143144
input_ports = self.node.inputs().values()
144145
self.inputs = [(p, p.connected_ports()) for p in input_ports]

NodeGraphQt/base/graph.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,38 @@ def _wire_signals(self):
115115
self._viewer.connection_changed.connect(self._on_connection_changed)
116116
self._viewer.moved_nodes.connect(self._on_nodes_moved)
117117
self._viewer.node_double_clicked.connect(self._on_node_double_clicked)
118+
self._viewer.insert_node.connect(self._insert_node)
118119

119120
# pass through signals.
120121
self._viewer.node_selected.connect(self._on_node_selected)
121122
self._viewer.data_dropped.connect(self._on_node_data_dropped)
122123

124+
def _insert_node(self, pipe, node_id, prev_node_pos):
125+
"""
126+
Slot function triggered when a selected node has collided with a pipe.
127+
128+
Args:
129+
pipe (Pipe): collided pipe item.
130+
node_id (str): selected node id to insert.
131+
prev_node_pos (dict): previous node position. {NodeItem: [prev_x, prev_y]}
132+
"""
133+
node = self.get_node_by_id(node_id)
134+
135+
disconnected = [(pipe.input_port, pipe.output_port)]
136+
connected = []
137+
138+
if node.inputs():
139+
connected.append(
140+
(pipe.output_port, list(node.inputs().values())[0].view)
141+
)
142+
if node.outputs():
143+
connected.append((node.output(0).view, pipe.input_port))
144+
145+
self._undo_stack.beginMacro('inserted node')
146+
self._on_connection_changed(disconnected, connected)
147+
self._on_nodes_moved(prev_node_pos)
148+
self._undo_stack.endMacro()
149+
123150
def _toggle_tab_search(self):
124151
"""
125152
toggle the tab search widget.
@@ -735,6 +762,16 @@ def delete_nodes(self, nodes):
735762
[self._undo_stack.push(NodeRemovedCmd(self, n)) for n in nodes]
736763
self._undo_stack.endMacro()
737764

765+
def delete_pipe(self, pipe):
766+
self._on_connection_changed([(pipe.input_port, pipe.output_port)], [])
767+
768+
def delete_pipes(self, pipes):
769+
disconnected = []
770+
for pipe in pipes:
771+
disconnected.append((pipe.input_port, pipe.output_port))
772+
if disconnected:
773+
self._on_connection_changed(disconnected, [])
774+
738775
def all_nodes(self):
739776
"""
740777
Return all nodes in the node graph.
@@ -862,7 +899,6 @@ def _serialize(self, nodes):
862899
serial_data = {'nodes': {}, 'connections': []}
863900
nodes_data = {}
864901
for n in nodes:
865-
866902
# update the node model.
867903
n.update_model()
868904

NodeGraphQt/base/node.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from NodeGraphQt.qgraphics.node_base import NodeItem
1414
from NodeGraphQt.widgets.node_widgets import (NodeComboBox,
1515
NodeLineEdit,
16+
NodeFloatEdit,
1617
NodeCheckBox)
1718

1819

@@ -528,6 +529,28 @@ def add_text_input(self, name, label='', text='', tab=None):
528529
widget.value_changed.connect(lambda k, v: self.set_property(k, v))
529530
self.view.add_widget(widget)
530531

532+
def add_float_input(self, name, label='', value=0.0, tab=None):
533+
"""
534+
Creates a custom property with the :meth:`NodeObject.create_property`
535+
function and embeds a :class:`PySide2.QtWidgets.QLineEdit` widget
536+
into the node.
537+
538+
Note:
539+
The embedded widget is wired up to the :meth:`NodeObject.set_property`
540+
function use this function to to update the widget.
541+
542+
Args:
543+
name (str): name for the custom property.
544+
label (str): label to be displayed.
545+
value (float): pre filled value.
546+
tab (str): name of the widget tab to display in.
547+
"""
548+
self.create_property(
549+
name, value, widget_type=NODE_PROP_QLINEEDIT, tab=tab)
550+
widget = NodeFloatEdit(self.view, name, label, value)
551+
widget.value_changed.connect(lambda k, v: self.set_property(k, v))
552+
self.view.add_widget(widget)
553+
531554
def add_checkbox(self, name, label='', text='', state=False, tab=None):
532555
"""
533556
Creates a custom property with the :meth:`NodeObject.create_property`

NodeGraphQt/base/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def setup_context_menu(graph):
6262

6363
edit_menu.add_command('Copy', _copy_nodes, QtGui.QKeySequence.Copy)
6464
edit_menu.add_command('Paste', _paste_nodes, QtGui.QKeySequence.Paste)
65-
edit_menu.add_command('Delete', _delete_nodes, QtGui.QKeySequence.Delete)
65+
edit_menu.add_command('Delete', _delete_items, QtGui.QKeySequence.Delete)
6666

6767
edit_menu.add_separator()
6868

@@ -183,8 +183,9 @@ def _paste_nodes(graph):
183183
graph.paste_nodes()
184184

185185

186-
def _delete_nodes(graph):
186+
def _delete_items(graph):
187187
graph.delete_nodes(graph.selected_nodes())
188+
graph.delete_pipes(graph._viewer.selected_pipes())
188189

189190

190191
def _select_all_nodes(graph):

NodeGraphQt/qgraphics/pipe.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def __init__(self, input_port=None, output_port=None):
2727
super(Pipe, self).__init__()
2828
self.setZValue(Z_VAL_PIPE)
2929
self.setAcceptHoverEvents(True)
30+
self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable)
3031
self._color = PIPE_DEFAULT_COLOR
3132
self._style = PIPE_STYLE_DEFAULT
3233
self._active = False
@@ -55,6 +56,8 @@ def hoverLeaveEvent(self, event):
5556
self.highlight()
5657
elif self.output_port.node.selected:
5758
self.highlight()
59+
if self.isSelected():
60+
self.highlight()
5861

5962
def paint(self, painter, option, widget):
6063
"""
@@ -243,6 +246,7 @@ def highlight(self):
243246
def highlighted(self):
244247
return self._highlight
245248

249+
246250
def reset(self):
247251
self._active = False
248252
self._highlight = False
@@ -267,6 +271,13 @@ def disabled(self):
267271
return True
268272
return False
269273

274+
def itemChange(self, change, value):
275+
if change == self.ItemSelectedChange and self.scene():
276+
self.reset()
277+
if value:
278+
self.highlight()
279+
return super(Pipe, self).itemChange(change, value)
280+
270281
@property
271282
def input_port(self):
272283
return self._input_port

NodeGraphQt/widgets/node_widgets.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/python
2-
from NodeGraphQt import QtCore, QtWidgets
2+
from NodeGraphQt import QtCore, QtWidgets, QtGui
33

44
from NodeGraphQt.constants import Z_VAL_NODE_WIDGET
55
from NodeGraphQt.widgets.stylesheet import *
@@ -252,6 +252,40 @@ def value(self, text=''):
252252
self._value_changed()
253253

254254

255+
class NodeFloatEdit(NodeLineEdit):
256+
"""
257+
NodeFloatEdit widget is subclassed from :class:`NodeLineEdit`,
258+
this widget is displayed as a ``QLineEdit`` embedded in a node.
259+
260+
.. note::
261+
`To embed a ``QLineEdit`` in a node see func:`
262+
:meth:`NodeGraphQt.BaseNode.add_float_input`
263+
"""
264+
265+
def __init__(self, parent=None, name='', label='', value=0.0):
266+
super(NodeFloatEdit, self).__init__(parent, name, label)
267+
regex = '\\d+|\\d+\\.\\d+'
268+
validator = QtGui.QRegExpValidator(regex, self._ledit)
269+
self._ledit.setValidator(validator)
270+
self.text = str(value)
271+
272+
@property
273+
def value(self):
274+
"""
275+
Returns the widgets current float value.
276+
277+
Returns:
278+
float: float value.
279+
"""
280+
return float(self._ledit.text() or '0')
281+
282+
@value.setter
283+
def value(self, text=0.0):
284+
if text != self.value:
285+
self._ledit.setText(str(text))
286+
self._value_changed()
287+
288+
255289
class NodeCheckBox(NodeBaseWidget):
256290
"""
257291
NodeCheckBox widget is subclassed from :class:`NodeBaseWidget`,
@@ -268,8 +302,7 @@ def __init__(self, parent=None, name='', label='', text='', state=False):
268302
self._cbox.setChecked(state)
269303
self._cbox.setMinimumWidth(80)
270304

271-
# issue #144: disabled stylesheet for now
272-
# self._cbox.setStyleSheet(STYLE_QCHECKBOX)
305+
self._cbox.setStyleSheet(STYLE_QCHECKBOX)
273306

274307
font = self._cbox.font()
275308
font.setPointSize(11)

NodeGraphQt/widgets/properties.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def get_value(self):
197197

198198
def set_value(self, value):
199199
if value != self.get_value():
200-
self.setText(value)
200+
self.setText(str(value))
201201
self.value_changed.emit(self.toolTip(), value)
202202

203203

NodeGraphQt/widgets/properties_bin.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ def paint(self, painter, option, index):
1616
painter.save()
1717
painter.setRenderHint(QtGui.QPainter.Antialiasing, False)
1818
painter.setPen(QtCore.Qt.NoPen)
19-
painter.setBrush(option.palette.midlight())
19+
20+
painter.setBrush(QtCore.Qt.NoBrush)
2021
painter.drawRect(option.rect)
2122

2223
if option.state & QtWidgets.QStyle.State_Selected:
2324
bdr_clr = option.palette.highlight().color()
2425
painter.setPen(QtGui.QPen(bdr_clr, 1.5))
2526
else:
26-
bdr_clr = option.palette.alternateBase().color()
27+
bdr_clr = QtGui.QColor(100, 100, 100)
2728
painter.setPen(QtGui.QPen(bdr_clr, 1))
2829

2930
painter.setBrush(QtCore.Qt.NoBrush)
@@ -69,19 +70,27 @@ def __init__(self, parent=None, node_graph=None):
6970
self._limit.setToolTip('Set display nodes limit.')
7071
self._limit.setMaximum(10)
7172
self._limit.setMinimum(0)
72-
self._limit.setValue(5)
73+
self._limit.setValue(2)
7374
self._limit.valueChanged.connect(self.__on_limit_changed)
74-
self.resize(400, 400)
75+
self.resize(450, 400)
7576

7677
self._block_signal = False
7778

79+
self._lock = False
80+
self.btn_lock = QtWidgets.QPushButton('lock')
81+
self.btn_lock.setToolTip(
82+
'Lock the properties bin prevent nodes from being loaded.')
83+
self.btn_lock.clicked.connect(self.lock_bin)
84+
7885
btn_clr = QtWidgets.QPushButton('clear')
7986
btn_clr.setToolTip('Clear the properties bin.')
8087
btn_clr.clicked.connect(self.clear_bin)
8188

8289
top_layout = QtWidgets.QHBoxLayout()
90+
top_layout.setSpacing(2)
8391
top_layout.addWidget(self._limit)
8492
top_layout.addStretch(1)
93+
top_layout.addWidget(self.btn_lock)
8594
top_layout.addWidget(btn_clr)
8695

8796
layout = QtWidgets.QVBoxLayout(self)
@@ -129,7 +138,8 @@ def __on_graph_property_changed(self, node, prop_name, prop_value):
129138
return
130139

131140
property_window = properties_widget.get_widget(prop_name)
132-
if prop_value != property_window.get_value():
141+
142+
if property_window and prop_value != property_window.get_value():
133143
self._block_signal = True
134144
property_window.set_value(prop_value)
135145
self._block_signal = False
@@ -173,13 +183,14 @@ def add_node(self, node):
173183
"""
174184
if self.limit() == 0:
175185
return
176-
177-
rows = self._prop_list.rowCount()
178-
if rows >= self.limit():
179-
self._prop_list.removeRow(rows - 1)
186+
if self._lock:
187+
return
180188

181189
itm_find = self._prop_list.findItems(node.id, QtCore.Qt.MatchExactly)
190+
182191
if itm_find:
192+
if itm_find[0].row() == 0:
193+
return
183194
self._prop_list.removeRow(itm_find[0].row())
184195

185196
self._prop_list.insertRow(0)
@@ -192,6 +203,10 @@ def add_node(self, node):
192203
self._prop_list.setItem(0, 0, item)
193204
self._prop_list.selectRow(0)
194205

206+
rows = self._prop_list.rowCount()
207+
if rows > self.limit():
208+
self._prop_list.removeRow(rows - 1)
209+
195210
def remove_node(self, node):
196211
"""
197212
Remove node from the properties bin.
@@ -202,6 +217,16 @@ def remove_node(self, node):
202217
node_id = node if isinstance(node, str) else node.id
203218
self.__on_prop_close(node_id)
204219

220+
def lock_bin(self):
221+
"""
222+
Lock/UnLock the properties bin.
223+
"""
224+
self._lock = not self._lock
225+
if self._lock:
226+
self.btn_lock.setText('UnLock')
227+
else:
228+
self.btn_lock.setText('Lock')
229+
205230
def clear_bin(self):
206231
"""
207232
Clear the properties bin.
@@ -266,7 +291,7 @@ def prop_changed(node_id, prop_name, prop_value):
266291
graph = NodeGraph()
267292
graph.register_node(TestNode)
268293

269-
prop_bin = PropertiesBinWidget()
294+
prop_bin = PropertiesBinWidget(node_graph=graph)
270295
prop_bin.property_changed.connect(prop_changed)
271296

272297
node = graph.create_node('nodeGraphQt.nodes.TestNode')

NodeGraphQt/widgets/stylesheet.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
padding-bottom: 2px;
1818
padding-left: 1px;
1919
padding-right: 1px;
20-
font-size: 10pt;
20+
font-size: 8pt;
2121
}
2222
QGroupBox::title {
2323
subcontrol-origin: margin;
@@ -158,6 +158,7 @@
158158
STYLE_QCHECKBOX = '''
159159
QCheckBox {
160160
color: rgba(255, 255, 255, 150);
161+
background-color: transparent;
161162
spacing: 8px 2px;
162163
padding-top: 2px;
163164
padding-bottom: 2px;

0 commit comments

Comments
 (0)