Skip to content

ListMixin

Subclasses

Class Module Description
NestedModel prettyqt.itemmodels.nestedmodel
FrameInfoModel prettyqt.itemmodels.frameinfomodel
MappingModel prettyqt.itemmodels.mappingmodel
ModelIndexModel prettyqt.itemmodels.modelindexmodel

⋔ Inheritance diagram

graph TD
  1473299910672["itemmodels.ListMixin"]
  140713234304496["builtins.object"]
  140713234304496 --> 1473299910672

🛈 DocStrings

Source code in prettyqt\itemmodels\listmixin.py
class ListMixin:
    SORT_METHODS: dict[int, Callable]
    MIME_TYPE: str = ""

    def __init__(self, *args, items=None, **kwargs):
        super().__init__(*args, **kwargs)  # type: ignore
        self.items = items or []

    def setData(
        self,
        index: core.ModelIndex,
        value: Any,
        role: constants.ItemDataRole = constants.EDIT_ROLE,
    ) -> bool:
        if role == constants.USER_ROLE:
            self.items[index.row()] = value
            self.update_row(index.row())
            return True
        return super().setData(index, value, role)  # type: ignore

    def removeRows(self, row: int, count: int, parent):
        # called by default implementation of QAbstractItemModel::startDrag
        end_row = row + count - 1
        with self.remove_rows(row, end_row, parent):
            for i in range(end_row, row - 1, -1):
                self.items.pop(i)
        return True

    # def insertRows(self, row: int, count: int, parent):
    #     # called by default implementation of QAbstractItemModel::dropMimeData
    #     end_row = row + count - 1
    #     with self.insert_rows(row, end_row, parent):
    #         for i in range(end_row, row - 1, -1):
    #             self.items.insert(i,)
    #     return True

    def rowCount(self, parent: core.ModelIndex | None = None) -> int:
        """Required override for AbstractitemModels."""
        parent = parent or core.ModelIndex()
        return 0 if parent.column() > 0 or parent.isValid() else len(self.items)

    def data_by_index(self, index):
        return self.items[index.row()]

    def dropMimeData(self, mime_data, action, row, column, parent_index):
        if not mime_data.hasFormat(self.MIME_TYPE):
            return False
        # Since we only drop in between items, parent_index must be invalid,
        # and we use the row arg to know where the drop took place.
        if parent_index.isValid():
            return False
        indexes = mime_data.get_json_data(self.MIME_TYPE)
        pos = row if row < len(self.items) and row != -1 else len(self.items)
        rem_offset = sum(i <= pos for i in indexes)
        new = [self.items[i] for i in indexes]
        with self.change_layout():
            for i in sorted(indexes, reverse=True):
                self.items.pop(i)
            for item in reversed(new):
                self.items.insert(pos - rem_offset, item)
        return False

    def sort(self, ncol: int, order):
        """Sort table by given column number."""
        is_asc = order == constants.ASCENDING
        if sorter := self.SORT_METHODS.get(ncol):
            with self.change_layout():
                self.items.sort(key=sorter, reverse=is_asc)

    def add(self, item: Any, position: int | None = None):
        """Append provided item to the list."""
        self.add_items(items=[item], position=position)
        return item

    def add_items(self, items: Iterable[Any], position: int | None = None):
        """Append a list of items to the list."""
        if position is None:
            position = len(self.items)
        items = list(items)
        with self.insert_rows(position, position + len(items) - 1):
            for i in range(len(items)):
                self.items.insert(i + position, items[i])
            # self.items.extend(items)
        return items

    def remove_items(self, offsets: Iterable[int]):
        for offset in sorted(offsets, reverse=True):
            self.removeRow(offset)

    def supportedDropActions(self):
        return constants.MOVE_ACTION

    def mimeTypes(self):
        return [self.MIME_TYPE]

    def mimeData(self, indexes):
        """AbstractItemModel override, defines the data used for drag and drop.

        atm this just returns the positions (not sure if this is perfect)
        """
        mime_data = core.MimeData()
        data = [i.row() for i in indexes if i.column() == 0]
        mime_data.set_json_data(self.MIME_TYPE, data)
        return mime_data

    # list interface

    def pop(self, row=None):
        if row is None:
            row = len(self.items) - 1
        result = self.items[row]
        self.removeRow(row)
        return result

    def __getitem__(self, row):
        return self.items[row]

    def __setitem__(self, row: int | slice, value):
        match row:
            case slice():
                rng = range(row.start or 0, row.stop or len(self.items), row.step or 1)
                for count, i in enumerate(rng):
                    if i < self.rowCount():
                        index = self.index(i)
                        self.setData(i, value[count], role=constants.USER_ROLE)
                    else:
                        self.items.append(value[count])
            case int():
                index = self.index(row)
                self.setData(index, value, role=constants.USER_ROLE)
            case _:
                raise ValueError(row)

    def __len__(self):
        return len(self.items)

    def insert(self, row: int, value):
        with self.insert_row(row):
            self.items.insert(row, value)

    def append(self, value):
        row = len(self.items)
        self.insert(row, value)

    def extend(self, values):
        pos = len(self.items)
        with self.insert_rows(pos, pos + len(values)):
            self.items.extend(values)

    def set_list(self, values):
        """Set the model to a new list."""
        with self.reset_model():
            self.items = values

    def remove(self, item):
        if item in self.items:
            pos = self.items.index(item)
            with self.remove_row(pos):
                self.items.remove(item)

add(item: Any, position: int | None = None)

Append provided item to the list.

Source code in prettyqt\itemmodels\listmixin.py
def add(self, item: Any, position: int | None = None):
    """Append provided item to the list."""
    self.add_items(items=[item], position=position)
    return item

add_items(items: Iterable[Any], position: int | None = None)

Append a list of items to the list.

Source code in prettyqt\itemmodels\listmixin.py
def add_items(self, items: Iterable[Any], position: int | None = None):
    """Append a list of items to the list."""
    if position is None:
        position = len(self.items)
    items = list(items)
    with self.insert_rows(position, position + len(items) - 1):
        for i in range(len(items)):
            self.items.insert(i + position, items[i])
        # self.items.extend(items)
    return items

mimeData(indexes)

AbstractItemModel override, defines the data used for drag and drop.

atm this just returns the positions (not sure if this is perfect)

Source code in prettyqt\itemmodels\listmixin.py
def mimeData(self, indexes):
    """AbstractItemModel override, defines the data used for drag and drop.

    atm this just returns the positions (not sure if this is perfect)
    """
    mime_data = core.MimeData()
    data = [i.row() for i in indexes if i.column() == 0]
    mime_data.set_json_data(self.MIME_TYPE, data)
    return mime_data

rowCount(parent: core.ModelIndex | None = None) -> int

Required override for AbstractitemModels.

Source code in prettyqt\itemmodels\listmixin.py
def rowCount(self, parent: core.ModelIndex | None = None) -> int:
    """Required override for AbstractitemModels."""
    parent = parent or core.ModelIndex()
    return 0 if parent.column() > 0 or parent.isValid() else len(self.items)

set_list(values)

Set the model to a new list.

Source code in prettyqt\itemmodels\listmixin.py
def set_list(self, values):
    """Set the model to a new list."""
    with self.reset_model():
        self.items = values

sort(ncol: int, order: int)

Sort table by given column number.

Source code in prettyqt\itemmodels\listmixin.py
def sort(self, ncol: int, order):
    """Sort table by given column number."""
    is_asc = order == constants.ASCENDING
    if sorter := self.SORT_METHODS.get(ncol):
        with self.change_layout():
            self.items.sort(key=sorter, reverse=is_asc)