Simple text editor for basic notes

This commit is contained in:
Andrew Mulbrook 2026-03-23 22:56:53 -05:00
parent bd4d571c95
commit 160de4c526
5 changed files with 96 additions and 15 deletions

View file

@ -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())
@ -71,4 +74,4 @@ class TroveMainWindow(QMainWindow):
if geometry:
self.restoreGeometry(geometry)
if state:
self.restoreState(state)
self.restoreState(state)

View file

@ -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)

View 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
View 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

View 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))