Skip to content

Commit c1ae2ac

Browse files
authored
Merge pull request #154 from ArnoChenFx/master
fix some bug and add button prop widget
2 parents 940e12b + ffae935 commit c1ae2ac

File tree

5 files changed

+112
-44
lines changed

5 files changed

+112
-44
lines changed

NodeGraphQt/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@
8181
NODE_PROP_FLOAT = 14
8282
#: Property type represented with int widget in the properties bin.
8383
NODE_PROP_INT = 15
84+
#: Property type represented with button widget in the properties bin.
85+
NODE_PROP_BUTTON = 16
8486

8587
# === NODE VIEWER ===
8688

NodeGraphQt/widgets/node_widgets.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ def __init__(self, parent=None, name='', label='', text='', ext="*"):
417417
self._ext = ext
418418

419419
def _on_select_file(self):
420-
file_path = file_dialog.getOpenFileName()
420+
file_path = file_dialog.getOpenFileName(ext_filter=self._ext)
421421
file = file_path[0] or None
422422
if file:
423423
self.value = file

NodeGraphQt/widgets/properties.py

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
NODE_PROP_VECTOR3,
1616
NODE_PROP_VECTOR4,
1717
NODE_PROP_FLOAT,
18-
NODE_PROP_INT)
18+
NODE_PROP_INT,
19+
NODE_PROP_BUTTON)
1920
from NodeGraphQt.widgets.file_dialog import file_dialog
2021

2122

@@ -333,6 +334,7 @@ class _valueMenu(QtWidgets.QMenu):
333334

334335
mouseMove = QtCore.Signal(object)
335336
mouseRelease = QtCore.Signal(object)
337+
stepChange = QtCore.Signal()
336338

337339
def __init__(self, parent=None):
338340
super(_valueMenu, self).__init__(parent)
@@ -357,6 +359,8 @@ def mouseMoveEvent(self, event):
357359

358360
action = self.actionAt(event.pos())
359361
if action:
362+
if action is not self.last_action:
363+
self.stepChange.emit()
360364
self.last_action = action
361365
self.step = action.step
362366
elif self.last_action:
@@ -389,16 +393,17 @@ def __init__(self, parent=None):
389393
self._data_type = float
390394
self.setText("0")
391395

392-
self.pre_x = 0
396+
self.pre_x = None
397+
self.pre_val = None
393398
self._step = 1
394-
self._tmp_value = 0
395399
self._speed = 0.1
396400

397401
self.textChanged.connect(self._on_text_changed)
398402

399403
self.menu = _valueMenu()
400404
self.menu.mouseMove.connect(self.mouseMoveEvent)
401405
self.menu.mouseRelease.connect(self.mouseReleaseEvent)
406+
self.menu.stepChange.connect(self._reset)
402407
steps = [0.001, 0.01, 0.1, 1, 10, 100, 1000]
403408
self.menu.set_steps(steps)
404409

@@ -407,25 +412,26 @@ def __init__(self, parent=None):
407412
def _on_text_changed(self, value):
408413
self.valueChanged.emit(self.value())
409414

415+
def _reset(self):
416+
self.pre_x = None
417+
410418
def mouseMoveEvent(self, event):
411419
if self.mid_state:
412420
if self.pre_x is None:
413421
self.pre_x = event.x()
414-
self.set_step(self.menu.step)
415-
delta = (event.x() - self.pre_x)
416-
self._tmp_value += delta * self._speed * self._step
417-
if abs(self._tmp_value) > self._step:
418-
value = self.value() + delta * self._step
422+
self.pre_val = self.value()
423+
else:
424+
self.set_step(self.menu.step)
425+
delta = event.x() - self.pre_x
426+
value = self.pre_val + int(delta*self._speed) * self._step
419427
self.setValue(value)
420-
self._tmp_value = 0
421-
self.pre_x = event.x()
428+
422429
super(_valueEdit,self).mouseMoveEvent(event)
423430

424431
def mousePressEvent(self, event):
425432
if event.button() == QtCore.Qt.MiddleButton:
426433
self.mid_state = True
427-
self.pre_x = None
428-
self._tmp_value = 0
434+
self._reset()
429435
self.menu.exec_(QtGui.QCursor.pos())
430436
super(_valueEdit,self).mousePressEvent(event)
431437

