Simple text editor for basic notes
This commit is contained in:
parent
bd4d571c95
commit
160de4c526
5 changed files with 96 additions and 15 deletions
|
|
@ -1,7 +1,6 @@
|
|||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtGui import QAction, QKeySequence
|
||||
from PySide6.QtWidgets import (
|
||||
QLabel,
|
||||
QMainWindow,
|
||||
QSplitter,
|
||||
QStatusBar,
|
||||
|
|
@ -13,7 +12,9 @@ from PySide6.QtWidgets import (
|
|||
from .settings import get_settings
|
||||
|
||||
from trovedb import trove as tr
|
||||
|
||||
from .note_browser import NoteBrowser
|
||||
from .note_tool_stack import NoteToolStack
|
||||
|
||||
class TroveMainWindow(QMainWindow):
|
||||
def __init__(self, trove: tr.Trove):
|
||||
|
|
@ -44,15 +45,17 @@ class TroveMainWindow(QMainWindow):
|
|||
layout.setSpacing(0)
|
||||
|
||||
# Horizontal splitter: tree | editor
|
||||
splitter = QSplitter(Qt.Orientation.Horizontal)
|
||||
self._splitter = QSplitter(Qt.Orientation.Horizontal)
|
||||
|
||||
self._note_browser = NoteBrowser(trove)
|
||||
splitter.addWidget(self._note_browser)
|
||||
self._splitter.addWidget(self._note_browser)
|
||||
|
||||
self._tool = QLabel("View/Edit Tool")
|
||||
splitter.addWidget(self._tool)
|
||||
self._tool_stack = NoteToolStack()
|
||||
self._splitter.addWidget(self._tool_stack)
|
||||
|
||||
layout.addWidget(splitter, stretch=1)
|
||||
layout.addWidget(self._splitter, stretch=1)
|
||||
|
||||
self._note_browser.activeNoteChanged.connect(self._tool_stack.onNoteSelected)
|
||||
|
||||
# ── Status bar ──
|
||||
self.setStatusBar(QStatusBar())
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ class NoteBrowser(QWidget):
|
|||
tree_selected(TreeNote) -- emitted when a tree note is activated
|
||||
"""
|
||||
|
||||
note_selected = Signal(object) # Note
|
||||
tree_selected = Signal(object) # TreeNote
|
||||
activeNoteChanged = Signal(object) # Note
|
||||
|
||||
def __init__(self, trove: Trove, parent: Optional[QWidget] = None):
|
||||
super().__init__(parent)
|
||||
|
|
@ -38,6 +37,8 @@ class NoteBrowser(QWidget):
|
|||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(2)
|
||||
|
||||
self._activeNote: Optional[Note] = None
|
||||
|
||||
self._tree = QTreeView()
|
||||
self._tree.setModel(self._model)
|
||||
self._tree.setHeaderHidden(True)
|
||||
|
|
@ -67,12 +68,7 @@ class NoteBrowser(QWidget):
|
|||
|
||||
def _on_activated(self, index: QModelIndex) -> None:
|
||||
note = index.data(Qt.ItemDataRole.UserRole)
|
||||
if note is None:
|
||||
return
|
||||
if isinstance(note, TreeNote):
|
||||
self.tree_selected.emit(note)
|
||||
else:
|
||||
self.note_selected.emit(note)
|
||||
self._handle_set_active_note(note)
|
||||
|
||||
def _on_context_menu(self, pos) -> None:
|
||||
index = self._tree.indexAt(pos)
|
||||
|
|
@ -105,6 +101,14 @@ class NoteBrowser(QWidget):
|
|||
# Public API
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _handle_set_active_note(self, note: Note | None) -> None:
|
||||
"""Called by the controller to update the active note."""
|
||||
if not isinstance(note, Note):
|
||||
note = None
|
||||
if self._activeNote != note:
|
||||
self._activeNote = note
|
||||
self.activeNoteChanged.emit(note)
|
||||
|
||||
def select_note(self, note: Note) -> None:
|
||||
"""Programmatically select the node matching the given note object."""
|
||||
match = self._find_index(self._model.index(0, 0, QModelIndex()), note)
|
||||
|
|
|
|||
32
trovedb/qgui/note_tool_stack.py
Normal file
32
trovedb/qgui/note_tool_stack.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
from typing import Generator
|
||||
|
||||
from PySide6.QtCore import Property, Slot
|
||||
from PySide6.QtWidgets import QStackedWidget, QWidget, QLabel
|
||||
|
||||
import trovedb.trove as tr
|
||||
|
||||
from .tool import Tool
|
||||
from .tool_basic_editor import ToolBasicEditor
|
||||
|
||||
|
||||
class NoteToolStack(QStackedWidget):
|
||||
def __init__(self, parent: QWidget | None = None):
|
||||
super().__init__(parent)
|
||||
self.setContentsMargins(0, 0, 0, 0)
|
||||
self.addWidget(QLabel("No note selected"))
|
||||
|
||||
@Slot(object)
|
||||
def onNoteSelected(self, note: tr.Note):
|
||||
for tool in self._iter_tools():
|
||||
if tool.note == note:
|
||||
self.setCurrentWidget(tool)
|
||||
return
|
||||
tool = ToolBasicEditor(note)
|
||||
self.addWidget(tool)
|
||||
self.setCurrentWidget(tool)
|
||||
|
||||
def _iter_tools(self) -> Generator[Tool, None, None]:
|
||||
for i in range(self.count()):
|
||||
widget = self.widget(i)
|
||||
if isinstance(widget, Tool):
|
||||
yield widget
|
||||
14
trovedb/qgui/tool.py
Normal file
14
trovedb/qgui/tool.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
"""Tool Base Class"""
|
||||
|
||||
from PySide6.QtWidgets import QWidget
|
||||
|
||||
import trovedb.trove as tr
|
||||
|
||||
class Tool(QWidget):
|
||||
def __init__(self, note: tr.Note, parent=None):
|
||||
super().__init__(parent)
|
||||
self._note = note
|
||||
|
||||
@property
|
||||
def note(self) -> tr.Note:
|
||||
return self._note
|
||||
28
trovedb/qgui/tool_basic_editor.py
Normal file
28
trovedb/qgui/tool_basic_editor.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
"""Tool Supporting Basic Editor Functions"""
|
||||
from typing import cast, Protocol
|
||||
from PySide6.QtWidgets import QTextEdit, QVBoxLayout
|
||||
|
||||
import trovedb.trove as tr
|
||||
from .tool import Tool
|
||||
|
||||
|
||||
class ToolBasicEditor(Tool):
|
||||
def __init__(self, note, parent=None):
|
||||
super().__init__(note, parent)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(0)
|
||||
|
||||
self._text_edit = QTextEdit()
|
||||
layout.addWidget(self._text_edit)
|
||||
self.refresh()
|
||||
|
||||
def _refresh_blob(self, note: tr.Blob):
|
||||
self._text_edit.setPlainText(note.read().decode("utf-8"))
|
||||
|
||||
def refresh(self):
|
||||
if isinstance(self.note, tr.Blob):
|
||||
self._refresh_blob(cast(tr.Blob, self.note))
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue