diff --git a/src/bedit_gui/commands/rename_component_command.py b/src/bedit_gui/commands/rename_component_command.py new file mode 100644 index 0000000..9d27ce8 --- /dev/null +++ b/src/bedit_gui/commands/rename_component_command.py @@ -0,0 +1,19 @@ +from PySide6.QtGui import QUndoCommand +from bedit_core.models import Component + +class RenameComponentCommand(QUndoCommand): + def __init__(self, document, component: Component, new_name: str) -> None: + super().__init__("Rename component") + + self.document = document + self.component = component + self.old_name = component.name + self.new_name = new_name + + def redo(self) -> None: + self.component.name = self.new_name + self.document.model_changed.emit(self.document.model) + + def undo(self) -> None: + self.component.name = self.old_name + self.document.model_changed.emit(self.document.model) \ No newline at end of file diff --git a/src/bedit_gui/commands/rename_document_command.py b/src/bedit_gui/commands/rename_document_command.py new file mode 100644 index 0000000..a99b158 --- /dev/null +++ b/src/bedit_gui/commands/rename_document_command.py @@ -0,0 +1,18 @@ +from PySide6.QtGui import QUndoCommand + + +class RenameDocumentCommand(QUndoCommand): + def __init__(self, document, new_name: str) -> None: + super().__init__("Rename document") + + self.document = document + self.old_name = document.model.name + self.new_name = new_name + + def redo(self) -> None: + self.document.model.name = self.new_name + self.document.model_changed.emit(self.document.model) + + def undo(self) -> None: + self.document.model.name = self.old_name + self.document.model_changed.emit(self.document.model) \ No newline at end of file diff --git a/src/bedit_gui/controllers/document_tree_controller.py b/src/bedit_gui/controllers/document_tree_controller.py index 4b6d82b..157b2f7 100644 --- a/src/bedit_gui/controllers/document_tree_controller.py +++ b/src/bedit_gui/controllers/document_tree_controller.py @@ -7,11 +7,7 @@ from bedit_gui.views.models.document_tree_model import DocumentTreeModel class DocumentTreeController(QObject): - def __init__( - self, - document: Document, - window: MainWindow, - ) -> None: + def __init__(self,document: Document,window: MainWindow) -> None: super().__init__(window) self.document = document @@ -20,6 +16,8 @@ class DocumentTreeController(QObject): window.ui.documentTree.setModel(self.model) document.model_changed.connect(self._on_document_changed) + self.model.rename_document_requested.connect(self.document.rename) + self.model.rename_component_requested.connect(self.document.rename_component) window.ui.documentTree.setHeaderHidden(True) diff --git a/src/bedit_gui/documents/document.py b/src/bedit_gui/documents/document.py index 4376bf0..f1060be 100644 --- a/src/bedit_gui/documents/document.py +++ b/src/bedit_gui/documents/document.py @@ -6,8 +6,10 @@ from PySide6.QtCore import QObject, Signal from PySide6.QtGui import QUndoStack from bedit_core.models import ID -from bedit_core.models import Document as CoreDocument +from bedit_core.models import Document as CoreDocument, Component from bedit_gui.services import document_files +from bedit_gui.commands.rename_document_command import RenameDocumentCommand +from bedit_gui.commands.rename_component_command import RenameComponentCommand class Document(QObject): @@ -78,3 +80,9 @@ class Document(QObject): name="Untitled", root={}, ) + + def rename(self, name: str) -> None: + self.undo_stack.push(RenameDocumentCommand(self, name)) + + def rename_component(self, component: Component, name:str) -> None: + self.undo_stack.push(RenameComponentCommand(self, component, name)) diff --git a/src/bedit_gui/views/models/document_tree_model.py b/src/bedit_gui/views/models/document_tree_model.py index 876535c..d9b75cd 100644 --- a/src/bedit_gui/views/models/document_tree_model.py +++ b/src/bedit_gui/views/models/document_tree_model.py @@ -2,7 +2,7 @@ from __future__ import annotations from dataclasses import dataclass -from PySide6.QtCore import QAbstractItemModel, QModelIndex, Qt +from PySide6.QtCore import QAbstractItemModel, QModelIndex, Qt, Signal from bedit_core.models import Document as CoreDocument, ComponentID, Component, GraphImplementation @@ -16,6 +16,9 @@ class DocumentTreeNode: class DocumentTreeModel(QAbstractItemModel): + rename_document_requested = Signal(str) + rename_component_requested = Signal(Component, str) + def __init__(self) -> None: super().__init__() self._document: CoreDocument | None = None @@ -33,18 +36,9 @@ class DocumentTreeModel(QAbstractItemModel): def columnCount(self, _parent: QModelIndex | None = None) -> int: return 1 - def index( - self, - row: int, - column: int, - parent: QModelIndex | None = None, - ) -> QModelIndex: + def index(self,row: int,column: int,parent: QModelIndex | None = None) -> QModelIndex: parent_node = self._node(parent) - if ( - column != 0 - or row < 0 - or row >= len(parent_node.children) - ): + if column != 0 or row < 0 or row >= len(parent_node.children): return QModelIndex() return self.createIndex(row, column, parent_node.children[row]) @@ -66,22 +60,38 @@ class DocumentTreeModel(QAbstractItemModel): row = grandparent.children.index(parent_node) return self.createIndex(row, 0, parent_node) - def data( - self, - index: QModelIndex, - role: int = Qt.ItemDataRole.DisplayRole, - ) -> object | None: + def data(self,index: QModelIndex,role: int = Qt.ItemDataRole.DisplayRole) -> object | None: if not index.isValid(): return None node = index.internalPointer() - if ( - role == Qt.ItemDataRole.DisplayRole - and isinstance(node, DocumentTreeNode) - ): + if not isinstance(node, DocumentTreeNode): + return None + + if role in (Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.EditRole): return node.name + return None + def setData(self,index: QModelIndex,value: object,role: int = Qt.ItemDataRole.EditRole) -> bool: + if role != Qt.ItemDataRole.EditRole or not index.isValid(): + return False + + node = index.internalPointer() + if not isinstance(node, DocumentTreeNode) or not isinstance(node.value, (CoreDocument, Component)): + return False + + name = str(value).strip() + + if not name or name == node.name: + return False + + if isinstance(node.value, CoreDocument): + self.rename_document_requested.emit(name) + elif isinstance(node.value, Component): + self.rename_component_requested.emit(node.value, name) + return True + def _node(self, index: QModelIndex | None) -> DocumentTreeNode: if index is None or not index.isValid(): return self._root @@ -89,6 +99,21 @@ class DocumentTreeModel(QAbstractItemModel): node = index.internalPointer() return node if isinstance(node, DocumentTreeNode) else self._root + def flags(self, index: QModelIndex) -> Qt.ItemFlag: + flags = super().flags(index) + + if not index.isValid(): + return flags + + node = index.internalPointer() + + # Make the document root node editable + if (isinstance(node, DocumentTreeNode) + and (isinstance(node.value, CoreDocument) or isinstance(node.value, Component))): + flags |= Qt.ItemFlag.ItemIsEditable + + return flags + def _build_tree(self, document: CoreDocument) -> DocumentTreeNode: # QT's invisible root root = DocumentTreeNode( @@ -110,7 +135,7 @@ class DocumentTreeModel(QAbstractItemModel): for component_id, component in components.items(): component_node = DocumentTreeNode( name = component.name, - value = (component_id, component), + value = component, parent = root, children = [] ) diff --git a/untitled.bedit.json b/untitled.bedit.json index 87baf04..5f313f1 100644 --- a/untitled.bedit.json +++ b/untitled.bedit.json @@ -2,10 +2,10 @@ "file_format_version": 1, "format_version": 1, "id": "3b6780c7-488b-471e-a784-392db7632090", - "name": "Current Document", + "name": "main_node", "root": { "50e6ef97-f686-4400-bc01-e5a352e8cc22": { - "name": "test", + "name": "some_bondgraph", "interface": { "ports": {} },