@@ -448,8 +454,10 @@ def set_data_type(self, dt):
448454
def _convert_text(self,text):
449455
# int("1.0") will return error
450456
# so we use int(float("1.0"))
451-
452-
value = float(text)
457+
try:
458+
value = float(text)
459+
except:
460+
value = 0.0
453461
if self._data_type is int:
454462
value = int(value)
455463
return value
@@ -506,14 +514,13 @@ def __init__(self, parent=None):
506514
self._lock = False
507515

508516
def _on_edit_changed(self,value):
509-
if self._lock:
510-
return
511-
self._lock = True
512517
self._set_slider_value(value)
513518
self.valueChanged.emit(self._edit.value())
514-
self._lock = False
515519

516520
def _on_slider_changed(self,value):
521+
if self._lock:
522+
self._lock = False
523+
return
517524
value = value / float(self._mul)
518525
self._edit.setValue(value)
519526

@@ -522,7 +529,7 @@ def _set_slider_value(self,value):
522529

523530
if value == self._slider.value():
524531
return
525-
532+
self._lock = True
526533
_min = self._slider.minimum()
527534
_max = self._slider.maximum()
528535
if _min<=value<=_max:
@@ -532,6 +539,7 @@ def _set_slider_value(self,value):
532539
elif value > _max and self._slider.value() != _max:
533540
self._slider.setValue(_max)
534541

542+
535543
def set_min(self, value=0):
536544
self._slider.setMinimum(int(value*self._mul))
537545

@@ -656,6 +664,21 @@ def __init__(self, parent=None):
656664
self.set_data_type(int)
657665

658666

667+
class PropButton(QtWidgets.QPushButton):
668+
value_changed = QtCore.Signal(str, object)
669+
670+
def __init__(self, parent=None):
671+
super(PropButton, self).__init__(parent)
672+
673+
def set_value(self, value):
674+
# value: list of functions
675+
for func in value:
676+
self.clicked.connect(func)
677+
678+
def get_value(self):
679+
return None
680+
681+
659682
WIDGET_MAP = {
660683
NODE_PROP_QLABEL: PropLabel,
661684
NODE_PROP_QLINEEDIT: PropLineEdit,
@@ -671,6 +694,7 @@ def __init__(self, parent=None):
671694
NODE_PROP_VECTOR4: PropVector4,
672695
NODE_PROP_FLOAT: PropFloat,
673696
NODE_PROP_INT: PropInt,
697+
NODE_PROP_BUTTON: PropButton
674698
}
675699

676700

@@ -710,11 +734,14 @@ def add_widget(self, name, widget, value, label=None):
710734
if row > 0:
711735
row += 1
712736

737+
label = QtWidgets.QLabel(label)
713738
label_flags = QtCore.Qt.AlignCenter | QtCore.Qt.AlignRight
714739
if widget.__class__.__name__ == 'PropTextEdit':
715740
label_flags = label_flags | QtCore.Qt.AlignTop
716-
717-
self.__layout.addWidget(QtWidgets.QLabel(label), row, 0, label_flags)
741+
elif widget.__class__.__name__ == 'PropButton':
742+
label.setVisible(False)
743+
widget.setText(name)
744+
self.__layout.addWidget(label, row, 0, label_flags)
718745
self.__layout.addWidget(widget, row, 1)
719746

720747
def get_widget(self, name):

NodeGraphQt/widgets/viewer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,9 @@ def mousePressEvent(self, event):
246246
nodes = [i for i in items if isinstance(i, AbstractNodeItem)]
247247
pipes = [i for i in items if isinstance(i, Pipe)]
248248

249+
if nodes:
250+
self.MMB_state = False
251+
249252
# toggle extend node selection.
250253
if self.LMB_state:
251254
if self.SHIFT_state:

example_auto_nodes/node_base/auto_node.py

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from NodeGraphQt import QtCore
55
import random
66
import copy
7-
7+
import time
88

99
def rand_color(seed_type):
1010
seed = id(seed_type)
@@ -35,6 +35,9 @@ def __init__(self, defaultInputType=None, defaultOutputType=None):
3535
self.defaultInputType = defaultInputType
3636
self.defaultOutputType = defaultOutputType
3737

38+
self._cookTime = 0.0
39+
self._toolTip = self._setup_tool_tip()
40+
3841
@property
3942
def autoCook(self):
4043
return self._autoCook
@@ -51,11 +54,24 @@ def autoCook(self, mode):
5154
self.defaultColor = self.get_property("color")
5255
self.set_property('color', self.stopCookColor)
5356

