Reorganized the application around a clear frontend/backend boundary.
src/bedit/
├── __main__.py
├── core/ # Pure Python, no PySide
│ ├── model.py
│ ├── port_types.py
│ ├── serializer.py
│ └── libraries.py
└── gui/ # All Qt-dependent code
├── app.py
├── main_window.py
├── preferences.py
├── controllers/
├── dialogs/
├── graphics/
├── models/
└── generated/ # Designer/resource output only
Notable improvements:
Domain models, serialization, port types, and library parsing are now Qt-free.
Qt signals and undo infrastructure are explicitly isolated under gui/controllers.
Library parsing is separated from the Qt repository and tree models.
All generated Python is contained in gui/generated.
Designer build tasks now write to the generated directory.
The application entry point and package metadata use the new paths.
README now documents the structure and dependency rules.
Removed the old mixed document, library, and workspace packages.
This commit is contained in:
95
BEdit/src/bedit/gui/models/library_tree.py
Normal file
95
BEdit/src/bedit/gui/models/library_tree.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import json
|
||||
|
||||
from PySide6.QtCore import QByteArray, QMimeData, QModelIndex, Qt, Signal
|
||||
from PySide6.QtGui import QStandardItem, QStandardItemModel
|
||||
|
||||
from bedit.core.model import Component
|
||||
from bedit.gui.controllers.document import DocumentController
|
||||
from bedit.gui.graphics.icon_renderer import library_icon
|
||||
from bedit.gui.models.library_repository import LibraryRepository
|
||||
|
||||
|
||||
COMPONENT_ROLE = Qt.ItemDataRole.UserRole + 1
|
||||
COMPONENT_ID_ROLE = Qt.ItemDataRole.UserRole + 2
|
||||
ITEM_KIND_ROLE = Qt.ItemDataRole.UserRole + 3
|
||||
COMPONENT_INSTANCE_ROLE = Qt.ItemDataRole.UserRole + 4
|
||||
COMPONENT_MIME_TYPE = "application/x-bedit-component"
|
||||
|
||||
|
||||
class LibraryTreeModel(QStandardItemModel):
|
||||
rebuilt = Signal()
|
||||
def __init__(
|
||||
self,
|
||||
repository: LibraryRepository,
|
||||
controller: DocumentController,
|
||||
parent=None,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
self.repository = repository
|
||||
self.controller = controller
|
||||
repository.librariesChanged.connect(self.rebuild)
|
||||
self.rebuild()
|
||||
|
||||
def rebuild(self) -> None:
|
||||
self.clear()
|
||||
self.setHorizontalHeaderLabels(["Libraries"])
|
||||
for library in self.repository.libraries:
|
||||
root = QStandardItem(library.name)
|
||||
root.setDragEnabled(False)
|
||||
root.setToolTip(library.source_path)
|
||||
for component in library.document.roots.values():
|
||||
root.appendRow(self._component_item(component))
|
||||
self.appendRow(root)
|
||||
self.rebuilt.emit()
|
||||
|
||||
def _component_item(self, component: Component, current: bool = False) -> QStandardItem:
|
||||
item = QStandardItem(component.name)
|
||||
item.setEditable(False)
|
||||
item.setIcon(library_icon(component.icon))
|
||||
item.setData(component.to_dict(), COMPONENT_ROLE)
|
||||
item.setData(component.id, COMPONENT_ID_ROLE)
|
||||
item.setData("current-component" if current else "library-component", ITEM_KIND_ROLE)
|
||||
item.setData(component, COMPONENT_INSTANCE_ROLE)
|
||||
if component.show_subtree_in_library:
|
||||
for child in component.graph.blocks.values():
|
||||
item.appendRow(self._component_item(child, current=current))
|
||||
return item
|
||||
|
||||
def mimeTypes(self) -> list[str]: # noqa: N802
|
||||
return [COMPONENT_MIME_TYPE]
|
||||
|
||||
def mimeData(self, indexes: list[QModelIndex]) -> QMimeData: # noqa: N802
|
||||
mime_data = QMimeData()
|
||||
for index in indexes:
|
||||
component = index.data(COMPONENT_ROLE)
|
||||
if component:
|
||||
encoded = json.dumps(component).encode("utf-8")
|
||||
mime_data.setData(COMPONENT_MIME_TYPE, QByteArray(encoded))
|
||||
break
|
||||
return mime_data
|
||||
|
||||
def supportedDragActions(self): # noqa: N802
|
||||
return Qt.DropAction.CopyAction
|
||||
|
||||
|
||||
class DocumentTreeModel(LibraryTreeModel):
|
||||
def __init__(self, controller: DocumentController, parent=None) -> None:
|
||||
QStandardItemModel.__init__(self, parent)
|
||||
self.controller = controller
|
||||
controller.documentReset.connect(self.rebuild)
|
||||
controller.componentMoved.connect(lambda _component_id, _position: self.rebuild())
|
||||
controller.connectionAdded.connect(lambda _connection_id: self.rebuild())
|
||||
controller.connectionRemoved.connect(lambda _connection_id: self.rebuild())
|
||||
self.rebuild()
|
||||
|
||||
def rebuild(self) -> None:
|
||||
self.clear()
|
||||
self.setHorizontalHeaderLabels(["Document"])
|
||||
if self.controller.document is not None:
|
||||
current_root = QStandardItem("Current Document")
|
||||
current_root.setDragEnabled(False)
|
||||
current_root.setData("current-document", ITEM_KIND_ROLE)
|
||||
for component in self.controller.document.roots.values():
|
||||
current_root.appendRow(self._component_item(component, current=True))
|
||||
self.appendRow(current_root)
|
||||
self.rebuilt.emit()
|
||||
Reference in New Issue
Block a user