Source code for jdxi_editor.ui.widgets.combo_box.combo_box

"""
combo_box.py
============

This module provides a custom `ComboBox` widget that extends `QWidget`.

The `ComboBox` class combines a label and a dropdown menu (QComboBox), allowing users
to select from a list of options, where each option is mapped to a corresponding integer value.
It emits a `valueChanged` signal whenever the selected value changes.

Classes
--------
- ComboBox: A labeled combo box with a value-mapping system.

Example Usage
--------------
.. code-block:: python

    from PySide6.QtWidgets import QApplication
    from combo_box import ComboBox

    app = QApplication([])

    options = ["Low", "Medium", "High"]
    values = [10, 50, 100]

    combo = ComboBox("Select Level:", options, values)
    combo.valueChanged.connect(lambda v: log.message(f"Selected Value: {v}"))

    combo.show()
    app.exec()

Attributes
-----------
- valueChanged (Signal): Emitted when the selected value changes.

Methods
--------
- setValue(value: int): Set the selected value in the combo box.
- setOptions(options: list, values: list): Update the combo box options and their corresponding values.
- value() -> int: Get the currently selected value.
- setEnabled(enabled: bool): Enable or disable the widget.
- setVisible(visible: bool): Show or hide the widget.
- setMinimumWidth(width: int): Set the minimum width of the label.
- setMaximumWidth(width: int): Set the maximum width of the label.

"""

from PySide6.QtCore import Signal, Slot
from PySide6.QtWidgets import QComboBox, QHBoxLayout, QLabel, QWidget


[docs] class ComboBox(QWidget): """Custom ComboBox widget with label and value mapping."""
[docs] valueChanged = Signal(int) # Define signal to emit selected value
def __init__( self, label: str, options: list[str], values: list[int] | None = None, parent: object | None = None, show_label: bool = True, tooltip: str = "", # Optional tooltip parameter ) -> None: """ Initialize the ComboBox widget. :param label: Label text :param options: List of option strings to digital :param values: List of corresponding integer values :param parent: Parent widget :param show_label: Whether to show the label """ super().__init__(parent)
[docs] self.options = options
[docs] self.values = values
# QWidget.setToolTip requires str; param.get_tooltip() may return a list if isinstance(tooltip, str): tooltip_str = tooltip elif isinstance(tooltip, (list, tuple)): tooltip_str = "\n".join(str(x) for x in tooltip) if tooltip else "" else: tooltip_str = str(tooltip) if tooltip is not None else "" self.setToolTip(tooltip_str) # QLabel requires str; spec.label / display_name may be a list if isinstance(label, str): label_str = label elif isinstance(label, (list, tuple)): label_str = label[0] if label else "" else: label_str = str(label) if label is not None else "" # Main layout layout = QHBoxLayout() self.setLayout(layout) # Create label
[docs] self.label_widget = QLabel(label_str)
if show_label: layout.addWidget(self.label_widget) # Properly add label when needed else: self.label_widget.hide() # Hide label if not needed # Create combo box
[docs] self.combo_box = QComboBox()
self.combo_box.addItems(options) layout.addWidget(self.combo_box) # Ensure label width consistency self.combo_box.setMaximumWidth(350) self.combo_box.setMaximumHeight(25) # Connect combo box index change to emit mapped value self.combo_box.currentIndexChanged.connect(self._on_valueChanged) @Slot(int)
[docs] def _on_valueChanged(self, index: int) -> None: """Emit the corresponding value when the selected index changes. :param index: int """ if self.values: if 0 <= index < len(self.values): self.valueChanged.emit(self.values[index]) else: self.valueChanged.emit(int(index))
[docs] def setLabelVisible(self, visible: bool) -> None: """Show or hide the label dynamically. :param visible: bool """ self.label_widget.setVisible(visible)
[docs] def setValue(self, value: int) -> None: """Set combo box index based on the value. :param value: int """ if self.values: if value in self.values: index = self.values.index(value) self.combo_box.setCurrentIndex(index)
[docs] def value(self) -> int: """Get current index :return: int """ return self.combo_box.currentIndex()