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
17 changes: 8 additions & 9 deletions NodeGraphQt/base/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import re
import copy

from NodeGraphQt import QtCore, QtWidgets
from NodeGraphQt import QtCore, QtWidgets, QtGui
from NodeGraphQt.base.commands import (NodeAddedCmd,
NodeRemovedCmd,
NodeMovedCmd,
Expand Down Expand Up @@ -105,10 +105,9 @@ def __init__(self, parent=None):
self._node_factory = NodeFactory()
self._undo_stack = QtWidgets.QUndoStack(self)

tab = QtWidgets.QAction('Search Nodes', self)
tab.setShortcut('tab')
tab.triggered.connect(self._toggle_tab_search)
self._viewer.addAction(tab)
tab = QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Tab), self._viewer)
tab.activated.connect(self._toggle_tab_search)
self._viewer.need_show_tab_search.connect(self._toggle_tab_search)

self._wire_signals()

Expand Down Expand Up @@ -164,8 +163,9 @@ def _toggle_tab_search(self):
"""
toggle the tab search widget.
"""
self._viewer.tab_search_set_nodes(self._node_factory.names)
self._viewer.tab_search_toggle()
if self._viewer.underMouse():
self._viewer.tab_search_set_nodes(self._node_factory.names)
self._viewer.tab_search_toggle()

def _on_property_bin_changed(self, node_id, prop_name, prop_value):
"""
Expand Down Expand Up @@ -687,8 +687,7 @@ def create_node(self, node_type, name=None, selected=True, color=None,
NodeCls = self._node_factory.create_node_instance(node_type)
if NodeCls:
node = NodeCls()

node._graph = self
node.set_graph(self)
node.model._graph_model = self.model

wid_types = node.model.__dict__.pop('_TEMP_property_widget_types')
Expand Down
7 changes: 6 additions & 1 deletion NodeGraphQt/base/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def __init__(self):
}

def add_property(self, name, value, items=None, range=None,
widget_type=NODE_PROP, tab='Properties'):
widget_type=NODE_PROP, tab='Properties', ext=None):
"""
add custom property.

Expand All @@ -103,6 +103,7 @@ def add_property(self, name, value, items=None, range=None,
range (tuple)): min, max values used by NODE_PROP_SLIDER.
widget_type (int): widget type flag.
tab (str): widget tab name.
ext (str) file ext for NODE_PROP_FILE
"""
tab = tab or 'Properties'

Expand All @@ -122,6 +123,8 @@ def add_property(self, name, value, items=None, range=None,
self._TEMP_property_attrs[name]['items'] = items
if range:
self._TEMP_property_attrs[name]['range'] = range
if ext:
self._TEMP_property_attrs[name]['ext'] = ext
else:
attrs = {self.type_: {name: {
'widget_type': widget_type,
Expand All @@ -131,6 +134,8 @@ def add_property(self, name, value, items=None, range=None,
attrs[self.type_][name]['items'] = items
if range:
attrs[self.type_][name]['range'] = range
if ext:
attrs[self.type_][name]['ext'] = ext
self._graph_model.set_node_common_properties(attrs)

def set_property(self, name, value):
Expand Down
25 changes: 19 additions & 6 deletions NodeGraphQt/base/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ def model(self):
"""
return self._model

def set_graph(self, graph):
self._graph = graph

def set_model(self, model):
"""
Set the node model.
Expand Down Expand Up @@ -234,7 +237,7 @@ def set_selected(self, selected=True):
self.set_property('selected', selected)

def create_property(self, name, value, items=None, range=None,
widget_type=NODE_PROP, tab=None):
widget_type=NODE_PROP, tab=None, ext=None):
"""
Creates a custom property to the node.

