Skip to content

MultiComboBox

Qt Base Class: QComboBox

Signature: QComboBox(self, parent: Optional[PySide6.QtWidgets.QWidget] = None) -> None

Base classes

Name Children Inherits
ComboBox
prettyqt.widgets.combobox

⋔ Inheritance diagram

graph TD
  1473367122368["custom_widgets.MultiComboBox"]
  1473296236368["widgets.ComboBox"]
  1473296223680["widgets.ComboBoxMixin"]
  1473293688240["widgets.WidgetMixin"]
  1473299815024["core.ObjectMixin"]
  140713234304496["builtins.object"]
  1473245548480["gui.PaintDeviceMixin"]
  1473241370080["QtWidgets.QComboBox"]
  1473290849680["QtWidgets.QWidget"]
  1473288842240["QtCore.QObject"]
  1473291690208["Shiboken.Object"]
  1473300082368["QtGui.QPaintDevice"]
  1473296236368 --> 1473367122368
  1473296223680 --> 1473296236368
  1473293688240 --> 1473296223680
  1473299815024 --> 1473293688240
  140713234304496 --> 1473299815024
  1473245548480 --> 1473293688240
  140713234304496 --> 1473245548480
  1473241370080 --> 1473296236368
  1473290849680 --> 1473241370080
  1473288842240 --> 1473290849680
  1473291690208 --> 1473288842240
  140713234304496 --> 1473291690208
  1473300082368 --> 1473290849680
  1473291690208 --> 1473300082368

🛈 DocStrings

Bases: ComboBox

ComboBox allowing multiple-choice selection.

Source code in prettyqt\custom_widgets\multicombobox.py
class MultiComboBox(widgets.ComboBox):
    """ComboBox allowing multiple-choice selection."""

    selectionChanged = core.Signal(list)

    def __init__(self, parent: widgets.QWidget | None = None, **kwargs):
        super().__init__(parent=parent, **kwargs)
        self.setEditable(True)
        self.lineEdit().setReadOnly(True)
        self.setItemDelegate(SizeHintDelegate())

        # Hide and show popup when clicking the line edit
        self.lineEdit().installEventFilter(self)
        self._close_on_lineedit_click = False

        # Prevent popup from closing when clicking on an item
        self.view().viewport().installEventFilter(self)

        self.addItem("Show/Hide All", isChecked=True)

        self.model().itemChanged.connect(self._update_selection)
        self.model().dataChanged.connect(self._update_text)
        self.model().dataChanged.connect(self._emit_current_data)

    def _emit_current_data(self):
        self.selectionChanged.emit(self.currentData())

    def _update_selection(self, item: gui.QStandardItem):
        if item.index().row() == 0:
            state = item.checkState()
            with self.model().change_layout():
                for item in self.get_model_items():
                    item.setCheckState(state)

    def resizeEvent(self, event):
        # Recompute text to elide as needed
        self._update_text()
        super().resizeEvent(event)

    def eventFilter(self, source, event):
        if source == self.lineEdit():
            if event.type() == core.QEvent.Type.MouseButtonRelease:
                if self._close_on_lineedit_click:
                    self.hidePopup()
                else:
                    self.showPopup()
                return True
            return False

        if (
            source == self.view().viewport()
            and event.type() == core.QEvent.Type.MouseButtonRelease
        ):
            index = self.view().indexAt(event.pos())
            item = self.model().itemFromIndex(index)
            item.toggle_checkstate()
            return True
        return False

    def showPopup(self):
        super().showPopup()
        # When the popup is displayed, a click on the lineedit should close it
        self._close_on_lineedit_click = True

    def hidePopup(self):
        super().hidePopup()
        # Used to prevent immediate reopening when clicking on the lineEdit
        self.startTimer(100)
        # Refresh the display text when closing
        self._update_text()

    def timerEvent(self, event):
        # After timeout, kill timer, and re-enable click on line edit
        self.killTimer(event.timerId())
        self._close_on_lineedit_click = False

    def _update_text(self):
        texts = [item.text() for item in self.get_model_items() if item.is_checked()]
        text = ", ".join(texts)
        # Compute elided text (with "...")
        metrics = gui.FontMetrics(self.lineEdit().font())
        text = metrics.elided_text(text, "right", self.lineEdit().width())
        self.lineEdit().setText(text)

    def addItem(self, text: str, data: Any = None, checked: bool = False, **kwargs):
        item = gui.StandardItem()
        item.setText(text)
        item.setData(text if data is None else data, constants.USER_ROLE)
        item.setFlags(constants.IS_ENABLED | constants.IS_CHECKABLE)
        item.set_checkstate(checked)
        self.model().appendRow(item)

    def addItems(
        self,
        items: list[str | tuple[str, Any]],
        all_checked: bool = False,
    ):
        for item in items:
            data = item[1] if isinstance(item, tuple) else item
            self.addItem(item, data, all_checked=all_checked)

    def currentData(
        self, role: constants.ItemDataRole = constants.USER_ROLE
    ) -> list[Any]:
        return [item.data(role) for item in self.get_model_items() if item.is_checked()]

    def get_current_options(self) -> list[tuple[str, Any]]:
        return [
            (item.text(), item.data(constants.USER_ROLE))
            for item in self.get_model_items()
            if item.is_checked()
        ]

    def get_model_items(self) -> Generator[gui.QStandardItem, None, None]:
        for i in range(1, self.model().rowCount()):
            yield self.model().item(i)

    def set_value(self, items: list[Any]):
        for item in self.get_model_items():
            if item.data(constants.USER_ROLE) in items:
                item.setChecked(True)

    def get_value(self) -> list[Any]:
        return self.currentData()

⌗ Property table

Qt Property Type Doc
objectName QString
modal bool
windowModality Qt::WindowModality
enabled bool
geometry QRect
frameGeometry QRect
normalGeometry QRect
x int
y int
pos QPoint
frameSize QSize
size QSize
width int
height int
rect QRect
childrenRect QRect
childrenRegion QRegion
sizePolicy QSizePolicy
minimumSize QSize
maximumSize QSize
minimumWidth int
minimumHeight int
maximumWidth int
maximumHeight int
sizeIncrement QSize
baseSize QSize
palette QPalette
font QFont
cursor QCursor
mouseTracking bool
tabletTracking bool
isActiveWindow bool
focusPolicy Qt::FocusPolicy
focus bool
contextMenuPolicy Qt::ContextMenuPolicy
updatesEnabled bool
visible bool
minimized bool
maximized bool
fullScreen bool
sizeHint QSize
minimumSizeHint QSize
acceptDrops bool
windowTitle QString
windowIcon QIcon
windowIconText QString
windowOpacity double
windowModified bool
toolTip QString
toolTipDuration int
statusTip QString
whatsThis QString
accessibleName QString
accessibleDescription QString
layoutDirection Qt::LayoutDirection
autoFillBackground bool
styleSheet QString
locale QLocale
windowFilePath QString
inputMethodHints QFlags
editable bool
count int
currentText QString
currentIndex int
currentData QVariant
maxVisibleItems int
maxCount int
insertPolicy QComboBox::InsertPolicy
sizeAdjustPolicy QComboBox::SizeAdjustPolicy
minimumContentsLength int
iconSize QSize
placeholderText QString
duplicatesEnabled bool
frame bool
modelColumn int