fix(bec_progress_bar): replace the custom paint event progressbar with native QProgressBar

This commit is contained in:
2026-05-26 11:32:39 +02:00
parent af125e2222
commit cd150c09a9
7 changed files with 580 additions and 158 deletions
+134 -7
View File
@@ -1,5 +1,8 @@
import numpy as np
from unittest import mock
import pytest
from qtpy.QtGui import QPalette
from qtpy.QtWidgets import QProgressBar
from bec_widgets.widgets.progress.bec_progressbar.bec_progressbar import (
BECProgressBar,
@@ -15,6 +18,14 @@ def progressbar(qtbot):
yield widget
@pytest.fixture
def static_progressbar(qtbot):
widget = BECProgressBar(enable_dynamic_stylesheet=False)
qtbot.addWidget(widget)
qtbot.waitExposed(widget)
yield widget
def test_progressbar(progressbar):
progressbar.update()
@@ -23,21 +34,137 @@ def test_progressbar_set_value(qtbot, progressbar):
progressbar.set_minimum(0)
progressbar.set_maximum(100)
progressbar.set_value(50)
progressbar.paintEvent(None)
qtbot.waitUntil(
lambda: np.isclose(
progressbar._value, progressbar._user_value * progressbar._oversampling_factor
)
)
assert isinstance(progressbar.progressbar, QProgressBar)
assert progressbar._value == progressbar._user_value * progressbar._oversampling_factor
assert progressbar.progressbar.value() == 50 * progressbar._oversampling_factor
def test_progressbar_label(progressbar):
progressbar.label_template = "Test: $value"
progressbar.set_value(50)
assert progressbar._get_label() == "Test: 50"
assert progressbar.center_label.text() == "Test: 50"
def test_progressbar_equal_minimum_and_maximum_does_not_raise(progressbar):
progressbar.set_minimum(0)
progressbar.set_maximum(0)
progressbar.set_value(0)
assert progressbar._get_label() == "0 / 0 - 100 %"
assert progressbar.progressbar.value() == progressbar.progressbar.maximum()
def test_progressbar_uses_static_stylesheet_with_palette_state_color(progressbar):
progressbar.progressbar.resize(100, 20)
progressbar.set_value(50)
progressbar.state = ProgressState.PAUSED
style_sheet = progressbar.progressbar.styleSheet()
assert "QProgressBar::chunk" in style_sheet
assert "background-color: palette(highlight);" in style_sheet
assert "background-color: palette(mid);" in style_sheet
assert "border-radius: 7px;" in style_sheet
assert (
progressbar.progressbar.palette().color(QPalette.ColorRole.Highlight)
== progressbar._state_colors[ProgressState.PAUSED]
)
def test_progressbar_value_updates_do_not_rebuild_stylesheet_within_same_chunk_mode(progressbar):
progressbar.progressbar.resize(100, 20)
progressbar.set_value(30)
with mock.patch.object(
progressbar, "_setup_style_sheet", wraps=progressbar._setup_style_sheet
) as setup_style_sheet:
progressbar.set_value(35)
progressbar.set_value(42)
progressbar.set_value(50)
setup_style_sheet.assert_not_called()
def test_progressbar_value_updates_skip_chunk_radius_after_target_reached(progressbar):
progressbar.progressbar.resize(100, 20)
progressbar.set_value(30)
assert progressbar._chunk_radius == progressbar._target_chunk_radius()
with mock.patch.object(
progressbar, "_update_chunk_radius", wraps=progressbar._update_chunk_radius
) as update_chunk_radius:
progressbar.set_value(35)
progressbar.set_value(42)
progressbar.set_value(50)
update_chunk_radius.assert_not_called()
def test_progressbar_repeated_same_maximum_does_not_reset_chunk_radius(progressbar):
progressbar.progressbar.resize(100, 20)
progressbar.set_maximum(100)
progressbar.set_value(30)
assert progressbar._chunk_radius == progressbar._target_chunk_radius()
with mock.patch.object(
progressbar, "_update_chunk_radius", wraps=progressbar._update_chunk_radius
) as update_chunk_radius:
progressbar.set_maximum(100)
progressbar.set_value(40)
update_chunk_radius.assert_not_called()
def test_progressbar_can_disable_dynamic_stylesheet(static_progressbar):
static_progressbar.progressbar.resize(100, 20)
assert static_progressbar.enable_dynamic_stylesheet is False
assert static_progressbar._chunk_radius == static_progressbar._target_chunk_radius()
with mock.patch.object(
static_progressbar, "_setup_style_sheet", wraps=static_progressbar._setup_style_sheet
) as setup_style_sheet:
static_progressbar.set_value(1)
static_progressbar.set_value(2)
static_progressbar.set_value(3)
setup_style_sheet.assert_not_called()
assert "border-radius: 7px;" in static_progressbar.progressbar.styleSheet()
def test_progressbar_dynamic_stylesheet_can_be_toggled(progressbar):
progressbar.enable_dynamic_stylesheet = False
assert progressbar.enable_dynamic_stylesheet is False
assert progressbar._chunk_radius == progressbar._target_chunk_radius()
assert "border-radius: 7px;" in progressbar.progressbar.styleSheet()
def test_progressbar_rebuilds_stylesheet_until_chunk_radius_reaches_target(progressbar):
progressbar.progressbar.resize(100, 20)
progressbar.set_value(9)
with mock.patch.object(
progressbar, "_setup_style_sheet", wraps=progressbar._setup_style_sheet
) as setup_style_sheet:
progressbar.set_value(12)
progressbar.set_value(25)
progressbar.set_value(30)
assert setup_style_sheet.call_count == 2
assert "border-radius: 7px;" in progressbar.progressbar.styleSheet()
def test_progressbar_resets_chunk_radius_when_value_goes_backwards(progressbar):
progressbar.progressbar.resize(100, 20)
progressbar.set_value(30)
assert "border-radius: 7px;" in progressbar.progressbar.styleSheet()
progressbar.set_value(4)
assert "border-radius: 2px;" in progressbar.progressbar.styleSheet()
def test_progress_state_from_bec_status():
"""ProgressState.from_bec_status() maps BEC literals correctly."""
mapping = {