diff --git a/brainglobe_utils/qtpy/dialog.py b/brainglobe_utils/qtpy/dialog.py new file mode 100644 index 0000000..9ba3cde --- /dev/null +++ b/brainglobe_utils/qtpy/dialog.py @@ -0,0 +1,29 @@ +from qtpy.QtWidgets import QMessageBox, QWidget + + +def display_warning(widget: QWidget, title: str, message: str) -> bool: + """ + Display a warning in a pop-up that can be accepted or dismissed + """ + message_reply = QMessageBox.question( + widget, + title, + message, + QMessageBox.Yes | QMessageBox.Cancel, + ) + if message_reply == QMessageBox.Yes: + return True + else: + return False + + +def display_info(widget, title, message): + """ + Display information in a pop-up that can only be accepted + """ + QMessageBox.information( + widget, + title, + message, + QMessageBox.Ok, + ) diff --git a/brainglobe_utils/qtpy/interaction.py b/brainglobe_utils/qtpy/interaction.py new file mode 100644 index 0000000..a5ac1d8 --- /dev/null +++ b/brainglobe_utils/qtpy/interaction.py @@ -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) + + 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 + + +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 + + +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) + # 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 + + +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) + 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 diff --git a/tests/tests/test_qtpy/test_interaction.py b/tests/tests/test_qtpy/test_interaction.py new file mode 100644 index 0000000..68fd1f3 --- /dev/null +++ b/tests/tests/test_qtpy/test_interaction.py @@ -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