DRY up some code

This commit is contained in:
Miguel Jacq 2025-11-10 10:25:46 +11:00
parent 77eec9cc84
commit eac37d8843
Signed by: mig5
GPG key ID: 59B3F0C24135C6A9
5 changed files with 52 additions and 88 deletions

View file

@ -1,3 +1,8 @@
# 0.2.1.4
* Increase font size of normal text
* DRY up some code
# 0.2.1.3
* Ensure checkbox only can get checked on/off if it is clicked right on its block position, not any click on the whole line

View file

@ -109,14 +109,6 @@ class HistoryDialog(QDialog):
self._load_versions()
# --- Data/UX helpers ---
def _fmt_local(self, iso_utc: str) -> str:
"""
Convert UTC in the database to user's local tz
"""
dt = datetime.fromisoformat(iso_utc.replace("Z", "+00:00"))
local = dt.astimezone()
return local.strftime("%Y-%m-%d %H:%M:%S %Z")
def _load_versions(self):
# [{id,version_no,created_at,note,is_current}]
self._versions = self._db.list_versions(self._date)
@ -126,7 +118,11 @@ class HistoryDialog(QDialog):
)
self.list.clear()
for v in self._versions:
label = f"v{v['version_no']}{self._fmt_local(v['created_at'])}"
created_at = datetime.fromisoformat(
v["created_at"].replace("Z", "+00:00")
).astimezone()
created_at_local = created_at.strftime("%Y-%m-%d %H:%M:%S %Z")
label = f"v{v['version_no']}{created_at_local}"
if v.get("note"):
label += f" · {v['note']}"
if v["is_current"]:

View file

