From a8dfff90c58008f8995d426b975bb668fff766e9 Mon Sep 17 00:00:00 2001 From: pax Date: Sat, 11 Apr 2026 22:30:21 -0500 Subject: [PATCH] search: fix autocomplete for multi-tag queries QCompleter previously replaced the entire search bar text when accepting a suggestion, wiping all previous tags. Added _TagCompleter subclass that overrides splitPath (match against last tag only) and pathFromIndex (prepend existing tags). Accepting a suggestion now replaces only the last tag. Space clears the suggestion popup so stale completions from the previous tag don't linger when starting a new tag. behavior change: autocomplete preserves existing tags in multi-tag search; suggestions reset on space. --- booru_viewer/gui/search.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/booru_viewer/gui/search.py b/booru_viewer/gui/search.py index 5c491e9..93e8061 100644 --- a/booru_viewer/gui/search.py +++ b/booru_viewer/gui/search.py @@ -17,6 +17,29 @@ from PySide6.QtWidgets import ( from ..core.db import Database +class _TagCompleter(QCompleter): + """Completer that operates on the last space-separated tag only. + + When the user types "blue_sky tre", the completer matches against + "tre" and the popup shows suggestions for that fragment. Accepting + a suggestion replaces only the last tag, preserving everything + before the final space. + """ + + def splitPath(self, path: str) -> list[str]: + return [path.split()[-1]] if path.split() else [""] + + def pathFromIndex(self, index) -> str: + completion = super().pathFromIndex(index) + text = self.widget().text() + parts = text.split() + if parts: + parts[-1] = completion + else: + parts = [completion] + return " ".join(parts) + " " + + class SearchBar(QWidget): """Tag search bar with autocomplete, history dropdown, and saved searches.""" @@ -63,9 +86,10 @@ class SearchBar(QWidget): self._btn.clicked.connect(self._do_search) layout.addWidget(self._btn) - # Autocomplete + # Autocomplete — _TagCompleter only completes the last tag, + # preserving previous tags in multi-tag queries. self._completer_model = QStringListModel() - self._completer = QCompleter(self._completer_model) + self._completer = _TagCompleter(self._completer_model) self._completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) self._completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion) self._input.setCompleter(self._completer) @@ -78,6 +102,9 @@ class SearchBar(QWidget): self._input.textChanged.connect(self._on_text_changed) def _on_text_changed(self, text: str) -> None: + if text.endswith(" "): + self._completer_model.setStringList([]) + return self._ac_timer.start() def _request_autocomplete(self) -> None: