0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-13 03:01:50 +02:00

fix(color_button_native): popup logic to choose color moved to ColorButtonNative

This commit is contained in:
2025-06-03 18:45:16 +02:00
committed by Jan Wyzula
parent f68f072da3
commit 2d0ed94f3f
3 changed files with 112 additions and 13 deletions

View File

@ -22,6 +22,7 @@ from qtpy.QtWidgets import (
QWidget,
)
from bec_widgets import SafeSlot
from bec_widgets.utils import ConnectionConfig, EntryValidator
from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.colors import Colors
@ -154,7 +155,7 @@ class CurveRow(QTreeWidgetItem):
"""Create columns 3..6: color button, style combo, width spin, symbol spin."""
# Color in col 3
self.color_button = ColorButtonNative(color=self.config.color)
self.color_button.clicked.connect(lambda: self._select_color(self.color_button))
self.color_button.color_changed.connect(self._on_color_changed)
self.tree.setItemWidget(self, 3, self.color_button)
# Style in col 4
@ -177,20 +178,16 @@ class CurveRow(QTreeWidgetItem):
self.symbol_spin.setValue(self.config.symbol_size)
self.tree.setItemWidget(self, 6, self.symbol_spin)
def _select_color(self, button):
@SafeSlot(str, verify_sender=True)
def _on_color_changed(self, new_color: str):
"""
Selects a new color using a color dialog and applies it to the specified button. Updates
related configuration properties based on the chosen color.
Update configuration when the color button emits a change.
Args:
button: The button widget whose color is being modified.
new_color (str): The new color in hex format.
"""
current_color = QColor(button.color())
chosen_color = QColorDialog.getColor(current_color, self.tree, "Select Curve Color")
if chosen_color.isValid():
button.set_color(chosen_color)
self.config.color = chosen_color.name()
self.config.symbol_color = chosen_color.name()
self.config.color = new_color
self.config.symbol_color = new_color
def add_dap_row(self):
"""Create a new DAP row as a child. Only valid if source='device'."""

View File

@ -1,5 +1,8 @@
from __future__ import annotations
from qtpy.QtCore import Signal
from qtpy.QtGui import QColor
from qtpy.QtWidgets import QPushButton
from qtpy.QtWidgets import QColorDialog, QPushButton
from bec_widgets import BECWidget, SafeProperty, SafeSlot
@ -12,6 +15,8 @@ class ColorButtonNative(BECWidget, QPushButton):
to guarantee good readability.
"""
color_changed = Signal(str)
RPC = False
PLUGIN = True
ICON_NAME = "colors"
@ -25,9 +30,10 @@ class ColorButtonNative(BECWidget, QPushButton):
"""
super().__init__(parent=parent, **kwargs)
self.set_color(color)
self.clicked.connect(self._open_color_dialog)
@SafeSlot()
def set_color(self, color):
def set_color(self, color: str | QColor):
"""Set the button's color and update its appearance.
Args:
@ -38,6 +44,7 @@ class ColorButtonNative(BECWidget, QPushButton):
else:
self._color = color
self._update_appearance()
self.color_changed.emit(self._color)
@SafeProperty("QColor")
def color(self):
@ -56,3 +63,11 @@ class ColorButtonNative(BECWidget, QPushButton):
text_color = "#000000" if brightness > 0.5 else "#FFFFFF"
self.setStyleSheet(f"background-color: {self._color}; color: {text_color};")
self.setText(self._color)
@SafeSlot()
def _open_color_dialog(self):
"""Open a QColorDialog and apply the selected color."""
current_color = QColor(self._color)
chosen_color = QColorDialog.getColor(current_color, self, "Select Curve Color")
if chosen_color.isValid():
self.set_color(chosen_color)

View File

@ -0,0 +1,87 @@
from qtpy.QtCore import Qt
from qtpy.QtGui import QColor
from qtpy.QtWidgets import QColorDialog
from bec_widgets.widgets.utility.visual.color_button_native.color_button_native import (
ColorButtonNative,
)
from .conftest import create_widget
def test_color_button_native(qtbot):
cb = create_widget(qtbot, ColorButtonNative)
# Check if the instance is created successfully
assert cb is not None
# Check if the button has a default color
assert cb.color is not None
# Check if the button can change color
new_color = QColor(255, 0, 0) # Red
cb.set_color(new_color)
assert cb.color == new_color.name()
def test_color_dialog_applies_chosen_color(qtbot, monkeypatch):
"""Clicking the button should open the dialog and apply the selected color."""
cb = create_widget(qtbot, ColorButtonNative)
chosen_color = QColor(0, 255, 0) # Green
# Force QColorDialog.getColor to return our chosen color
monkeypatch.setattr(QColorDialog, "getColor", lambda *args, **kwargs: chosen_color)
# Expect the color_changed signal during the click
with qtbot.waitSignal(cb.color_changed, timeout=1000):
qtbot.mouseClick(cb, Qt.LeftButton)
assert cb.color == chosen_color.name()
def test_color_dialog_cancel_keeps_color(qtbot, monkeypatch):
"""If the dialog returns an invalid color, the button color should stay the same."""
cb = create_widget(qtbot, ColorButtonNative)
original_color = cb.color
# Simulate cancel: return an invalid QColor
monkeypatch.setattr(QColorDialog, "getColor", lambda *args, **kwargs: QColor())
qtbot.mouseClick(cb, Qt.LeftButton)
# No signal emitted, color unchanged
assert cb.color == original_color
# Additional tests for color property getter/setter
def test_color_property_getter_setter_hex(qtbot):
"""Verify the color property works correctly with hex strings."""
cb = create_widget(qtbot, ColorButtonNative)
# Confirm default value is a valid hex string
default_color = cb.color
assert (
isinstance(default_color, str) and default_color.startswith("#") and len(default_color) == 7
)
# Use property setter with a new hex color
new_color_hex = "#123456"
with qtbot.waitSignal(cb.color_changed, timeout=1000):
cb.color = new_color_hex
# Getter should reflect the new value
assert cb.color == new_color_hex
# Button text should update as well
assert cb.text() == new_color_hex
def test_color_property_setter_qcolor(qtbot):
"""Verify the color property accepts QColor and emits the signal."""
cb = create_widget(qtbot, ColorButtonNative)
q_color = QColor(200, 100, 50)
with qtbot.waitSignal(cb.color_changed, timeout=1000):
cb.color = q_color
assert cb.color == q_color.name()
assert cb.text() == q_color.name()