Skip to content

Commit

Permalink
_NumberValueMenu updates. #374
Browse files Browse the repository at this point in the history
  • Loading branch information
jchanvfx committed Sep 12, 2023
1 parent 4823b43 commit 54c596b
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ def __init__(self, parent=None):
self._color = (0, 0, 0)
self._button = QtWidgets.QPushButton()
self._vector = PropVector3()
self._vector.set_steps([1, 10, 100])
self._vector.set_data_type(int)
self._vector.set_value([0, 0, 0])
self._vector.set_min(0)
self._vector.set_max(255)
self._update_color()

self._button.clicked.connect(self._on_select_color)
Expand Down Expand Up @@ -53,6 +57,15 @@ def _update_color(self):
'rgb: {}\nhex: {}'.format(self._color[:3], hex_color)
)

def set_data_type(self, data_type):
"""
Sets the input line edit fields to either display in float or int.
Args:
data_type(int or float): int or float data type object.
"""
self._vector.set_data_type(data_type)

def get_value(self):
return self._color[:3]

Expand All @@ -74,7 +87,11 @@ def __init__(self, parent=None):
self._color = (0, 0, 0, 255)
self._button = QtWidgets.QPushButton()
self._vector = PropVector4()
self._vector.set_steps([1, 10, 100])
self._vector.set_data_type(int)
self._vector.set_value([0, 0, 0, 255])
self._vector.set_min(0)
self._vector.set_max(255)
self._update_color()

self._button.clicked.connect(self._on_select_color)
Expand Down
131 changes: 111 additions & 20 deletions NodeGraphQt/custom_widgets/properties_bin/custom_widget_value_edit.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#!/usr/bin/python
import re

from Qt import QtWidgets, QtCore, QtGui

_NUMB_REGEX = re.compile(r'^((?:\-)*\d+)*([\.,])*(\d+(?:[eE](?:[\-\+])*\d+)*)*')


class _NumberValueMenu(QtWidgets.QMenu):

Expand Down Expand Up @@ -83,16 +87,17 @@ def __init__(self, parent=None, data_type=float):
self._previous_x = None
self._previous_value = None
self._step = 1
self._speed = 0.1
self._speed = 0.05
self._data_type = float
self._min = None
self._max = None

self._menu = _NumberValueMenu()
self._menu.mouseMove.connect(self.mouseMoveEvent)
self._menu.mouseRelease.connect(self.mouseReleaseEvent)
self._menu.stepChange.connect(self._reset_previous_x)
self._menu.set_steps([0.001, 0.01, 0.1, 1, 10, 100, 1000])

self.editingFinished.connect(self._on_text_changed)
self.editingFinished.connect(self._on_editing_finished)

self.set_data_type(data_type)

Expand All @@ -113,7 +118,7 @@ def mouseMoveEvent(self, event):
value = self._previous_value
value = value + int(delta * self._speed) * self._step
self.set_value(value)
self._on_text_changed()
self._on_mmb_mouse_move()
super(_NumberValueEdit, self).mouseMoveEvent(event)

def mousePressEvent(self, event):
Expand All @@ -140,15 +145,37 @@ def keyPressEvent(self, event):
def _reset_previous_x(self):
self._previous_x = None

def _on_text_changed(self):
def _on_mmb_mouse_move(self):
self.value_changed.emit(self.get_value())

def _on_editing_finished(self):
if self._data_type is float:
match = _NUMB_REGEX.match(self.text())
if match:
val1, point, val2 = match.groups()
if point:
val1 = val1 or '0'
val2 = val2 or '0'
self.setText(val1 + point + val2)
self.value_changed.emit(self.get_value())

def _convert_text(self, text):
# int("1.0") will return error
# so we use int(float("1.0"))
try:
value = float(text)
except:
"""
Convert text to int or float.
Args:
text (str): input text.
Returns:
int or float: converted value.
"""
match = _NUMB_REGEX.match(text)
if match:
val1, _, val2 = match.groups()
val1 = val1 or '0'
val2 = val2 or '0'
value = float(val1 + '.' + val2)
else:
value = 0.0
if self._data_type is int:
value = int(value)
Expand All @@ -157,26 +184,90 @@ def _convert_text(self, text):
# public

