Skip to content

Commit deabe8d

Browse files
authored
0.8.0
Develop
2 parents 8d0da63 + a01cee2 commit deabe8d

File tree

6 files changed

+179
-73
lines changed

6 files changed

+179
-73
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file.
66
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
77
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
88

9+
## [0.8.0] - 2025-07-18
10+
11+
### Added
12+
- `widgets.ColoredButton`: as the name suggests ...
13+
14+
### Changed
15+
- `widgets.SlideToggle`: tweaked color-scheme
16+
917
## [0.7.1] - 2025-07-16
1018

1119
### Changed
@@ -145,6 +153,7 @@ _First release._
145153
providing color-mapped numerical data.
146154
- `widgets.StatefulButton`: A `QPushButton` that maintains an active/inactive state.
147155

156+
[0.8.0]: https://github.com/int-brain-lab/iblqt/releases/tag/v0.8.0
148157
[0.7.1]: https://github.com/int-brain-lab/iblqt/releases/tag/v0.7.1
149158
[0.7.0]: https://github.com/int-brain-lab/iblqt/releases/tag/v0.7.0
150159
[0.6.1]: https://github.com/int-brain-lab/iblqt/releases/tag/v0.6.1

iblqt/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
11
"""A collection of extensions to the Qt framework."""
2-
3-
__version__ = '0.7.1'

