Improve search results window and highlight in calendar when there are matches.

This commit is contained in:
Miguel Jacq 2025-11-05 16:10:48 +11:00
parent 6fb465c546
commit 0e3ca64619
Signed by: mig5
GPG key ID: 59B3F0C24135C6A9
3 changed files with 60 additions and 17 deletions

View file

@ -1,3 +1,7 @@
# 0.1.10
* Improve search results window and highlight in calendar when there are matches.
# 0.1.9 # 0.1.9
* More styling/toolbar fixes to support toggled-on styles, exclusive styles (e.g it should not be * More styling/toolbar fixes to support toggled-on styles, exclusive styles (e.g it should not be

View file

@ -17,11 +17,12 @@ from PySide6.QtCore import (
) )
from PySide6.QtGui import ( from PySide6.QtGui import (
QAction, QAction,
QBrush,
QColor,
QCursor, QCursor,
QDesktopServices, QDesktopServices,
QFont, QFont,
QGuiApplication, QGuiApplication,
QTextCharFormat,
QTextListFormat, QTextListFormat,
) )
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
@ -132,15 +133,15 @@ class MainWindow(QMainWindow):
self.search = Search(self.db) self.search = Search(self.db)
self.search.openDateRequested.connect(self._load_selected_date) 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 # Lock the calendar to the left panel at the top to stop it stretching
# when the main window is resized. # when the main window is resized.
left_panel = QWidget() left_panel = QWidget()
left_layout = QVBoxLayout(left_panel) left_layout = QVBoxLayout(left_panel)
left_layout.setContentsMargins(8, 8, 8, 8) left_layout.setContentsMargins(8, 8, 8, 8)
left_layout.addWidget(self.calendar, alignment=Qt.AlignTop) left_layout.addWidget(self.calendar)
left_layout.addWidget(self.search, alignment=Qt.AlignBottom) left_layout.addWidget(self.search)
left_layout.addStretch(1)
left_panel.setFixedWidth(self.calendar.sizeHint().width() + 16) left_panel.setFixedWidth(self.calendar.sizeHint().width() + 16)
# This is the note-taking editor # This is the note-taking editor
@ -313,22 +314,44 @@ class MainWindow(QMainWindow):
if self._try_connect(): if self._try_connect():
return True 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): 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()): for d in getattr(self, "_marked_dates", set()):
self.calendar.setDateTextFormat(d, QTextCharFormat()) fmt = self.calendar.dateTextFormat(d)
fmt.setFontWeight(QFont.Weight.Normal) # remove bold only
self.calendar.setDateTextFormat(d, fmt)
self._marked_dates = set() self._marked_dates = set()
try: try:
for date_iso in self.db.dates_with_content(): for date_iso in self.db.dates_with_content():
qd = QDate.fromString(date_iso, "yyyy-MM-dd") qd = QDate.fromString(date_iso, "yyyy-MM-dd")
if qd.isValid(): if qd.isValid():
self.calendar.setDateTextFormat(qd, fmt_bold) fmt = self.calendar.dateTextFormat(qd)
fmt.setFontWeight(QFont.Weight.Bold) # add bold only
self.calendar.setDateTextFormat(qd, fmt)
self._marked_dates.add(qd) self._marked_dates.add(qd)
except Exception: except Exception:
pass pass

View file

@ -6,10 +6,12 @@ from typing import Iterable, Tuple
from PySide6.QtCore import Qt, Signal from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QFont, QTextCharFormat, QTextCursor, QTextDocument from PySide6.QtGui import QFont, QTextCharFormat, QTextCursor, QTextDocument
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QFrame,
QLabel, QLabel,
QLineEdit, QLineEdit,
QListWidget, QListWidget,
QListWidgetItem, QListWidgetItem,
QSizePolicy,
QHBoxLayout, QHBoxLayout,
QVBoxLayout, QVBoxLayout,
QWidget, QWidget,
@ -23,6 +25,7 @@ class Search(QWidget):
"""Encapsulates the search UI + logic and emits a signal when a result is chosen.""" """Encapsulates the search UI + logic and emits a signal when a result is chosen."""
openDateRequested = Signal(str) openDateRequested = Signal(str)
resultDatesChanged = Signal(list)
def __init__(self, db, parent: QWidget | None = None): def __init__(self, db, parent: QWidget | None = None):
super().__init__(parent) super().__init__(parent)
@ -30,17 +33,21 @@ class Search(QWidget):
self.search = QLineEdit() self.search = QLineEdit()
self.search.setPlaceholderText("Search for notes here") self.search.setPlaceholderText("Search for notes here")
self.search.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
self.search.textChanged.connect(self._search) self.search.textChanged.connect(self._search)
self.results = QListWidget() self.results = QListWidget()
self.results.setUniformItemSizes(False) self.results.setUniformItemSizes(False)
self.results.setSelectionMode(self.results.SelectionMode.SingleSelection) self.results.setSelectionMode(self.results.SelectionMode.SingleSelection)
self.results.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self.results.itemClicked.connect(self._open_selected) self.results.itemClicked.connect(self._open_selected)
self.results.hide() self.results.hide()
self.results.setMinimumHeight(250)
lay = QVBoxLayout(self) lay = QVBoxLayout(self)
lay.setContentsMargins(0, 0, 0, 0) lay.setContentsMargins(0, 0, 0, 0)
lay.setSpacing(6) lay.setSpacing(6)
lay.setAlignment(Qt.AlignTop)
lay.addWidget(self.search) lay.addWidget(self.search)
lay.addWidget(self.results) lay.addWidget(self.results)
@ -58,6 +65,7 @@ class Search(QWidget):
if not q: if not q:
self.results.clear() self.results.clear()
self.results.hide() self.results.hide()
self.resultDatesChanged.emit([]) # clear highlights
return return
try: try:
@ -73,8 +81,10 @@ class Search(QWidget):
rows = list(rows) rows = list(rows)
if not rows: if not rows:
self.results.hide() self.results.hide()
self.resultDatesChanged.emit([]) # clear highlights
return return
self.resultDatesChanged.emit(sorted({d for d, _ in rows}))
self.results.show() self.results.show()
for date_str, content in rows: for date_str, content in rows:
@ -90,12 +100,13 @@ class Search(QWidget):
outer.setSpacing(2) outer.setSpacing(2)
# Date label (plain text) # Date label (plain text)
date_lbl = QLabel(date_str) date_lbl = QLabel()
date_lbl.setTextFormat(Qt.TextFormat.PlainText) date_lbl.setTextFormat(Qt.TextFormat.RichText)
date_lbl.setText(f"<i>{date_str}</i>:")
date_f = date_lbl.font() 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.setFont(date_f)
date_lbl.setStyleSheet("color:#666;") date_lbl.setStyleSheet("color:#000;")
outer.addWidget(date_lbl) outer.addWidget(date_lbl)
# Preview row with optional ellipses # Preview row with optional ellipses
@ -127,6 +138,11 @@ class Search(QWidget):
outer.addWidget(row) outer.addWidget(row)
line = QFrame()
line.setFrameShape(QFrame.HLine)
line.setFrameShadow(QFrame.Sunken)
outer.addWidget(line)
# ---- Add to list ---- # ---- Add to list ----
item = QListWidgetItem() item = QListWidgetItem()
item.setData(Qt.ItemDataRole.UserRole, date_str) item.setData(Qt.ItemDataRole.UserRole, date_str)