@ -169,9 +169,7 @@ class MainWindow(QMainWindow):
self.statusBar().showMessage("Ready", 800)
# Add findBar and add it to the statusBar
# FindBar will get the current editor dynamically via a callable
self.findBar = FindBar(
lambda: self.current_editor(), shortcut_parent=self, parent=self
)
self.findBar = FindBar(lambda: self.editor, shortcut_parent=self, parent=self)
self.statusBar().addPermanentWidget(self.findBar)
# When the findBar closes, put the caret back in the editor
self.findBar.closed.connect(self._focus_editor_now)
@ -431,7 +429,7 @@ class MainWindow(QMainWindow):
self.tab_widget.setCurrentIndex(index)
# Load the date's content
self._load_date_into_editor(date, editor)
self._load_date_into_editor(date)
# Store the date with the editor so we can save it later
editor.current_date = date
@ -478,19 +476,12 @@ class MainWindow(QMainWindow):
"""
Call the relevant method of the MarkdownEditor class on bind
"""
ed = self.current_editor()
if ed is None:
return
getattr(ed, method_name)(*args)
def current_editor(self) -> MarkdownEditor | None:
"""Get the currently active editor."""
return self.tab_widget.currentWidget()
getattr(self.editor, method_name)(*args)
@property
def editor(self) -> MarkdownEditor | None:
"""Compatibility property to get current editor (for existing code)."""
return self.current_editor()
"""Get the currently active editor."""
return self.tab_widget.currentWidget()
def _date_from_calendar_pos(self, pos) -> QDate | None:
"""Translate a QCalendarWidget local pos to the QDate under the cursor."""
@ -801,16 +792,12 @@ class MainWindow(QMainWindow):
def _load_selected_date(self, date_iso=False, extra_data=False):
"""Load a date into the current editor"""
editor = self.current_editor()
if not editor:
return
if not date_iso:
date_iso = self._current_date_iso()
qd = QDate.fromString(date_iso, "yyyy-MM-dd")
self._load_date_into_editor(qd, editor, extra_data)
editor.current_date = qd
self._load_date_into_editor(qd, extra_data)
self.editor.current_date = qd
# Update tab title
current_index = self.tab_widget.currentIndex()
@ -820,9 +807,7 @@ class MainWindow(QMainWindow):
# Keep tabs sorted by date
self._reorder_tabs_by_date()
def _load_date_into_editor(
self, date: QDate, editor: MarkdownEditor, extra_data=False
):
def _load_date_into_editor(self, date: QDate, extra_data=False):
"""Load a specific date's content into a given editor."""
date_iso = date.toString("yyyy-MM-dd")
try:
@ -833,14 +818,14 @@ class MainWindow(QMainWindow):
text += "\n"
text += extra_data
# Force a save now so we don't lose it.
self._set_editor_markdown_preserve_view(text, editor)
self._set_editor_markdown_preserve_view(text)
self._dirty = True
self._save_date(date_iso, True)
except Exception as e:
QMessageBox.critical(self, "Read Error", str(e))
return
self._set_editor_markdown_preserve_view(text, editor)
self._set_editor_markdown_preserve_view(text)
self._dirty = False
def _save_editor_content(self, editor: MarkdownEditor):
@ -921,10 +906,6 @@ class MainWindow(QMainWindow):
if getattr(self, "_showing_context_menu", False):
return
editor = self.current_editor()
if not editor:
return
# Stop pending autosave and persist current buffer if needed
try:
self._save_timer.stop()
@ -932,14 +913,14 @@ class MainWindow(QMainWindow):
pass
# Save the current editor's content if dirty
if hasattr(editor, "current_date") and self._dirty:
prev_date_iso = editor.current_date.toString("yyyy-MM-dd")
if hasattr(self.editor, "current_date") and self._dirty:
prev_date_iso = self.editor.current_date.toString("yyyy-MM-dd")
self._save_date(prev_date_iso, explicit=False)
# Now load the newly selected date into the current tab
new_date = self.calendar.selectedDate()
self._load_date_into_editor(new_date, editor)
editor.current_date = new_date
self._load_date_into_editor(new_date)
self.editor.current_date = new_date
# Update tab title
current_index = self.tab_widget.currentIndex()
@ -1003,10 +984,6 @@ class MainWindow(QMainWindow):
except Exception:
pass
editor = self.current_editor()
if not editor or not hasattr(editor, "current_date"):
return
if explicit:
# Prompt for a note
dlg = SaveDialog(self)
@ -1016,7 +993,7 @@ class MainWindow(QMainWindow):
else:
note = "autosave"
# Save the current editor's date
date_iso = editor.current_date.toString("yyyy-MM-dd")
date_iso = self.editor.current_date.toString("yyyy-MM-dd")
self._save_date(date_iso, explicit, note)
try:
self._save_timer.start()
@ -1314,17 +1291,18 @@ If you want an encrypted backup, choose Backup instead of Export.
return
if not self.isActiveWindow():
return
editor = self.current_editor()
if not editor:
return
# Belt-and-suspenders: do it now and once more on the next tick
editor.setFocus(Qt.ActiveWindowFocusReason)
editor.ensureCursorVisible()
self.editor.setFocus(Qt.ActiveWindowFocusReason)
self.editor.ensureCursorVisible()
QTimer.singleShot(
0,
lambda: (
editor.setFocus(Qt.ActiveWindowFocusReason) if editor else None,
editor.ensureCursorVisible() if editor else None,
(
self.editor.setFocus(Qt.ActiveWindowFocusReason)
if self.editor
else None
),
self.editor.ensureCursorVisible() if self.editor else None,
),
)
@ -1339,44 +1317,36 @@ If you want an encrypted backup, choose Backup instead of Export.
if ev.type() == QEvent.ActivationChange and self.isActiveWindow():
QTimer.singleShot(0, self._focus_editor_now)
def _set_editor_markdown_preserve_view(
self, markdown: str, editor: MarkdownEditor | None = None
):
if editor is None:
editor = self.current_editor()
if not editor:
return
ed = editor
def _set_editor_markdown_preserve_view(self, markdown: str):
# Save caret/selection and scroll
cur = ed.textCursor()
cur = self.editor.textCursor()
old_pos, old_anchor = cur.position(), cur.anchor()
v = ed.verticalScrollBar().value()
h = ed.horizontalScrollBar().value()
v = self.editor.verticalScrollBar().value()
h = self.editor.horizontalScrollBar().value()
# Only touch the doc if it actually changed
ed.blockSignals(True)
if ed.to_markdown() != markdown:
ed.from_markdown(markdown)
ed.blockSignals(False)
self.editor.blockSignals(True)
if self.editor.to_markdown() != markdown:
self.editor.from_markdown(markdown)
self.editor.blockSignals(False)
# Restore scroll first
ed.verticalScrollBar().setValue(v)
ed.horizontalScrollBar().setValue(h)
self.editor.verticalScrollBar().setValue(v)
self.editor.horizontalScrollBar().setValue(h)
# Restore caret/selection (bounded to new doc length)
doc_length = ed.document().characterCount() - 1
doc_length = self.editor.document().characterCount() - 1
old_pos = min(old_pos, doc_length)
old_anchor = min(old_anchor, doc_length)
cur = ed.textCursor()
cur = self.editor.textCursor()
cur.setPosition(old_anchor)
mode = (
QTextCursor.KeepAnchor if old_anchor != old_pos else QTextCursor.MoveAnchor
)
cur.setPosition(old_pos, mode)
ed.setTextCursor(cur)
self.editor.setTextCursor(cur)
# Refresh highlights if the theme changed
if hasattr(self, "findBar"):

View file

@ -9,18 +9,18 @@ APP_ORG = "Bouquin"
APP_NAME = "Bouquin"
def default_db_path() -> Path:
base = Path(QStandardPaths.writableLocation(QStandardPaths.AppDataLocation))
return base / "notebook.db"
def get_settings() -> QSettings:
return QSettings(APP_ORG, APP_NAME)
def load_db_config() -> DBConfig:
s = get_settings()
path = Path(s.value("db/path", str(default_db_path())))
default_db_path = str(
Path(QStandardPaths.writableLocation(QStandardPaths.AppDataLocation))
/ "notebook.db"
)
path = Path(s.value("db/path", default_db_path))
key = s.value("db/key", "")
idle = s.value("ui/idle_minutes", 15, type=int)
theme = s.value("ui/theme", "system", type=str)

View file

@ -1,6 +1,5 @@
from pathlib import Path
from bouquin.settings import (
default_db_path,
get_settings,
load_db_config,
save_db_config,
@ -8,12 +7,6 @@ from bouquin.settings import (
from bouquin.db import DBConfig
def test_default_db_path_returns_writable_path(app, tmp_path):
p = default_db_path()
assert isinstance(p, Path)
p.parent.mkdir(parents=True, exist_ok=True)
def test_load_and_save_db_config_roundtrip(app, tmp_path):
s = get_settings()
for k in ["db/path", "db/key", "ui/idle_minutes", "ui/theme", "ui/move_todos"]: