mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-13 11:11:49 +02:00
fix(color_button_native): popup logic to choose color moved to ColorButtonNative
This commit is contained in:
@ -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'."""
|
||||
|
@ -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)
|
||||
|
87
tests/unit_tests/test_color_button_native.py
Normal file
87
tests/unit_tests/test_color_button_native.py
Normal 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()
|
Reference in New Issue
Block a user