def set_data_type(self, data_type):
"""
Sets the line edit to either display value in float or int.
Args:
data_type(int or float): int or float data type object.
"""
self._data_type = data_type
self._menu.set_data_type(data_type)
if data_type is int:
self.setValidator(QtGui.QIntValidator())
regexp = QtCore.QRegExp(r'\d+')
validator = QtGui.QRegExpValidator(regexp, self)
steps = [1, 10, 100, 1000]
elif data_type is float:
self.setValidator(QtGui.QDoubleValidator())
regexp = QtCore.QRegExp(r'\d+[\.,]\d+(?:[eE](?:[\-\+]|)\d+)*')
validator = QtGui.QRegExpValidator(regexp, self)
steps = [0.001, 0.01, 0.1, 1]
self.setValidator(validator)
if not self._menu.steps:
self._menu.set_steps(steps)
self._menu.set_data_type(data_type)

def set_steps(self, steps=None):
steps = steps or [0.001, 0.01, 0.1, 1, 10, 100, 1000]
"""
Sets the step items in the MMB context menu.
Args:
steps (list[int] or list[float]): list of ints or floats.
"""
step_types = {
int: [1, 10, 100, 1000],
float: [0.001, 0.01, 0.1, 1]
}
steps = steps or step_types.get(self._data_type)
self._menu.set_steps(steps)

def set_min(self, value=None):
"""
Set the minimum range for the input field.
Args:
value (int or float): minimum range value.
"""
if self._data_type is int:
self._min = int(value)
elif self._data_type is float:
self._min = float(value)
else:
self._min = value

def set_max(self, value=None):
"""
Set the maximum range for the input field.
Args:
value (int or float): maximum range value.
"""
if self._data_type is int:
self._max = int(value)
elif self._data_type is float:
self._max = float(value)
else:
self._max = value

def get_value(self):
if self.text().startswith('.'):
text = '0' + self.text()
self.setText(text)
return self._convert_text(self.text())
value = self._convert_text(self.text())
return value

def set_value(self, value):
if value != self.get_value():
self.setText(str(self._convert_text(value)))
text = str(value)
converted = self._convert_text(text)
current = self.get_value()
if converted == current:
return
point = None
if isinstance(converted, float):
point = _NUMB_REGEX.match(str(value)).groups(2)
if self._min is not None and converted < self._min:
text = str(self._min)
if point and point not in text:
text = str(self._min).replace('.', point)
if self._max is not None and converted > self._max:
text = str(self._max)
if point and point not in text:
text = text.replace('.', point)
self.setText(text)


class IntValueEdit(_NumberValueEdit):
Expand Down
36 changes: 36 additions & 0 deletions NodeGraphQt/custom_widgets/properties_bin/custom_widget_vectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,45 @@ def _update_items(self):
self._items[index].set_value(value)

def set_data_type(self, data_type):
"""
Sets the input line edit fields to either display in float or int.
Args:
data_type(int or float): int or float data type object.
"""
for item in self._items:
item.set_data_type(data_type)

def set_steps(self, steps):
"""
Sets the step items in the MMB context menu.
Args:
steps (list[int] or list[float]): list of ints or floats.
"""
for item in self._items:
item.set_steps(steps)

def set_min(self, value):
"""
Set the minimum range for the input fields.
Args:
value (int or float): minimum range value.
"""
for item in self._items:
item.set_min(value)

def set_max(self, value):
"""
Set the maximum range for the input fields.
Args:
value (int or float): maximum range value.
"""
for item in self._items:
item.set_max(value)

def get_value(self):
return self._value

Expand Down
6 changes: 3 additions & 3 deletions NodeGraphQt/nodes/base_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,9 +697,9 @@ def connected_output_nodes(self):

def add_accept_port_type(self, port, port_type_data):
"""
Add a accept constrain to a specified node port.
Add an accept constrain to a specified node port.
Once a constrain has been added only ports of that type specified will
Once a constraint has been added only ports of that type specified will
be allowed a pipe connection.
port type data example
Expand Down Expand Up @@ -759,7 +759,7 @@ def add_reject_port_type(self, port, port_type_data):
"""
Add a reject constrain to a specified node port.
Once a constrain has been added only ports of that type specified will
Once a constraint has been added only ports of that type specified will
NOT be allowed a pipe connection.
port type data example
Expand Down
2 changes: 1 addition & 1 deletion NodeGraphQt/pkg_info.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
__version__ = '0.6.21'
__version__ = '0.6.22'
__status__ = 'Work in Progress'
__license__ = 'MIT'

Expand Down

0 comments on commit 54c596b

Please sign in to comment.