Skip to content

LayoutMixin

Base classes

Name Children Inherits
ObjectMixin
prettyqt.core.object
LayoutItemMixin
prettyqt.widgets.layoutitem

Subclasses

Class Module Description
Layout prettyqt.widgets.layout
FormLayout prettyqt.widgets.formlayout
BoxLayoutMixin prettyqt.widgets.boxlayout
StackedLayout prettyqt.widgets.stackedlayout
GridLayout prettyqt.widgets.gridlayout

â‹” Inheritance diagram

graph TD
  1473296333968["widgets.LayoutMixin"]
  1473299815024["core.ObjectMixin"]
  140713234304496["builtins.object"]
  1473296346656["widgets.LayoutItemMixin"]
  1473299815024 --> 1473296333968
  140713234304496 --> 1473299815024
  1473296346656 --> 1473296333968
  140713234304496 --> 1473296346656

🛈 DocStrings

Bases: ObjectMixin, LayoutItemMixin

Source code in prettyqt\widgets\layout.py
class LayoutMixin(core.ObjectMixin, widgets.LayoutItemMixin):
    def __init__(self, *args, margin=None, **kwargs):
        self._next_container = None
        self._stack = []
        super().__init__(*args, **kwargs)
        if margin is not None:
            self.set_margin(margin)

    @overload
    def __getitem__(
        self, index: slice
    ) -> listdelegators.ListDelegator[widgets.QWidget | widgets.QLayout]:
        ...

    @overload
    def __getitem__(self, index: int | str) -> widgets.QWidget | widgets.QLayout:
        ...

    def __getitem__(
        self, index: str | int | slice
    ) -> (
        widgets.QWidget
        | widgets.QLayout
        | listdelegators.ListDelegator[widgets.QWidget | widgets.QLayout]
    ):
        match index:
            case int():
                if index < 0:
                    index + self.count()
                if index < 0 or index >= self.count():
                    raise IndexError(index)
                item = self.itemAt(index)
                return i if (i := item.widget()) is not None else item.layout()
            case str():
                if (item := self.find_child(typ=core.QObject, name=index)) is not None:
                    return item
                raise KeyError(index)
            case slice():
                stop = index.stop or self.count()
                rng = range(index.start or 0, stop, index.step or 1)
                widgets = [self[i] for i in rng]
                return listdelegators.ListDelegator(widgets, parent=self)
            case _:
                raise TypeError(index)

    def __setitem__(self, key, value):
        if self._container != self:
            self._container.__setitem__(key, value)

    def __delitem__(self, item: int | widgets.QLayoutItem):
        if isinstance(item, int):
            item = self.itemAt(item)
        self.removeItem(item)
        item.deleteLater()

    def __len__(self) -> int:
        return self.count()

    def __iter__(self) -> Iterator[widgets.QWidget | widgets.QLayout | None]:
        return iter(self[i] for i in range(self.count()))

    def __contains__(self, item: widgets.QWidget | widgets.QLayoutItem):
        return self.indexOf(item) >= 0

    def __iadd__(self, item, *args, **kwargs):
        self.add(item, *args, **kwargs)
        return self

    def _get_map(self):
        maps = super()._get_map()
        maps |= {"sizeConstraint": SIZE_CONSTRAINT}
        return maps

    def add(self, item, *args, **kwargs):
        match item:
            case widgets.QWidget():
                self._container.addWidget(item, *args, **kwargs)
            case widgets.QLayout():
                self._container.addLayout(item, *args, **kwargs)
            case widgets.QLayoutItem():
                self._container.addItem(item, *args, **kwargs)
            case list():
                for i in item:
                    self._container.add(i, *args, **kwargs)
        return item

    def __enter__(self):
        def enter(item):
            if item._next_container is not None:
                enter(item._next_container)
                item._stack.append(item._next_container)
                item._next_container = None
            return item

        return enter(self)

    def __exit__(self, *_):
        def exit(item):
            if item._stack:
                item = item._stack.pop()
                exit(item)

        exit(self)

    @property
    def _container(self):
        return self._stack[-1] if self._stack else self

    def get_sub_layout(
        self,
        layout: str,
        orientation: constants.OrientationStr | None = None,
        stretch: int | None = None,
        **kwargs,
    ) -> Self:
        from prettyqt import custom_widgets

        CONTEXT_LAYOUTS = dict(
            horizontal=widgets.HBoxLayout,
            vertical=widgets.VBoxLayout,
            grid=widgets.GridLayout,
            form=widgets.FormLayout,
            stacked=widgets.StackedLayout,
            flow=custom_widgets.FlowLayout,
            splitter=widgets.Splitter,
            scroll=widgets.ScrollArea,
            frame=widgets.GroupBox,
        )
        Klass = CONTEXT_LAYOUTS[layout]
        match self._container:
            case widgets.QWidget() if layout == "scroll":
                scroller = Klass(parent=self._container)
                scroller.setWidgetResizable(True)
                widget = widgets.Widget()
                scroller.set_widget(widget)
                new = widget.set_layout(orientation, **kwargs)
            case widgets.QLayout() if layout == "scroll":
                scroller = Klass(parent=self._container)
                scroller.setWidgetResizable(True)
                widget = widgets.Widget()
                scroller.set_widget(widget)
                new = widget.set_layout(orientation, **kwargs)
                self._container.add(new)
            case widgets.QWidget() if layout == "splitter":
                new = Klass(orientation=orientation, parent=self._container, **kwargs)
            case widgets.QLayout() if layout == "splitter":
                new = Klass(orientation=orientation, **kwargs)
                self._container.add(new)
            case widgets.QWidget() if layout == "frame":
                frame = Klass(parent=self._container, **kwargs)
                widget = widgets.Widget()
                new = widget.set_layout(orientation or "horizontal")
                frame.set_layout(new)
            case widgets.QLayout() if layout == "frame":
                frame = Klass(**kwargs)
                widget = widgets.Widget()
                new = widget.set_layout(orientation or "horizontal")
                frame.set_layout(new)
                self._container.add(new)
            case widgets.QMainWindow():
                widget = widgets.Widget(parent=self._container)
                self._container.setCentralWidget(widget)
                new = Klass(widget, **kwargs)
            case widgets.QScrollArea():
                widget = widgets.Widget(parent=self._container)
                self._container.setWidget(widget)
                self._container.setWidgetResizable(True)
                new = widget.set_layout("vertical", **kwargs)
            case widgets.QSplitter():
                widget = widgets.Widget(parent=self._container)
                self._container.addWidget(widget)
                new = Klass(widget, **kwargs)
            case None | widgets.QWidget():
                new = Klass(self._container, **kwargs)
            case widgets.QLayout():
                new = Klass(**kwargs)
                if stretch:
                    self._container.add(new, stretch)
                else:
                    self._container.add(new)
        new._stack = []
        new._next_container = None
        self._next_container = new
        return self

    def item_at(self, pos_or_index: int | core.Point) -> widgets.QLayoutItem:
        match pos_or_index:
            case int():
                return super().itemAt(pos_or_index)
            case core.QPoint():
                for i in range(self.count()):
                    item = self.itemAt(i)
                    if item.geometry().contains(pos_or_index):
                        return item
            case _:
                raise ValueError(pos_or_index)

    def clear(self):
        for i in reversed(range(self.count())):
            self.takeAt(i)

    # def takeAt(self, index: int):
    #     if index < 0:
    #         index = self.count() + index
    #     return super().takeAt(index)

    def get_items(self):
        return [self.itemAt(i) for i in range(self.count())]

    def get_children(
        self,
    ) -> listdelegators.ListDelegator[widgets.QWidget | widgets.QLayout]:
        return listdelegators.ListDelegator(self)

    def set_margin(self, margin: datatypes.MarginsType | None):
        match margin:
            case None:
                self.unsetContentsMargins()
            case _:
                margin = datatypes.to_margins(margin)
                self.setContentsMargins(margin)

    def set_spacing(self, pixels: int):
        self.setSpacing(pixels)

    def set_size_constraint(
        self, mode: SizeConstraintStr | widgets.QLayout.SizeConstraint
    ):
        """Set the size mode of the layout.

        Args:
            mode: size mode for the layout
        """
        self.setSizeConstraint(SIZE_CONSTRAINT.get_enum_value(mode))

    def get_size_constraint(self) -> SizeConstraintStr:
        """Return current size mode.

        Returns:
            size mode
        """
        return SIZE_CONSTRAINT.inverse[self.sizeConstraint()]

    def set_alignment(
        self,
        alignment: constants.AlignmentStr | constants.AlignmentFlag,
        item: widgets.QWidget | widgets.QLayout | None = None,
    ) -> bool:
        """Set the alignment for widget / layout to alignment.

        Returns true if w is found in this layout (not including child layouts).

        Args:
            alignment: alignment for the layout
            item: set alignment for specific child only
        """
        if item is not None:
            return self.setAlignment(item, constants.ALIGNMENTS.get_enum_value(alignment))
        else:
            return self.setAlignment(constants.ALIGNMENTS.get_enum_value(alignment))

