mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-02-01 15:49:09 +00:00
ui: keyboard navigation for editing tags (#407)
* build_tag modal: make Tag Title selected when opening modal
* build_tag modal: Tab now changes focus when aliases field is in focus
* fix: unpredictable tab order in build tag modal
* feat: implement proper tab order
* ci: fix mypy errors
* fix: merge issue 1
* fix: merge issue 2
* refactor: TagDatabasePanel now inherits from TagSearchPanel for code deduplication
* Revert "refactor: TagDatabasePanel now inherits from TagSearchPanel for code deduplication"
This reverts commit fac589b3e3.
This commit is contained in:
@@ -112,6 +112,8 @@ class BuildTagPanel(PanelWidget):
|
||||
self.aliases_table.verticalHeader().setVisible(False)
|
||||
self.aliases_table.horizontalHeader().setStretchLastSection(True)
|
||||
self.aliases_table.setColumnWidth(0, 35)
|
||||
self.aliases_table.setTabKeyNavigation(False)
|
||||
self.aliases_table.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
||||
|
||||
self.alias_add_button = QPushButton()
|
||||
self.alias_add_button.setText("+")
|
||||
@@ -136,6 +138,7 @@ class BuildTagPanel(PanelWidget):
|
||||
self.parent_tags_scroll_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
|
||||
|
||||
self.scroll_area = QScrollArea()
|
||||
self.scroll_area.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
||||
# self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
|
||||
self.scroll_area.setWidgetResizable(True)
|
||||
self.scroll_area.setFrameShadow(QFrame.Shadow.Plain)
|
||||
@@ -239,8 +242,6 @@ class BuildTagPanel(PanelWidget):
|
||||
self.new_item_id = sys.maxsize
|
||||
|
||||
self.set_tag(tag or Tag(name=Translations["tag.new"]))
|
||||
if tag is None:
|
||||
self.name_field.selectAll()
|
||||
|
||||
def backspace(self):
|
||||
focused_widget = QApplication.focusWidget()
|
||||
@@ -305,6 +306,7 @@ class BuildTagPanel(PanelWidget):
|
||||
while self.parent_tags_scroll_layout.itemAt(0):
|
||||
self.parent_tags_scroll_layout.takeAt(0).widget().deleteLater()
|
||||
|
||||
last: QWidget = self.aliases_table.cellWidget(self.aliases_table.rowCount() - 1, 1)
|
||||
c = QWidget()
|
||||
layout = QVBoxLayout(c)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
@@ -314,6 +316,10 @@ class BuildTagPanel(PanelWidget):
|
||||
tw = TagWidget(tag, has_edit=False, has_remove=True)
|
||||
tw.on_remove.connect(lambda t=tag_id: self.remove_parent_tag_callback(t))
|
||||
layout.addWidget(tw)
|
||||
self.setTabOrder(last, tw.bg_button)
|
||||
last = tw.bg_button
|
||||
self.setTabOrder(last, self.name_field)
|
||||
|
||||
self.parent_tags_scroll_layout.addWidget(c)
|
||||
|
||||
def add_aliases(self):
|
||||
@@ -349,6 +355,7 @@ class BuildTagPanel(PanelWidget):
|
||||
|
||||
self.alias_names.clear()
|
||||
|
||||
last: QWidget = self.panel_save_button or self.color_field
|
||||
for alias_id in self.alias_ids:
|
||||
alias = self.lib.get_alias(self.tag.id, alias_id)
|
||||
|
||||
@@ -375,6 +382,12 @@ class BuildTagPanel(PanelWidget):
|
||||
self.aliases_table.setCellWidget(row, 1, new_item)
|
||||
self.aliases_table.setCellWidget(row, 0, remove_btn)
|
||||
|
||||
self.setTabOrder(last, self.aliases_table.cellWidget(row, 1))
|
||||
self.setTabOrder(
|
||||
self.aliases_table.cellWidget(row, 1), self.aliases_table.cellWidget(row, 0)
|
||||
)
|
||||
last = self.aliases_table.cellWidget(row, 0)
|
||||
|
||||
def _alias_name_change(self, item: CustomTableItem):
|
||||
self.new_alias_names[item.id] = item.text()
|
||||
|
||||
@@ -424,3 +437,14 @@ class BuildTagPanel(PanelWidget):
|
||||
|
||||
logger.info("built tag", tag=tag)
|
||||
return tag
|
||||
|
||||
def parent_post_init(self):
|
||||
self.setTabOrder(self.name_field, self.shorthand_field)
|
||||
self.setTabOrder(self.shorthand_field, self.alias_add_button)
|
||||
self.setTabOrder(self.alias_add_button, self.parent_tags_add_button)
|
||||
self.setTabOrder(self.parent_tags_add_button, self.color_field)
|
||||
self.setTabOrder(self.color_field, self.panel_cancel_button)
|
||||
self.setTabOrder(self.panel_cancel_button, self.panel_save_button)
|
||||
self.setTabOrder(self.panel_save_button, self.aliases_table.cellWidget(0, 1))
|
||||
self.name_field.selectAll()
|
||||
self.name_field.setFocus()
|
||||
|
||||
@@ -706,14 +706,14 @@ class QtDriver(DriverMixin, QObject):
|
||||
)
|
||||
|
||||
def add_tag_action_callback(self):
|
||||
panel = BuildTagPanel(self.lib)
|
||||
self.modal = PanelModal(
|
||||
BuildTagPanel(self.lib),
|
||||
panel,
|
||||
has_save=True,
|
||||
)
|
||||
Translations.translate_with_setter(self.modal.setTitle, "tag.new")
|
||||
Translations.translate_with_setter(self.modal.setWindowTitle, "tag.add")
|
||||
|
||||
panel: BuildTagPanel = self.modal.widget
|
||||
self.modal.saved.connect(
|
||||
lambda: (
|
||||
self.lib.add_tag(
|
||||
|
||||
@@ -16,7 +16,7 @@ class PanelModal(QWidget):
|
||||
# figure out what you want from this.
|
||||
def __init__(
|
||||
self,
|
||||
widget,
|
||||
widget: "PanelWidget",
|
||||
title: str = "",
|
||||
window_title: str = "",
|
||||
done_callback: Callable | None = None,
|
||||
@@ -89,8 +89,10 @@ class PanelModal(QWidget):
|
||||
|
||||
self.root_layout.addWidget(self.title_widget)
|
||||
self.root_layout.addWidget(widget)
|
||||
widget.parent_modal = self
|
||||
self.root_layout.setStretch(1, 2)
|
||||
self.root_layout.addWidget(self.button_container)
|
||||
widget.parent_post_init()
|
||||
|
||||
def closeEvent(self, event): # noqa: N802
|
||||
self.done_button.click()
|
||||
@@ -104,6 +106,7 @@ class PanelWidget(QWidget):
|
||||
"""Used for widgets that go in a modal panel, ex. for editing or searching."""
|
||||
|
||||
done = Signal()
|
||||
parent_modal: PanelModal = None
|
||||
panel_save_button: QPushButton | None = None
|
||||
panel_cancel_button: QPushButton | None = None
|
||||
panel_done_button: QPushButton | None = None
|
||||
@@ -117,5 +120,8 @@ class PanelWidget(QWidget):
|
||||
def reset(self):
|
||||
pass
|
||||
|
||||
def parent_post_init(self):
|
||||
pass
|
||||
|
||||
def add_callback(self, callback: Callable, event: str = "returnPressed"):
|
||||
logging.warning(f"add_callback not implemented for {self.__class__.__name__}")
|
||||
|
||||
@@ -73,9 +73,9 @@ class PreviewPanel(QWidget):
|
||||
self.file_attrs = FileAttributes(library, driver)
|
||||
self.fields = FieldContainers(library, driver)
|
||||
|
||||
tag_search_panel = TagSearchPanel(self.driver.lib)
|
||||
self.tag_search_panel = TagSearchPanel(self.driver.lib)
|
||||
self.add_tag_modal = PanelModal(
|
||||
tag_search_panel, Translations.translate_formatted("tag.add.plural")
|
||||
self.tag_search_panel, Translations.translate_formatted("tag.add.plural")
|
||||
)
|
||||
Translations.translate_with_setter(self.add_tag_modal.setWindowTitle, "tag.add.plural")
|
||||
|
||||
@@ -195,10 +195,10 @@ class PreviewPanel(QWidget):
|
||||
|
||||
def update_add_tag_button(self, entry_id: int = None):
|
||||
with catch_warnings(record=True):
|
||||
self.add_tag_modal.widget.tag_chosen.disconnect()
|
||||
self.tag_search_panel.tag_chosen.disconnect()
|
||||
self.add_tag_button.clicked.disconnect()
|
||||
|
||||
self.add_tag_modal.widget.tag_chosen.connect(
|
||||
self.tag_search_panel.tag_chosen.connect(
|
||||
lambda t: (
|
||||
self.fields.add_tags_to_selected(t),
|
||||
(self.fields.update_from_entry(entry_id) if entry_id else ()),
|
||||
@@ -207,7 +207,7 @@ class PreviewPanel(QWidget):
|
||||
|
||||
self.add_tag_button.clicked.connect(
|
||||
lambda: (
|
||||
self.add_tag_modal.widget.update_tags(),
|
||||
self.tag_search_panel.update_tags(),
|
||||
self.add_tag_modal.show(),
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user