Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/tagstudio/qt/controllers/field_suggest_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ def __init__(self, library: Library, settings: GlobalSettings, placeholder_text:
self.layout().search_field.addAction(edit_field_on_add_action)
edit_field_on_add_action.setChecked(self._settings.edit_field_on_add)
edit_field_on_add_action.triggered.connect(
lambda checked: self.toggle_edit_on_field_add(checked)
lambda checked: self._toggle_edit_on_field_add(checked)
)

def toggle_edit_on_field_add(self, checked: bool) -> None:
def _toggle_edit_on_field_add(self, checked: bool) -> None:
"""Toggle the setting for opening the edit window after adding a field."""
self._settings.edit_field_on_add = checked
self._settings.save()
Expand Down Expand Up @@ -77,7 +77,7 @@ def _on_item_edit(self, item: BaseFieldTemplate) -> None:
@override
def _on_item_chosen(self, item: BaseFieldTemplate) -> None:
self.item_chosen.emit(item)
self.done.emit()
self.done.emit("*")

@override
def _search_items(self, query: str) -> tuple[list[BaseFieldTemplate], list[BaseFieldTemplate]]:
Expand Down
24 changes: 16 additions & 8 deletions src/tagstudio/qt/controllers/preview_panel_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def __init__(self, driver: "QtDriver") -> None:
super().__init__()
self._driver = driver
self._lib = self._driver.lib
self._settings = self._driver.settings
self._selected: list[int]
self._current_stats: FileAttributeData | None = None

Expand All @@ -75,13 +76,13 @@ def _connect_callbacks(self) -> None:
# Tag Search
self.layout().add_tag_button.clicked.connect(lambda: self._set_item_mode(_ItemMode.TAG))
self._open_tag_search_action.activated.connect(self._open_tag_search_callback)
self.layout().tag_search_box.done.connect(self._tag_added_callback)
self.layout().tag_search_box.done.connect(partial(self._tag_added_callback))
self.layout().containers.on_tags_update.connect(self._update_added_callback)

# Field Search
self.layout().add_field_button.clicked.connect(lambda: self._set_item_mode(_ItemMode.FIELD))
self._open_field_search_action.activated.connect(self._open_field_search_callback)
self.layout().field_search_box.done.connect(self._field_added_callback)
self.layout().field_search_box.done.connect(partial(self._field_added_callback))

# Previews
self.layout().preview_thumb.stats_updated.connect(self._thumb_stats_updated_callback)
Expand Down Expand Up @@ -122,13 +123,20 @@ def _open_field_search_callback(self) -> None:
self.layout().add_field_button.setFocus()
self.layout().add_field_button.click()

def _tag_added_callback(self):
self._set_item_mode(None)
self.layout().add_tag_button.setFocus()
def _tag_added_callback(self, query: str):
if not query or not self._settings.keep_suggest_boxes_open:
self._set_item_mode(None)
self.layout().add_tag_button.setFocus()
else:
self._update_added_callback()
self.layout().tag_search_box.layout().search_field.setFocus()

def _field_added_callback(self):
self._set_item_mode(None)
self.layout().add_field_button.setFocus()
def _field_added_callback(self, query: str):
if not query or not self._settings.keep_suggest_boxes_open:
self._set_item_mode(None)
self.layout().add_field_button.setFocus()
else:
self.layout().field_search_box.layout().search_field.setFocus()

def _update_added_callback(self):
self.layout().tag_search_box.added = self.layout().containers.tags
Expand Down
40 changes: 26 additions & 14 deletions src/tagstudio/qt/controllers/suggest_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@

import structlog
from PySide6.QtCore import Signal
from PySide6.QtGui import QShowEvent
from PySide6.QtGui import QAction, QShowEvent, Qt
from PySide6.QtWidgets import QGraphicsOpacityEffect, QWidget

from tagstudio.core.library.alchemy.library import Library
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.translations import Translations
from tagstudio.qt.views.stylesheets.stylesheets import (
autofill_line_edit_style,
autofill_line_edit_top_style,
Expand Down Expand Up @@ -42,7 +43,7 @@ def _item_name(item: object) -> str:

class SuggestBox[T](QWidget):
item_chosen = Signal(object)
done = Signal()
done = Signal(str) # Query

def __init__(
self, library: Library, settings: GlobalSettings, placeholder_text: str = ""
Expand All @@ -57,8 +58,21 @@ def __init__(
self.excluded: list[int] = []

self.setLayout(SuggestBoxView(placeholder_text))
self.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
self._connect_callbacks()

self._keep_box_open_action = QAction(Translations["settings.keep_suggest_boxes_open"], self)
self._keep_box_open_action.setCheckable(True)
self.addAction(self._keep_box_open_action)
self.layout().search_field.addAction(self._keep_box_open_action)
self._keep_box_open_action.triggered.connect(
lambda checked: self._toggle_keep_open(checked)
)

def _toggle_keep_open(self, checked: bool) -> None:
self._settings.keep_suggest_boxes_open = checked
self._settings.save()

def set_placeholder_text(self, text: str) -> None:
self.layout().search_field.setPlaceholderText(text)

Expand Down Expand Up @@ -108,10 +122,8 @@ def _on_search_query_changed(self, query: str) -> None:

def _on_search_query_submitted(self, query: str, always_create: bool = False) -> None:
# Focus search field if no query
logger.info("Query submitted")
if not query:
self.done.emit()
self.hide_and_reset()
self.done.emit(query)
return
elif not self.isHidden():
self.layout().search_field.setFocus()
Expand Down Expand Up @@ -197,9 +209,10 @@ def _set_item_widget(self, item: T | None, index: int) -> None: # pyright: igno
raise NotImplementedError()

def _editing_finished_callback(self) -> None:
if self.layout().search_field.text() == "":
self.done.emit()
self.hide_and_reset()
# Only trigger when the search field is clicked off of and there's no query.
# NOTE: The search field is already cleared by this point when pressing enter.
if self.layout().search_field.text() == "" and not self.layout().search_field.hasFocus():
self.done.emit("")

def _create_item_from_modal(self, edit_item_panel: ModalContent) -> None: # pyright: ignore[reportUnusedParameter]
raise NotImplementedError()
Expand All @@ -213,6 +226,7 @@ def showEvent(self, event: QShowEvent) -> None:
self._on_shift_held(held=False)
self.layout().search_field.setDisabled(False)
self._clear_search_query()
self._keep_box_open_action.setChecked(self._settings.keep_suggest_boxes_open)
return super().showEvent(event)

@override
Expand All @@ -222,9 +236,7 @@ def layout(self) -> SuggestBoxView:
@override
def keyPressEvent(self, event: QtGui.QKeyEvent) -> None:
# When Escape is pressed, focus back on the search box.
if event.key() in {
QtCore.Qt.Key.Key_Escape,
QtCore.Qt.Key.Key_Enter,
QtCore.Qt.Key.Key_Return,
}:
self.hide_and_reset()
if event.key() in {QtCore.Qt.Key.Key_Enter, QtCore.Qt.Key.Key_Return}:
self.done.emit("*")
elif event.key() == QtCore.Qt.Key.Key_Escape:
self.done.emit("")
13 changes: 6 additions & 7 deletions src/tagstudio/qt/controllers/tag_suggest_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import structlog
from PySide6.QtCore import Signal
from PySide6.QtGui import QAction, Qt
from PySide6.QtGui import QAction
from PySide6.QtWidgets import QGraphicsOpacityEffect, QWidget

from tagstudio.core.library.alchemy.library import Library
Expand All @@ -33,18 +33,17 @@ def __init__(
super().__init__(library, settings, placeholder_text)

# Context Menu Actions

edit_tag_on_create_action = QAction(Translations["settings.edit_tag_on_create"], self)
edit_tag_on_create_action.setCheckable(True)
self.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
self.addAction(edit_tag_on_create_action)
self.layout().search_field.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
self.layout().search_field.addAction(edit_tag_on_create_action)
edit_tag_on_create_action.setChecked(self._settings.edit_tag_on_create)
edit_tag_on_create_action.triggered.connect(
lambda checked: self.toggle_edit_on_tag_create(checked)
lambda checked: self._toggle_edit_on_tag_create(checked)
)

def toggle_edit_on_tag_create(self, checked: bool) -> None:
def _toggle_edit_on_tag_create(self, checked: bool) -> None:
"""Toggle the setting for opening the edit window after creating a tag."""
self._settings.edit_tag_on_create = checked
self._settings.save()
Expand Down Expand Up @@ -89,7 +88,8 @@ def _on_item_edit(self, item: Tag) -> None:
@override
def _on_item_chosen(self, item: Tag) -> None:
self.item_chosen.emit(item.id)
self.done.emit()
self._clear_search_query()
self.done.emit("*") # The query does not matter

@override
def _search_items(self, query: str) -> tuple[list[Tag], list[Tag]]:
Expand Down Expand Up @@ -144,7 +144,6 @@ def _create_item_from_modal(self, edit_item_panel: ModalContent) -> None:
tag, parent_ids=edit_item_panel.parent_ids, aliases=edit_item_panel.aliases
)
self._on_item_chosen(tag)
self._clear_search_query()

edit_item_panel.hide()
self._on_search_query_changed(self.layout().search_field.text())
Expand Down
1 change: 1 addition & 0 deletions src/tagstudio/qt/global_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class GlobalSettings(BaseModel):
tag_click_action: TagClickActionOption = Field(default=TagClickActionOption.DEFAULT)
edit_tag_on_create: bool = Field(default=False)
edit_field_on_add: bool = Field(default=True)
keep_suggest_boxes_open: bool = Field(default=True)
theme: Theme = Field(default=Theme.SYSTEM)
splash: Splash = Field(default=Splash.DEFAULT)
windows_start_command: bool = Field(default=False)
Expand Down
11 changes: 11 additions & 0 deletions src/tagstudio/qt/mixed/settings_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,15 @@ def on_page_size_changed():
Translations["settings.edit_field_on_add"], self.edit_field_on_add_checkbox
)

# Keep Tag/Field Suggest Boxes Open After Adding Items
self.keep_suggest_boxes_open_checkbox = QCheckBox()
self.keep_suggest_boxes_open_checkbox.setChecked(
self.driver.settings.keep_suggest_boxes_open
)
form_layout.addRow(
Translations["settings.keep_suggest_boxes_open"], self.keep_suggest_boxes_open_checkbox
)

# TODO: Implement Library Settings
def __build_library_settings(self): # pyright: ignore[reportUnusedFunction]
form_layout = QFormLayout(self.library_settings_container)
Expand Down Expand Up @@ -383,6 +392,7 @@ def get_settings(self) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
"tag_click_action": self.tag_click_action_combobox.currentData(),
"edit_tag_on_create": self.edit_tag_on_create_checkbox.isChecked(),
"edit_field_on_add": self.edit_field_on_add_checkbox.isChecked(),
"keep_suggest_boxes_open": self.keep_suggest_boxes_open_checkbox.isChecked(),
"date_format": self.dateformat_combobox.currentData(),
"hour_format": self.hourformat_checkbox.isChecked(),
"zero_padding": self.zeropadding_checkbox.isChecked(),
Expand All @@ -407,6 +417,7 @@ def update_settings(self, driver: "QtDriver"):
driver.settings.tag_click_action = settings["tag_click_action"]
driver.settings.edit_tag_on_create = settings["edit_tag_on_create"]
driver.settings.edit_field_on_add = settings["edit_field_on_add"]
driver.settings.keep_suggest_boxes_open = settings["keep_suggest_boxes_open"]
driver.settings.date_format = settings["date_format"]
driver.settings.hour_format = settings["hour_format"]
driver.settings.zero_padding = settings["zero_padding"]
Expand Down
1 change: 1 addition & 0 deletions src/tagstudio/qt/views/suggest_box_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def __init__(self, placeholder_text: str = "") -> None:
self.search_field.setMinimumHeight(28)
self.search_field.setPlaceholderText(placeholder_text)
self.scroll_area.setFocusProxy(self.search_field)
self.search_field.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)

# Finalize Layout
self.addWidget(scroll_area_container)
Expand Down
3 changes: 2 additions & 1 deletion src/tagstudio/resources/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
"home.search_or_create_fields": "Search or Create Fields…",
"home.search_or_create_tags": "Search or Create Tags…",
"home.search_tags": "Search Tags…",
"home.search.how_to_exit": "(Esc to Exit)",
"home.search.how_to_exit": "(Enter to Exit)",
"home.search.view_limit": "View Limit:",
"home.show_hidden_entries": "Show Hidden Entries",
"home.thumbnail_size": "Thumbnail Size",
Expand Down Expand Up @@ -329,6 +329,7 @@
"settings.global": "Global Settings",
"settings.hourformat.label": "24-Hour Time",
"settings.infinite_scroll": "Infinite Scrolling",
"settings.keep_suggest_boxes_open": "Keep Search Boxes Open After Adding Items",
"settings.language": "Language",
"settings.library": "Library Settings",
"settings.localization": "Localization",
Expand Down
Loading