Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move qtpy functionality from brainglobe-segmentation & cellfinder #27

Merged
merged 2 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions brainglobe_utils/qtpy/dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from qtpy.QtWidgets import QMessageBox, QWidget

Check warning on line 1 in brainglobe_utils/qtpy/dialog.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/dialog.py#L1

Added line #L1 was not covered by tests


def display_warning(widget: QWidget, title: str, message: str) -> bool:

Check warning on line 4 in brainglobe_utils/qtpy/dialog.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/dialog.py#L4

Added line #L4 was not covered by tests
"""
Display a warning in a pop-up that can be accepted or dismissed
"""
message_reply = QMessageBox.question(

Check warning on line 8 in brainglobe_utils/qtpy/dialog.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/dialog.py#L8

Added line #L8 was not covered by tests
widget,
title,
message,
QMessageBox.Yes | QMessageBox.Cancel,
)
if message_reply == QMessageBox.Yes:
return True

Check warning on line 15 in brainglobe_utils/qtpy/dialog.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/dialog.py#L14-L15

Added lines #L14 - L15 were not covered by tests
else:
return False

Check warning on line 17 in brainglobe_utils/qtpy/dialog.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/dialog.py#L17

Added line #L17 was not covered by tests


def display_info(widget, title, message):

Check warning on line 20 in brainglobe_utils/qtpy/dialog.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/dialog.py#L20

Added line #L20 was not covered by tests
"""
Display information in a pop-up that can only be accepted
"""
QMessageBox.information(

Check warning on line 24 in brainglobe_utils/qtpy/dialog.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/dialog.py#L24

Added line #L24 was not covered by tests
widget,
title,
message,
QMessageBox.Ok,
)
138 changes: 138 additions & 0 deletions brainglobe_utils/qtpy/interaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
from typing import Callable, List, Optional, Tuple

from qtpy.QtWidgets import (
QCheckBox,
QComboBox,
QDoubleSpinBox,
QLabel,
QLayout,
QPushButton,
QSpinBox,
)


def add_button(
label: str,
layout: QLayout,
connected_function: Callable,
*,
row: int = 0,
column: int = 0,
visibility: bool = True,
minimum_width: int = 0,
alignment: str = "center",
tooltip: Optional[str] = None,
) -> QPushButton:
"""
Add a button to *layout*.
"""
button = QPushButton(label)
if alignment == "center":
pass
elif alignment == "left":
button.setStyleSheet("QPushButton { text-align: left; }")
elif alignment == "right":
button.setStyleSheet("QPushButton { text-align: right; }")

button.setVisible(visibility)
button.setMinimumWidth(minimum_width)

if tooltip:
button.setToolTip(tooltip)

Check warning on line 41 in brainglobe_utils/qtpy/interaction.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/interaction.py#L41

Added line #L41 was not covered by tests

layout.addWidget(button, row, column)
button.clicked.connect(connected_function)
return button


def add_checkbox(
layout, default, label, row: int = 0, column: int = 0, tooltip=None
):
box = QCheckBox()
box.setChecked(default)
if tooltip:
box.setToolTip(tooltip)
layout.addWidget(QLabel(label), row, column)
layout.addWidget(box, row, column + 1)
return box

Check warning on line 57 in brainglobe_utils/qtpy/interaction.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/interaction.py#L51-L57

Added lines #L51 - L57 were not covered by tests


def add_float_box(
layout,
default,
minimum,
maximum,
label,
step,
row: int = 0,
column: int = 0,
tooltip=None,
):
box = QDoubleSpinBox()
box.setMinimum(minimum)
box.setMaximum(maximum)
box.setValue(default)
box.setSingleStep(step)
if tooltip:
box.setToolTip(tooltip)
layout.addWidget(QLabel(label), row, column)
layout.addWidget(box, row, column + 1)
return box

Check warning on line 80 in brainglobe_utils/qtpy/interaction.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/interaction.py#L71-L80

Added lines #L71 - L80 were not covered by tests


def add_int_box(
layout,
default,
minimum,
maximum,
label,
row: int = 0,
column: int = 0,
tooltip=None,
):
box = QSpinBox()
box.setMinimum(minimum)
box.setMaximum(maximum)

Check warning on line 95 in brainglobe_utils/qtpy/interaction.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/interaction.py#L93-L95

Added lines #L93 - L95 were not covered by tests
# Not always set if not after min & max
box.setValue(default)
if tooltip:
box.setToolTip(tooltip)
layout.addWidget(QLabel(label), row, column)
layout.addWidget(box, row, column + 1)
return box

Check warning on line 102 in brainglobe_utils/qtpy/interaction.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/interaction.py#L97-L102

Added lines #L97 - L102 were not covered by tests


def add_combobox(
layout: QLayout,
label: str,
items: List[str],
row: int = 0,
column: int = 0,
label_stack: bool = False,
callback=None,
width: int = 150,
) -> Tuple[QComboBox, Optional[QLabel]]:
"""
Add a selection box to *layout*.
"""
if label_stack:
combobox_row = row + 1
combobox_column = column
else:
combobox_row = row
combobox_column = column + 1
combobox = QComboBox()
combobox.addItems(items)
if callback:
combobox.currentIndexChanged.connect(callback)

Check warning on line 127 in brainglobe_utils/qtpy/interaction.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_utils/qtpy/interaction.py#L127

Added line #L127 was not covered by tests
combobox.setMaximumWidth = width

if label is not None:
combobox_label = QLabel(label)
combobox_label.setMaximumWidth = width
layout.addWidget(combobox_label, row, column)
else:
combobox_label = None

layout.addWidget(combobox, combobox_row, combobox_column)
return combobox, combobox_label
39 changes: 39 additions & 0 deletions tests/tests/test_qtpy/test_interaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pytest
from qtpy.QtWidgets import QGridLayout

from brainglobe_utils.qtpy.interaction import add_button, add_combobox


@pytest.mark.parametrize("label_stack", [True, False])
@pytest.mark.parametrize("label", ["A label", None])
def test_add_combobox(label, label_stack):
"""
Smoke test for add_combobox for all conditional branches
"""
layout = QGridLayout()
combobox = add_combobox(
layout,
row=0,
label=label,
items=["item 1", "item 2"],
label_stack=label_stack,
)
assert combobox is not None


@pytest.mark.parametrize(
argnames="alignment", argvalues=["center", "left", "right"]
)
def test_add_button(alignment):
"""
Smoke tests for add_button for all conditional branches
"""
layout = QGridLayout()
button = add_button(
layout=layout,
connected_function=lambda: None,
label="A button",
row=0,
alignment=alignment,
)
assert button is not None