from __future__ import annotations import json from collections.abc import Callable from PySide6.QtCore import QMimeData, QModelIndex, Qt from bedit_core.models import Component from bedit_gui.services.component_clipboard import COMPONENTS_MIME from bedit_gui.views.models.document_tree_model import DocumentTreeModel PayloadFactory = Callable[[list[Component]], dict] class LibraryTreeModel(DocumentTreeModel): def __init__(self, payload_factory: PayloadFactory) -> None: super().__init__(editable=False) self._payload_factory = payload_factory def flags(self, index: QModelIndex) -> Qt.ItemFlag: flags = super().flags(index) if isinstance(self.value(index), Component): flags |= Qt.ItemFlag.ItemIsDragEnabled return flags def mimeTypes(self) -> list[str]: return [COMPONENTS_MIME] def mimeData(self, indexes: list[QModelIndex]) -> QMimeData: rows = [index for index in indexes if index.column() == 0 and isinstance(self.value(index), Component)] selected = {id(self.value(index)) for index in rows} components = [] added = set() for index in rows: parent = index.parent() if any(id(self.value(parent_index)) in selected for parent_index in self._parents(parent)): continue component = self.value(index) if isinstance(component, Component) and id(component) not in added: components.append(component) added.add(id(component)) mime = QMimeData() if components: mime.setData(COMPONENTS_MIME, json.dumps(self._payload_factory(components)).encode("utf-8")) mime.setText("\n".join(component.name for component in components)) return mime def supportedDragActions(self) -> Qt.DropAction: return Qt.DropAction.CopyAction @staticmethod def _parents(index: QModelIndex): while index.isValid(): yield index index = index.parent()