iblqt/widgets.py

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,64 @@ def editorEvent(
147147
return super().editorEvent(event, model, option, index)
148148

149149

150-
class StatefulButton(QPushButton):
150+
class ColoredButton(QPushButton):
151+
"""A QPushButton that can change color."""
152+
153+
def __init__(
154+
self,
155+
text: str,
156+
color: QColor | None = None,
157+
parent: QWidget | None = None,
158+
**kwargs,
159+
):
160+
"""
161+
Initialize the ColoredButton.
162+
163+
Parameters
164+
----------
165+
text : str
166+
The text to be displayed.
167+
color : QColor, optional
168+
The color to use for the button.
169+
parent : QWidget
170+
The parent widget.
171+
**kwargs : dict
172+
Arbitrary keyword arguments (passed to QPushButton).
173+
"""
174+
super().__init__(text, parent, **kwargs)
175+
self._original_color = self.palette().color(QPalette.Button)
176+
if color is not None:
177+
self.setColor(color)
178+
179+
def setColor(self, color: QColor | None) -> None:
180+
"""
181+
Set the color of the button.
182+
183+
Parameters
184+
----------
185+
color : QColor, optional
186+
The new color of the button. If None, the color will be reset to it's
187+
default color.
188+
"""
189+
palette = self.palette()
190+
palette.setColor(QPalette.Button, color or self._original_color)
191+
self.setPalette(palette)
192+
self.setAutoFillBackground(True)
193+
self.update()
194+
195+
def color(self) -> QColor:
196+
"""
197+
Return the color of the button.
198+
199+
Returns
200+
-------
201+
QColor
202+
The color of the button.
203+
"""
204+
return self.palette().color(QPalette.Button)
205+
206+
207+
class StatefulButton(ColoredButton):
151208
"""A QPushButton that maintains an active/inactive state."""
152209

153210
clickedWhileActive = Signal() # type: Signal
@@ -166,8 +223,10 @@ def __init__(
166223
textInactive: str | None = None,
167224
active: bool = False,
168225
parent: QWidget | None = None,
226+
**kwargs: dict[str, Any],
169227
):
170-
"""Initialize the StatefulButton with the specified active state.
228+
"""
229+
Initialize the StatefulButton with the specified active state.
171230
172231
Parameters
173232
----------
@@ -179,11 +238,18 @@ def __init__(
179238
Initial state of the button (default is False).
180239
parent : QWidget
181240
The parent widget.
241+
**kwargs : dict
242+
Arbitrary keyword arguments (passed to ColoredButton).
182243
"""
183244
self._isActive = active
184245
self._textActive = textActive or ''
185246
self._textInactive = textInactive or ''
186-
super().__init__(self._textActive if active else self._textInactive, parent)
247+
super().__init__(
248+
text=self._textActive if active else self._textInactive,
249+
color=None,
250+
parent=parent,
251+
**kwargs,
252+
)
187253

188254
self.clicked.connect(self._onClick)
189255
self.stateChanged.connect(self._onStateChange)
@@ -281,7 +347,10 @@ def _onClick(self):
281347
@Slot(bool)
282348
def _onStateChange(self, state: bool):
283349
"""Handle the state change event."""
284-
self.setText(self._textActive if state is True else self._textInactive)
350+
if state is True:
351+
self.setText(self._textActive)
352+
if state is False:
353+
self.setText(self._textInactive)
285354

286355

287356
class UseTokenCache(IntEnum):
@@ -913,11 +982,12 @@ def paintEvent(self, event: QPaintEvent):
913982
# Determine colors based on state
914983
palette = self.palette()
915984
if not self.isEnabled():
916-
color_background = palette.shadow().color()
917-
color_foreground = palette.midlight().color()
985+
color_background = palette.dark().color()
986+
color_background.setAlphaF(0.6)
987+
color_foreground = palette.window().color()
918988
elif self.isChecked():
919989
color_background = palette.highlight().color()
920-
color_foreground = palette.highlightedText().color()
990+
color_foreground = palette.light().color()
921991
else:
922992
color_background = palette.dark().color()
923993
color_foreground = palette.light().color()

pyproject.toml

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
[build-system]
2-
requires = ["pdm-backend"]
3-
build-backend = "pdm.backend"
2+
requires = ["uv_build"]
3+
build-backend = "uv_build"
44

55
[project]
66
name = "iblqt"
7+
version = "0.8.0"
78
description = "A collection of extensions to the Qt framework."
89
dependencies = [
910
"qtpy>=2.4.1",
@@ -20,7 +21,6 @@ license = {text = "MIT"}
2021
authors = [
2122
{name = "Florian Rau", email = "[email protected]"},
2223
]
23-
dynamic = ["version"]
2424

2525
[project.optional-dependencies]
2626
pyqt5 = [
@@ -85,16 +85,11 @@ required-environments = [
8585
"sys_platform == 'darwin'",
8686
]
8787

88-
[tool.pdm]
89-
distribution = true
90-
91-
[tool.pdm.build]
92-
excludes = [ "docs/source/api" ]
93-
source-includes = [ "tests/*.py", "resources/", "docs/source/" ]
94-
95-
[tool.pdm.version]
96-
source = "file"
97-
path = "iblqt/__init__.py"
88+
[tool.uv.build-backend]
89+
module-name = "iblqt"
90+
module-root = ""
91+
source-include = [ "tests/*.py", "resources/**/*", "docs/source/**/*" ]
92+
source-exclude = [ "docs/source/api" ]
9893

9994
[tool.ruff]
10095
include = ["pyproject.toml", "iblqt/**/*.py", "tests/**/*.py"]

tests/test_widgets.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,39 @@ def test_painting_checkbox(self, qtbot, setup_method):
6666
self.delegate.paint(painter, option, index)
6767

6868

69+
class TestColoredButton:
70+
@pytest.fixture
71+
def button_factory(self, qtbot):
72+
def _create_button(text='Click Me', color=None, parent=None):
73+
button = widgets.ColoredButton(text, color=color, parent=parent)
74+
qtbot.addWidget(button)
75+
return button
76+
77+
return _create_button
78+
79+
def test_default_color(self, button_factory):
80+
button = button_factory()
81+
default_color = button._original_color
82+
assert button.color() == default_color
83+
84+
def test_initial_color(self, button_factory):
85+
button = button_factory(color=QColor('red'))
86+
assert button.color() == QColor('red')
87+
88+
def test_set_color(self, button_factory):
89+
button = button_factory()
90+
new_color = QColor('red')
91+
button.setColor(new_color)
92+
assert button.color() == new_color
93+
94+
def test_resets_color(self, button_factory):
95+
button = button_factory()
96+
original = button._original_color
97+
button.setColor(QColor('blue'))
98+
button.setColor(None)
99+
assert button.color() == original
100+
101+
69102
class TestStatefulButton:
70103
def test_initial_state(self, qtbot):
71104
"""Test the initial state of the StatefulButton."""

0 commit comments

Comments
 (0)