57+
@property
58+
def cookTime(self):
59+
return self._cookTime
60+
61+
@autoCook.setter
62+
def cookTime(self, time):
63+
self._cookTime = time
64+
self._update_tool_tip()
65+
5466
def cookNextNode(self):
5567
for nodeList in self.connected_output_nodes().values():
5668
for n in nodeList:
5769
n.cook()
5870

71+
def getData(self, port):
72+
# for custom output data
73+
return self.get_property(port.name())
74+
5975
def getInputData(self, port):
6076
# get input data by input Port,the type of "port" can be :
6177
# int : Port index
@@ -77,38 +93,41 @@ def getInputData(self, port):
7793
return copy.deepcopy(self.defaultValue)
7894

7995
for from_port in from_ports:
80-
data = from_port.node().get_property(from_port.name())
96+
data = from_port.node().getData(from_port)
8197
return copy.deepcopy(data)
8298

99+
def when_disabled(self):
100+
num = len(self.input_ports())
101+
for index, out_port in enumerate(self.output_ports()):
102+
self.set_property(out_port.name(), self.getInputData(index % num))
103+
83104
def cook(self, forceCook=False):
84105
if not self._autoCook and forceCook is not True:
85106
return
86107

87-
_tmp = self._autoCook
88-
self._autoCook = False
89-
90-
if self.disabled():
91-
num = len(self.input_ports())
92-
for index, out_port in enumerate(self.output_ports()):
93-
self.set_property(out_port.name(), self.getInputData(index % num))
94-
self.cookNextNode()
95-
return
96-
97108
if not self.needCook:
98109
return
99110

111+
_tmp = self._autoCook
112+
self._autoCook = False
113+
100114
if self.error():
101115
self._close_error()
102116

117+
_start_time = time.time()
118+
103119
try:
104120
self.run()
105121
except Exception as error:
106122
self.error(error)
123+
107124
self._autoCook = _tmp
108125

109126
if self.error():
110127
return
111128

129+
self.cookTime = time.time() - _start_time
130+
112131
self.cooked.emit()
113132
self.cookNextNode()
114133

@@ -128,11 +147,6 @@ def on_input_disconnected(self, to_port, from_port):
128147
return
129148
self.cook()
130149

131-
def set_disabled(self, mode=False):
132-
super(AutoNode, self).set_disabled(mode)
133-
if self.input_ports():
134-
self.cook()
135-
136150
def checkPortType(self, to_port, from_port):
137151
# None type port can connect with any other type port
138152
# types in self.matchTypes can connect with each other
@@ -203,21 +217,43 @@ def add_output(self, name='output', data_type=None, multi_output=True, display_n
203217
self.set_port_type(new_port, self.defaultOutputType)
204218
return new_port
205219

220+
def set_disabled(self, mode=False):
221+
super(AutoNode, self).set_disabled(mode)
222+
self._autoCook = not mode
223+
if mode is True:
224+
self.when_disabled()
225+
self.cookNextNode()
226+
else:
227+
self.cook()
228+
229+
206230
def _close_error(self):
207231
self._error = False
208232
self.set_property('color', self.defaultColor)
209-
self._view._tooltip_disable(False)
233+
self._update_tool_tip()
210234

211235
def _show_error(self, message):
212236
if not self._error:
213237
self.defaultColor = self.get_property("color")
214238

215239
self._error = True
216240
self.set_property('color', self.errorColor)
217-
tooltip = '<b>{}</b>'.format(self.name())
218-
tooltip += ' <font color="red"><br>({})</br></font>'.format(message)
219-
tooltip += '<br/>{}<br/>'.format(self._view.type_)
220-
self._view.setToolTip(tooltip)
241+
tooltip = '<font color="red"><br>({})</br></font>'.format(message)
242+
self._update_tool_tip(tooltip)
243+
244+
def _update_tool_tip(self, message = None):
245+
if message is None:
246+
tooltip = self._toolTip.format(self._cookTime)
247+
else:
248+
tooltip = '<b>{}</b>'.format(self.name())
249+
tooltip += message
250+
tooltip += '<br/>{}<br/>'.format(self._view.type_)
251+
self.view.setToolTip(tooltip)
252+
return tooltip
253+
254+
def _setup_tool_tip(self):
255+
tooltip = '<br> last cook used: {}s</br>'
256+
return self._update_tool_tip(tooltip)
221257

222258
def error(self, message=None):
223259
if message is None:

0 commit comments

Comments
 (0)