get_size_constraint() -> SizeConstraintStr

Return current size mode.

Source code in prettyqt\widgets\layout.py
def get_size_constraint(self) -> SizeConstraintStr:
    """Return current size mode.

    Returns:
        size mode
    """
    return SIZE_CONSTRAINT.inverse[self.sizeConstraint()]

set_alignment(alignment: constants.AlignmentStr | constants.AlignmentFlag, item: widgets.QWidget | widgets.QLayout | None = None) -> bool

Set the alignment for widget / layout to alignment.

Returns true if w is found in this layout (not including child layouts).

Parameters:

Name Type Description Default
alignment AlignmentStr | AlignmentFlag

alignment for the layout

required
item QWidget | QLayout | None

set alignment for specific child only

None
Source code in prettyqt\widgets\layout.py
def set_alignment(
    self,
    alignment: constants.AlignmentStr | constants.AlignmentFlag,
    item: widgets.QWidget | widgets.QLayout | None = None,
) -> bool:
    """Set the alignment for widget / layout to alignment.

    Returns true if w is found in this layout (not including child layouts).

    Args:
        alignment: alignment for the layout
        item: set alignment for specific child only
    """
    if item is not None:
        return self.setAlignment(item, constants.ALIGNMENTS.get_enum_value(alignment))
    else:
        return self.setAlignment(constants.ALIGNMENTS.get_enum_value(alignment))

set_size_constraint(mode: SizeConstraintStr | widgets.QLayout.SizeConstraint)

Set the size mode of the layout.

Parameters:

Name Type Description Default
mode SizeConstraintStr | SizeConstraint

size mode for the layout

required
Source code in prettyqt\widgets\layout.py
def set_size_constraint(
    self, mode: SizeConstraintStr | widgets.QLayout.SizeConstraint
):
    """Set the size mode of the layout.

    Args:
        mode: size mode for the layout
    """
    self.setSizeConstraint(SIZE_CONSTRAINT.get_enum_value(mode))