Expand All @@ -247,7 +250,13 @@ def create_property(self, name, value, items=None, range=None,
- :attr:`NodeGraphQt.constants.NODE_PROP_QCHECKBOX`
- :attr:`NodeGraphQt.constants.NODE_PROP_QSPINBOX`
- :attr:`NodeGraphQt.constants.NODE_PROP_COLORPICKER`
- :attr:`NodeGraphQt.constants.NODE_PROP_SLIDER`
- :attr:`NodeGraphQt.constants.NODE_PROP_FILE`
- :attr:`NodeGraphQt.constants.NODE_PROP_VECTOR2`
- :attr:`NodeGraphQt.constants.NODE_PROP_VECTOR3`
- :attr:`NodeGraphQt.constants.NODE_PROP_VECTOR4`
- :attr:`NodeGraphQt.constants.NODE_PROP_FLOAT`
- :attr:`NodeGraphQt.constants.NODE_PROP_INT`
- :attr:`NodeGraphQt.constants.NODE_PROP_BUTTON`

See Also:
:class:`NodeGraphQt.PropertiesBinWidget`
Expand All @@ -259,8 +268,9 @@ def create_property(self, name, value, items=None, range=None,
range (tuple)): ``(min, max)`` values used by ``NODE_PROP_SLIDER``
widget_type (int): widget flag to display in the ``PropertiesBinWidget``
tab (str): name of the widget tab to display in the properties bin.
ext (str): file ext of ``NODE_PROP_FILE``
"""
self.model.add_property(name, value, items, range, widget_type, tab)
self.model.add_property(name, value, items, range, widget_type, tab, ext)

def properties(self):
"""
Expand Down Expand Up @@ -557,9 +567,12 @@ def add_file_input(self, name, label='', text='', tab=None, ext="*"):
tab (str): name of the widget tab to display in.
ext (str): file ext
"""
self.create_property(
name, text, widget_type=NODE_PROP_FILE, tab=tab)
widget = NodeFilePath(self.view, name, label, text,ext)
self.model.add_property(name, text, None, None, NODE_PROP_FILE, tab, ext)
# use create_property will cause strange error
# self.create_property(
# name, text, widget_type=NODE_PROP_FILE, tab=tab, ext=None)

widget = NodeFilePath(self.view, name, label, text, ext)
widget.value_changed.connect(lambda k, v: self.set_property(k, v))
self.view.add_widget(widget)

Expand Down
8 changes: 8 additions & 0 deletions NodeGraphQt/widgets/file_dialog.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from NodeGraphQt import QtWidgets
from NodeGraphQt.widgets.stylesheet import STYLE_MESSAGEBOX
import os

current_dir = os.path.expanduser('~')
Expand Down Expand Up @@ -40,3 +41,10 @@ def getOpenFileName(parent=None, title="Open File", file_dir=None, ext_filter="*
return file_dlg


def messageBox(text, title , buttons):
msg = QtWidgets.QMessageBox()
msg.setStyleSheet(STYLE_MESSAGEBOX)
msg.setWindowTitle(title)
msg.setInformativeText(text)
msg.setStandardButtons(buttons)
return msg.exec_()
22 changes: 15 additions & 7 deletions NodeGraphQt/widgets/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,13 @@ def __init__(self, parent=None):

self._ledit.setStyleSheet("QLineEdit{border:1px solid}")
_button.setStyleSheet("QPushButton{border:1px solid}")
self._ext = "*"

def set_ext(self, ext):
self._ext = ext

def _on_select_file(self):
file_path = file_dialog.getOpenFileName(self)
file_path = file_dialog.getOpenFileName(self, ext_filter=self._ext)
file = file_path[0] or None
if file:
self.set_value(file)
Expand Down Expand Up @@ -398,7 +402,7 @@ def __init__(self, parent=None):
self._step = 1
self._speed = 0.1

self.textChanged.connect(self._on_text_changed)
self.editingFinished.connect(self._on_text_changed)

self.menu = _valueMenu()
self.menu.mouseMove.connect(self.mouseMoveEvent)
Expand All @@ -409,7 +413,7 @@ def __init__(self, parent=None):

self.set_data_type(float)

def _on_text_changed(self, value):
def _on_text_changed(self):
self.valueChanged.emit(self.value())

def _reset(self):
Expand All @@ -425,6 +429,7 @@ def mouseMoveEvent(self, event):
delta = event.x() - self.pre_x
value = self.pre_val + int(delta*self._speed) * self._step
self.setValue(value)
self._on_text_changed()

super(_valueEdit,self).mouseMoveEvent(event)

Expand Down Expand Up @@ -513,18 +518,19 @@ def __init__(self, parent=None):
self.set_data_type(float)
self._lock = False

def _on_edit_changed(self,value):
def _on_edit_changed(self, value):
self._set_slider_value(value)
self.valueChanged.emit(self._edit.value())

def _on_slider_changed(self,value):
def _on_slider_changed(self, value):
if self._lock:
self._lock = False
return
value = value / float(self._mul)
self._edit.setValue(value)
self._on_edit_changed(value)

def _set_slider_value(self,value):
def _set_slider_value(self, value):
value = int(value * self._mul)

if value == self._slider.value():
Expand All @@ -539,7 +545,6 @@ def _set_slider_value(self,value):
elif value > _max and self._slider.value() != _max:
self._slider.setValue(_max)


def set_min(self, value=0):
self._slider.setMinimum(int(value*self._mul))

Expand All @@ -563,6 +568,7 @@ def value(self):

def setValue(self,value):
self._edit.setValue(value)
self._on_edit_changed(value)


class _doubleSpinBox(QtWidgets.QDoubleSpinBox):
Expand Down Expand Up @@ -868,6 +874,8 @@ def _read_node(self, node):
prop_range = common_props[prop_name]['range']
widget.set_min(prop_range[0])
widget.set_max(prop_range[1])
if 'ext' in common_props[prop_name].keys():
widget.set_ext(common_props[prop_name]['ext'])

prop_window.add_widget(prop_name, widget, value,
prop_name.replace('_', ' '))
Expand Down
28 changes: 28 additions & 0 deletions NodeGraphQt/widgets/stylesheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,31 @@
background-color: transparent;
}
'''

STYLE_MESSAGEBOX = '''
QLabel{
min-width:500 px;
font-size: 18px;
background-color: transparent;
color: rgb(200 ,200, 200);
}
QPushButton{
width:100px;
font-size: 18px;
background-color: transparent;
color: rgb(200 ,200, 200);
border-width: 1px;
border-color: rgb(40,40,40);
}
QPushButton::pressed {
border-style: inset;
}
QPushButton::hover {
background-color: rgb(65, 65, 65);
border-color: rgb(10,80,230);
}
QMessageBox{
background-color: rgb(55, 55, 55);
color: rgb(200 ,200, 200);
}
'''
20 changes: 10 additions & 10 deletions NodeGraphQt/widgets/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from NodeGraphQt.widgets.actions import BaseMenu
from NodeGraphQt.widgets.scene import NodeScene
from NodeGraphQt.widgets.tab_search import TabSearchWidget, TabSearchMenuWidget
from NodeGraphQt.widgets.file_dialog import file_dialog
from NodeGraphQt.widgets.file_dialog import file_dialog, messageBox

ZOOM_MIN = -0.95
ZOOM_MAX = 2.0
Expand All @@ -33,6 +33,7 @@ class NodeViewer(QtWidgets.QGraphicsView):
connection_sliced = QtCore.Signal(list)
connection_changed = QtCore.Signal(list, list)
insert_node = QtCore.Signal(object, str, dict)
need_show_tab_search = QtCore.Signal()

# pass through signals
node_selected = QtCore.Signal(str)
Expand Down Expand Up @@ -207,10 +208,13 @@ def contextMenuEvent(self, event):
action.node_id = node.id

ctx_menu = ctx_menu or self._ctx_menu
if ctx_menu.isEnabled():
ctx_menu.exec_(event.globalPos())
if len(ctx_menu.actions()) > 0:
if ctx_menu.isEnabled():
ctx_menu.exec_(event.globalPos())
else:
return super(NodeViewer, self).contextMenuEvent(event)
else:
return super(NodeViewer, self).contextMenuEvent(event)
self.need_show_tab_search.emit()

def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
Expand Down Expand Up @@ -286,7 +290,6 @@ def mouseReleaseEvent(self, event):
elif event.button() == QtCore.Qt.MiddleButton:
self.MMB_state = False


# hide pipe slicer.
if self._SLICER_PIPE.isVisible():
self._on_pipes_sliced(self._SLICER_PIPE.path())
Expand Down Expand Up @@ -714,14 +717,11 @@ def context_menus(self):
'nodes': self._ctx_node_menu}

def question_dialog(self, text, title='Node Graph'):
dlg = QtWidgets.QMessageBox.question(
self, title, text,
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
dlg = messageBox(text, title, QtWidgets.QMessageBox.Yes|QtWidgets.QMessageBox.No)
return dlg == QtWidgets.QMessageBox.Yes

def message_dialog(self, text, title='Node Graph'):
QtWidgets.QMessageBox.information(
self, title, text, QtWidgets.QMessageBox.Ok)
messageBox(text, title, QtWidgets.QMessageBox.Ok)

def load_dialog(self, current_dir=None, ext=None):
ext = '*{} '.format(ext) if ext else ''
Expand Down
33 changes: 21 additions & 12 deletions example_auto_nodes/node_base/auto_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@
from NodeGraphQt.base.port import Port
from NodeGraphQt.constants import NODE_PROP
from NodeGraphQt import QtCore
import random
import hashlib
import copy
import time

def rand_color(seed_type):
seed = id(seed_type)
random.seed(seed + 10)
r = random.randint(50, 200)
random.seed(seed + 5)
g = random.randint(50, 200)
random.seed(seed + 3421)
b = random.randint(50, 200)
return (r, g, b, 255)

# Generate random color based on strings
class CryptoColors(object):
def __init__(self):
self.colors = {}

def get(self, text, Min=50, Max=200):
if text in self.colors:
return self.colors[text]
h = hashlib.sha256(text.encode('utf-8')).hexdigest()
d = int('0xFFFFFFFFFFFFFFFF', 0)
r = int(Min + (int("0x" + h[:16], 0) / d) * (Max - Min))
g = int(Min + (int("0x" + h[16:32], 0) / d) * (Max - Min))
b = int(Min + (int("0x" + h[32:48], 0) / d) * (Max - Min))
a = int(Min + (int("0x" + h[48:], 0) / d) * (Max - Min))
self.colors[text] = (r, g, b, 255)
return self.colors[text]


class AutoNode(BaseNode,QtCore.QObject):
Expand All @@ -29,6 +37,7 @@ def __init__(self, defaultInputType=None, defaultOutputType=None):
self.matchTypes = [[float, int]]
self.errorColor = (200, 50, 50)
self.stopCookColor = (200, 200, 200)
self._cryptoColors = CryptoColors()

self.defaultColor = self.get_property("color")
self.defaultValue = None
Expand Down Expand Up @@ -186,8 +195,8 @@ def set_port_type(self, port, value_type):
else:
current_port.DataType = value_type

current_port.border_color = rand_color(value_type)
current_port.color = rand_color(value_type)
current_port.border_color = self._cryptoColors.get(str(value_type))
current_port.color = self._cryptoColors.get(str(value_type))
conn_type = 'multi' if current_port.multi_connection() else 'single'
data_type_name = value_type.__name__ if value_type else "all"
current_port.view.setToolTip('{}: {} ({}) '.format(current_port.name(), data_type_name, conn_type))
Expand Down