Compare commits

...

1 Commits

Author SHA1 Message Date
Travis Abendshien 7cd1f65d70 feat(ui): add hint icons to suggest boxes 2026-08-13 10:46:58 -07:00
16 changed files with 84 additions and 2 deletions
+7 -1
View File
@@ -45,6 +45,12 @@ SPDX-FileCopyrightText = "(c) 2026 Boxicons"
SPDX-License-Identifier = "MIT"
[[annotations]]
path = ["src/tagstudio/resources/qt/images/dupe_file_stat.png"]
path = [
"src/tagstudio/resources/qt/images/dupe_file_stat.png",
"src/tagstudio/resources/qt/images/hint_field_add.png",
"src/tagstudio/resources/qt/images/hint_field_create.png",
"src/tagstudio/resources/qt/images/hint_tag_add.png",
"src/tagstudio/resources/qt/images/hint_tag_create.png",
]
SPDX-FileCopyrightText = "(c) github:google/material-design-icons Contributors"
SPDX-License-Identifier = "Apache-2.0"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

@@ -86,6 +86,24 @@ class FieldSuggestBox(SuggestBox[BaseFieldTemplate]):
else:
return ([], [])
@override
def _on_shift_held(self, held: bool) -> None:
if held:
self.set_hint_icon(self._rm.hint_field_create)
else:
self._update_hint_icon()
return super()._on_shift_held(held)
@override
def _update_hint_icon(self) -> None:
if self.layout().search_field.text() and len(self._search_results) > 0:
self.set_hint_icon(self._rm.hint_field_add)
elif self.layout().search_field.text():
self.set_hint_icon(self._rm.hint_field_create)
else:
self.set_hint_icon(None)
@override
def _set_item_widget(self, item: BaseFieldTemplate | None, index: int) -> None:
"""Set the field template of a field template widget at a specific index."""
+16 -1
View File
@@ -4,8 +4,9 @@
from typing import Any, override
import structlog
from PIL import Image, ImageQt
from PySide6.QtCore import Signal
from PySide6.QtGui import QShowEvent
from PySide6.QtGui import QPixmap, QShowEvent
from PySide6.QtWidgets import QGraphicsOpacityEffect, QWidget
from tagstudio.core.library.alchemy.library import Library
@@ -13,6 +14,8 @@ from tagstudio.qt.controllers.autofill_line_edit import QtCore, QtGui
from tagstudio.qt.controllers.modal_content import ModalContent
from tagstudio.qt.controllers.underlined_widget import UnderlinedWidget
from tagstudio.qt.global_settings import GlobalSettings
from tagstudio.qt.helpers.color_overlay import auto_theme_overlay
from tagstudio.qt.resource_manager import ResourceManager
from tagstudio.qt.views.stylesheets.stylesheets import (
autofill_line_edit_style,
autofill_line_edit_top_style,
@@ -50,6 +53,7 @@ class SuggestBox[T](QWidget):
super().__init__()
self._lib = library
self._settings = settings
self._rm = ResourceManager()
self._limit = 5
self._is_shift_held = False
self._search_results: list[T] = []
@@ -81,6 +85,13 @@ class SuggestBox[T](QWidget):
self.layout().search_field.shift_holding.connect(lambda held: self._on_shift_held(held))
def set_hint_icon(self, icon: Image.Image | None) -> None:
if icon:
pixmap = QPixmap.fromImage(ImageQt.ImageQt(auto_theme_overlay(icon)))
self.layout().hint_icon_action.setIcon(pixmap)
else:
self.layout().hint_icon_action.setIcon(QPixmap())
def _on_shift_held(self, held: bool) -> None:
if held:
self._is_shift_held = True
@@ -105,6 +116,7 @@ class SuggestBox[T](QWidget):
def _on_search_query_changed(self, query: str) -> None:
self._update_items(query)
self._update_hint_icon()
def _on_search_query_submitted(self, query: str, always_create: bool = False) -> None:
# Focus search field if no query
@@ -137,6 +149,9 @@ class SuggestBox[T](QWidget):
def _is_excluded(self, item: T) -> bool:
return _item_id(item) in self.excluded
def _update_hint_icon(self) -> None:
raise NotImplementedError()
def _update_items(self, query: str | None = None) -> None:
"""Update the item list given a search query."""
logger.info("[SearchPanel] Updating items", limit=self._limit)
@@ -91,6 +91,24 @@ class TagSuggestBox(SuggestBox[Tag]):
self.item_chosen.emit(item.id)
self.done.emit()
@override
def _on_shift_held(self, held: bool) -> None:
if held:
self.set_hint_icon(self._rm.hint_tag_create)
else:
self._update_hint_icon()
return super()._on_shift_held(held)
@override
def _update_hint_icon(self) -> None:
if self.layout().search_field.text() and len(self._search_results) > 0:
self.set_hint_icon(self._rm.hint_tag_add)
elif self.layout().search_field.text():
self.set_hint_icon(self._rm.hint_tag_create)
else:
self.set_hint_icon(None)
@override
def _search_items(self, query: str) -> tuple[list[Tag], list[Tag]]:
if query != "":
+4
View File
@@ -36,6 +36,10 @@ class ResourceManager:
edit: Image.Image
file_generic: Image.Image
font: Image.Image
hint_field_add: Image.Image
hint_field_create: Image.Image
hint_tag_add: Image.Image
hint_tag_create: Image.Image
icon: Image.Image
ignored_stat: Image.Image
ignored: Image.Image
+16
View File
@@ -71,6 +71,22 @@
"mode": "pil",
"path": "qt/images/file_icons/font.png"
},
"hint_field_add": {
"mode": "pil",
"path": "qt/images/hint_field_add.png"
},
"hint_field_create": {
"mode": "pil",
"path": "qt/images/hint_field_create.png"
},
"hint_tag_add": {
"mode": "pil",
"path": "qt/images/hint_tag_add.png"
},
"hint_tag_create": {
"mode": "pil",
"path": "qt/images/hint_tag_create.png"
},
"icon": {
"mode": "pil",
"path": "icon.png"
@@ -4,6 +4,7 @@
import structlog
from PySide6.QtCore import Qt
from PySide6.QtGui import QPixmap
from PySide6.QtWidgets import QFrame, QHBoxLayout, QScrollArea, QSizePolicy, QVBoxLayout, QWidget
from tagstudio.qt.controllers.autofill_line_edit import AutofillLineEdit
@@ -18,6 +19,7 @@ logger = structlog.get_logger(__name__)
class SuggestBoxView(QVBoxLayout):
def __init__(self, placeholder_text: str = "") -> None:
super().__init__()
self.setContentsMargins(0, 0, 0, 0)
self.setSpacing(0)
@@ -70,6 +72,9 @@ class SuggestBoxView(QVBoxLayout):
self.search_field.setObjectName("search_field")
self.search_field.setMinimumHeight(28)
self.search_field.setPlaceholderText(placeholder_text)
self.hint_icon_action = self.search_field.addAction(
QPixmap(), AutofillLineEdit.ActionPosition.TrailingPosition
)
self.scroll_area.setFocusProxy(self.search_field)
# Finalize Layout
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB