Skip to content

Commit

Permalink
CollapsibleWidget using superqt with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
IgorTatarnikov committed Nov 13, 2023
1 parent e2ebf8e commit 83d2653
Show file tree
Hide file tree
Showing 6 changed files with 336 additions and 86 deletions.
27 changes: 0 additions & 27 deletions brainglobe_utils/qtpy/chest.py

This file was deleted.

162 changes: 162 additions & 0 deletions brainglobe_utils/qtpy/collapsible_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
from typing import List, overload

from qtpy.QtCore import Qt, Signal
from qtpy.QtWidgets import QGroupBox, QVBoxLayout, QWidget
from superqt.collapsible import QCollapsible


class CollapsibleWidget(QCollapsible):
"""
Custom collapsible widget.
Attributes
----------
toggled_signal_with_self : Signal
Emitted when the CollapsibleWidget is toggled.
Provides the CollapsibleWidget instance and the new state.
Parameters
----------
title : str, optional
The title of the CollapsibleWidget.
parent : QWidget or None, optional
The parent widget.
expanded_icon : str or None, optional
The ASCII symbol for the expanded state.
collapsed_icon : str or None, optional
The ASCII symbol for the collapsed state.
"""

toggled_signal_with_self = Signal(QCollapsible, bool)

def __init__(
self,
title: str = "",
parent: QWidget | None = None,
expanded_icon: str | None = "▲",
collapsed_icon: str | None = "▼",
):
"""
Initializes a new CollapsibleWidget instance.
Parameters
----------
title : str, optional
The title of the CollapsibleWidget.
parent : QWidget or None, optional
The parent widget.
expanded_icon : str or None, optional
The icon for the expanded state.
collapsed_icon : str or None, optional
The icon for the collapsed state.
"""
super().__init__(title, parent, expanded_icon, collapsed_icon)
self.currently_expanded = False

self.toggled.connect(self._on_toggle)

def _on_toggle(self, state):
"""
Handles the toggled signal by emitting the custom signal
with the CollapsibleWidget instance and the new state.
Parameters
----------
state : bool
The new state of the CollapsibleWidget
(True if expanded, False if collapsed).
"""
self.toggled_signal_with_self.emit(self, state)


class CollapsibleWidgetContainer(QGroupBox):
"""
Container for multiple CollapsibleWidgets with the ability to add,
remove, and synchronize their states.
Methods
-------
add_widget(QWidget or CollapsibleWidget)
Adds a widget to the CollapsibleWidgetContainer.
remove_drawer(QWidget or CollapsibleWidget)
Removes a widget from the CollapsibleWidgetContainer.
_update_drawers(signalling_drawer, state)
Private method to synchronize drawer states.
"""

def __init__(self):
"""
Initializes a new CollapsibleWidgetContainer instance.
"""
super().__init__()
self.setLayout(QVBoxLayout())

self.layout().setAlignment(Qt.AlignTop)
self.layout().setSpacing(0)
self.layout().setContentsMargins(0, 0, 0, 0)
self.collapsible_widgets: List[CollapsibleWidget] = []

@overload
def add_widget(self, widget: QWidget):
...

@overload
def add_widget(self, widget: CollapsibleWidget):
...

def add_widget(self, widget: QWidget | CollapsibleWidget):
"""
Adds a QWidget or a CollapsibleWidget to the chest.
Parameters
----------
widget : QWidget or CollapsibleWidget
The widget instance to be added.
"""
if isinstance(widget, CollapsibleWidget):
self.collapsible_widgets.append(widget)
widget.toggled_signal_with_self.connect(self._update_drawers)

self.layout().addWidget(widget, 0, Qt.AlignTop)

@overload
def remove_widget(self, widget: QWidget):
...

@overload
def remove_widget(self, widget: CollapsibleWidget):
...

def remove_widget(self, widget: QWidget | CollapsibleWidget):
"""
Removes a widget from the chest.
Parameters
----------
widget : QWidget or CollapsibleWidget
The widget instance to be removed.
"""
if isinstance(widget, CollapsibleWidget):
self.collapsible_widgets.remove(widget)
widget.toggled_signal_with_self.disconnect(self._update_drawers)

self.layout().removeWidget(widget)

def _update_drawers(
self, signalling_widget: CollapsibleWidget, state: bool
):
"""
Synchronizes CollapsibleWidget states to ensure only one
CollapsibleWidget is expanded at a time.
Parameters
----------
signalling_widget : CollapsibleWidget
The CollapsibleWidget emitting the signal.
state : bool
The new state of the signalling_widget.
"""
if state:
for collapsible_widget in self.collapsible_widgets:
if collapsible_widget is not signalling_widget:
collapsible_widget.collapse(False)
41 changes: 0 additions & 41 deletions brainglobe_utils/qtpy/drawer.py

This file was deleted.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies = [
"PyYAML",
"scipy",
"scikit-image",
"superqt",
]

license = {text = "MIT"}
Expand Down
Loading

0 comments on commit 83d2653

Please sign in to comment.