diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5966eb0..c560986 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,3 @@
-# 0.1.10
-
- * Improve search results window and highlight in calendar when there are matches.
- * Fix styling issue with text that comes after a URL, so it doesn't appear as part of the URL.
-
# 0.1.9
* More styling/toolbar fixes to support toggled-on styles, exclusive styles (e.g it should not be
diff --git a/bouquin/editor.py b/bouquin/editor.py
index b7fc341..07ef6d3 100644
--- a/bouquin/editor.py
+++ b/bouquin/editor.py
@@ -349,7 +349,7 @@ class Editor(QTextEdit):
if source.hasImage():
img = self._to_qimage(source.imageData())
if img is not None:
- self._insert_qimage_at_cursor(img, autoscale=True)
+ self._insert_qimage_at_cursor(self, img, autoscale=True)
return
# 2) File URLs (drag/drop or paste)
@@ -496,21 +496,12 @@ class Editor(QTextEdit):
cur_fmt = self.textCursor().charFormat()
# Do nothing unless either side indicates we're in/propagating an anchor
- if not (
- ins_fmt.isAnchor()
- or cur_fmt.isAnchor()
- or ins_fmt.fontUnderline()
- or ins_fmt.foreground().style() != Qt.NoBrush
- ):
+ if not (ins_fmt.isAnchor() or cur_fmt.isAnchor()):
return
nf = QTextCharFormat(ins_fmt)
- # stop the link itself
nf.setAnchor(False)
nf.setAnchorHref("")
- # also stop the link *styling*
- nf.setFontUnderline(False)
- nf.clearForeground()
self.setCurrentCharFormat(nf)
diff --git a/bouquin/history_dialog.py b/bouquin/history_dialog.py
index fee2a4f..5ee404c 100644
--- a/bouquin/history_dialog.py
+++ b/bouquin/history_dialog.py
@@ -165,10 +165,12 @@ class HistoryDialog(QDialog):
sel_id = item.data(Qt.UserRole)
if sel_id == self._current_id:
return
+ sel = self._db.get_version(version_id=sel_id)
+ vno = sel["version_no"]
# Flip head pointer
try:
self._db.revert_to_version(self._date, version_id=sel_id)
except Exception as e:
QMessageBox.critical(self, "Revert failed", str(e))
return
- self.accept()
+ self.accept() # let the caller refresh the editor
diff --git a/bouquin/main_window.py b/bouquin/main_window.py
index 693456b..1428384 100644
--- a/bouquin/main_window.py
+++ b/bouquin/main_window.py
@@ -17,12 +17,11 @@ from PySide6.QtCore import (
)
from PySide6.QtGui import (
QAction,
- QBrush,
- QColor,
QCursor,
QDesktopServices,
QFont,
QGuiApplication,
+ QTextCharFormat,
QTextListFormat,
)
from PySide6.QtWidgets import (
@@ -133,15 +132,15 @@ class MainWindow(QMainWindow):
self.search = Search(self.db)
self.search.openDateRequested.connect(self._load_selected_date)
- self.search.resultDatesChanged.connect(self._on_search_dates_changed)
# Lock the calendar to the left panel at the top to stop it stretching
# when the main window is resized.
left_panel = QWidget()
left_layout = QVBoxLayout(left_panel)
left_layout.setContentsMargins(8, 8, 8, 8)
- left_layout.addWidget(self.calendar)
- left_layout.addWidget(self.search)
+ left_layout.addWidget(self.calendar, alignment=Qt.AlignTop)
+ left_layout.addWidget(self.search, alignment=Qt.AlignBottom)
+ left_layout.addStretch(1)
left_panel.setFixedWidth(self.calendar.sizeHint().width() + 16)
# This is the note-taking editor
@@ -314,44 +313,22 @@ class MainWindow(QMainWindow):
if self._try_connect():
return True
- def _on_search_dates_changed(self, date_strs: list[str]):
- dates = set()
- for ds in date_strs or []:
- qd = QDate.fromString(ds, "yyyy-MM-dd")
- if qd.isValid():
- dates.add(qd)
- self._apply_search_highlights(dates)
-
- def _apply_search_highlights(self, dates: set):
- yellow = QBrush(QColor("#fff9c4"))
- old = getattr(self, "_search_highlighted_dates", set())
-
- for d in old - dates: # clear removed
- fmt = self.calendar.dateTextFormat(d)
- fmt.setBackground(Qt.transparent)
- self.calendar.setDateTextFormat(d, fmt)
-
- for d in dates: # apply new/current
- fmt = self.calendar.dateTextFormat(d)
- fmt.setBackground(yellow)
- self.calendar.setDateTextFormat(d, fmt)
-
- self._search_highlighted_dates = dates
-
def _refresh_calendar_marks(self):
- """Make days with entries bold, but keep any search highlight backgrounds."""
+ """
+ Sets a bold marker on the day to indicate that text exists
+ for that day.
+ """
+ fmt_bold = QTextCharFormat()
+ fmt_bold.setFontWeight(QFont.Weight.Bold)
+ # Clear previous marks
for d in getattr(self, "_marked_dates", set()):
- fmt = self.calendar.dateTextFormat(d)
- fmt.setFontWeight(QFont.Weight.Normal) # remove bold only
- self.calendar.setDateTextFormat(d, fmt)
+ self.calendar.setDateTextFormat(d, QTextCharFormat())
self._marked_dates = set()
try:
for date_iso in self.db.dates_with_content():
qd = QDate.fromString(date_iso, "yyyy-MM-dd")
if qd.isValid():
- fmt = self.calendar.dateTextFormat(qd)
- fmt.setFontWeight(QFont.Weight.Bold) # add bold only
- self.calendar.setDateTextFormat(qd, fmt)
+ self.calendar.setDateTextFormat(qd, fmt_bold)
self._marked_dates.add(qd)
except Exception:
pass
diff --git a/bouquin/search.py b/bouquin/search.py
index 27c7e17..8cd2fd5 100644
--- a/bouquin/search.py
+++ b/bouquin/search.py
@@ -6,12 +6,10 @@ from typing import Iterable, Tuple
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QFont, QTextCharFormat, QTextCursor, QTextDocument
from PySide6.QtWidgets import (
- QFrame,
QLabel,
QLineEdit,
QListWidget,
QListWidgetItem,
- QSizePolicy,
QHBoxLayout,
QVBoxLayout,
QWidget,
@@ -25,7 +23,6 @@ class Search(QWidget):
"""Encapsulates the search UI + logic and emits a signal when a result is chosen."""
openDateRequested = Signal(str)
- resultDatesChanged = Signal(list)
def __init__(self, db, parent: QWidget | None = None):
super().__init__(parent)
@@ -33,21 +30,17 @@ class Search(QWidget):
self.search = QLineEdit()
self.search.setPlaceholderText("Search for notes here")
- self.search.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
self.search.textChanged.connect(self._search)
self.results = QListWidget()
self.results.setUniformItemSizes(False)
self.results.setSelectionMode(self.results.SelectionMode.SingleSelection)
- self.results.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self.results.itemClicked.connect(self._open_selected)
self.results.hide()
- self.results.setMinimumHeight(250)
lay = QVBoxLayout(self)
lay.setContentsMargins(0, 0, 0, 0)
lay.setSpacing(6)
- lay.setAlignment(Qt.AlignTop)
lay.addWidget(self.search)
lay.addWidget(self.results)
@@ -65,7 +58,6 @@ class Search(QWidget):
if not q:
self.results.clear()
self.results.hide()
- self.resultDatesChanged.emit([]) # clear highlights
return
try:
@@ -81,10 +73,8 @@ class Search(QWidget):
rows = list(rows)
if not rows:
self.results.hide()
- self.resultDatesChanged.emit([]) # clear highlights
return
- self.resultDatesChanged.emit(sorted({d for d, _ in rows}))
self.results.show()
for date_str, content in rows:
@@ -100,13 +90,12 @@ class Search(QWidget):
outer.setSpacing(2)
# Date label (plain text)
- date_lbl = QLabel()
- date_lbl.setTextFormat(Qt.TextFormat.RichText)
- date_lbl.setText(f"{date_str}:")
+ date_lbl = QLabel(date_str)
+ date_lbl.setTextFormat(Qt.TextFormat.PlainText)
date_f = date_lbl.font()
- date_f.setPointSizeF(date_f.pointSizeF() + 1)
+ date_f.setPointSizeF(date_f.pointSizeF() - 1)
date_lbl.setFont(date_f)
- date_lbl.setStyleSheet("color:#000;")
+ date_lbl.setStyleSheet("color:#666;")
outer.addWidget(date_lbl)
# Preview row with optional ellipses
@@ -138,11 +127,6 @@ class Search(QWidget):
outer.addWidget(row)
- line = QFrame()
- line.setFrameShape(QFrame.HLine)
- line.setFrameShadow(QFrame.Sunken)
- outer.addWidget(line)
-
# ---- Add to list ----
item = QListWidgetItem()
item.setData(Qt.ItemDataRole.UserRole, date_str)
diff --git a/tests/test_editor.py b/tests/test_editor.py
index 6935143..cd5855d 100644
--- a/tests/test_editor.py
+++ b/tests/test_editor.py
@@ -4,8 +4,6 @@ from PySide6.QtTest import QTest
from bouquin.editor import Editor
-import re
-
def _move_cursor_to_first_image(editor: Editor) -> QTextImageFormat | None:
c = editor.textCursor()
@@ -23,57 +21,6 @@ def _move_cursor_to_first_image(editor: Editor) -> QTextImageFormat | None:
return None
-def _fmt_at(editor: Editor, pos: int):
- c = editor.textCursor()
- c.setPosition(pos)
- c.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, 1)
- return c.charFormat()
-
-
-def test_space_breaks_link_anchor_and_styling(qtbot):
- e = Editor()
- e.resize(600, 300)
- e.show()
- qtbot.waitExposed(e)
-
- # Type a URL, which should be linkified (anchor + underline + blue)
- url = "https://mig5.net"
- QTest.keyClicks(e, url)
- qtbot.waitUntil(lambda: e.toPlainText() == url)
-
- # Sanity: characters within the URL are anchors
- for i in range(len(url)):
- assert _fmt_at(e, i).isAnchor()
-
- # Hit Space – Editor.keyPressEvent() should call _break_anchor_for_next_char()
- QTest.keyClick(e, Qt.Key_Space)
-
- # Type some normal text; it must not inherit the link formatting
- tail = "this is a test"
- QTest.keyClicks(e, tail)
- qtbot.waitUntil(lambda: e.toPlainText().endswith(tail))
-
- txt = e.toPlainText()
- # Find where our 'tail' starts
- start = txt.index(tail)
- end = start + len(tail)
-
- # None of the trailing characters should be part of an anchor or visually underlined
- for i in range(start, end):
- fmt = _fmt_at(e, i)
- assert not fmt.isAnchor(), f"char {i} unexpectedly still has an anchor"
- assert not fmt.fontUnderline(), f"char {i} unexpectedly still underlined"
-
- # Optional: ensure the HTML only wraps the URL in , not the trailing text
- html = e.document().toHtml()
- assert re.search(
- r']*href="https?://mig5\.net"[^>]*>(?:]*>)?https?://mig5\.net(?:)?\s+this is a test',
- html,
- re.S,
- ), html
- assert "this is a test" not in html
-
-
def test_embed_qimage_saved_as_data_url(qtbot):
e = Editor()
e.resize(600, 400)