fix: preserve category/manufacturer selection when focusing and highlighting

- Add internal state tracking (_active_category, _active_manufacturer) to Sidebar
- Cmd+3/4 now restores previously selected category/manufacturer instead of always selecting first
- Manufacturer gray highlight remains when clicking a plugin (filter still active)
- Pressing Enter on plugin or sidebar now highlights plugin's categories
- All focus/selection uses proper selectionModel.setCurrentIndex with ClearAndSelect flag

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
h
2026-01-31 13:34:16 +01:00
parent 6cb2754353
commit a58b4f0928
2 changed files with 72 additions and 6 deletions

View File

@@ -34,6 +34,8 @@ KVK_K = 0x28
class _VimTableView(QTableView): class _VimTableView(QTableView):
enter_pressed = Signal()
def _select_row(self, row: int) -> None: def _select_row(self, row: int) -> None:
index = self.model().index(row, 0) index = self.model().index(row, 0)
self.selectionModel().setCurrentIndex( self.selectionModel().setCurrentIndex(
@@ -58,6 +60,10 @@ class _VimTableView(QTableView):
self._select_row(current.row() - 1) self._select_row(current.row() - 1)
event.accept() event.accept()
return return
if key in (Qt.Key.Key_Return, Qt.Key.Key_Enter):
self.enter_pressed.emit()
event.accept()
return
super().keyPressEvent(event) super().keyPressEvent(event)
@@ -131,6 +137,7 @@ class PluginTableView(QWidget):
layout.addWidget(self._table, 1) layout.addWidget(self._table, 1)
self._table.selectionModel().currentChanged.connect(self._on_current_changed) self._table.selectionModel().currentChanged.connect(self._on_current_changed)
self._table.enter_pressed.connect(self._on_enter_pressed)
def _on_current_changed(self, current: QModelIndex, _previous: QModelIndex) -> None: def _on_current_changed(self, current: QModelIndex, _previous: QModelIndex) -> None:
if current.isValid(): if current.isValid():
@@ -138,6 +145,13 @@ class PluginTableView(QWidget):
if plugin: if plugin:
self.plugin_selected.emit(plugin) self.plugin_selected.emit(plugin)
def _on_enter_pressed(self) -> None:
current = self._table.currentIndex()
if current.isValid():
plugin = self._model.get_plugin(current.row())
if plugin:
self.plugin_selected.emit(plugin)
def set_plugins(self, logic: Logic) -> None: def set_plugins(self, logic: Logic) -> None:
self._model.set_plugins(logic) self._model.set_plugins(logic)
self._resize_columns() self._resize_columns()
@@ -175,6 +189,12 @@ class PluginTableView(QWidget):
if not has_selection and self._model.rowCount() > 0: if not has_selection and self._model.rowCount() > 0:
self._table.selectRow(0) self._table.selectRow(0)
current = self._table.currentIndex()
if current.isValid():
plugin = self._model.get_plugin(current.row())
if plugin:
self.plugin_selected.emit(plugin)
def _on_search_escape(self) -> None: def _on_search_escape(self) -> None:
self._table.setFocus() self._table.setFocus()

View File

@@ -257,6 +257,9 @@ class Sidebar(QWidget):
super().__init__(parent) super().__init__(parent)
self.setMinimumWidth(200) self.setMinimumWidth(200)
self._active_category: str | None = None
self._active_manufacturer: str | None = None
layout = QVBoxLayout(self) layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0) layout.setSpacing(0)
@@ -392,22 +395,30 @@ class Sidebar(QWidget):
self._uncategorized.set_selected(False) self._uncategorized.set_selected(False)
def _on_show_all_clicked(self) -> None: def _on_show_all_clicked(self) -> None:
self._active_category = "Show All"
self._active_manufacturer = None
self._clear_selections() self._clear_selections()
self.category_selected.emit("Show All") self.category_selected.emit("Show All")
def _on_uncategorized_clicked(self) -> None: def _on_uncategorized_clicked(self) -> None:
self._active_category = None
self._active_manufacturer = None
self._clear_selections() self._clear_selections()
self.category_selected.emit(None) self.category_selected.emit(None)
def _on_category_clicked(self, index: QModelIndex) -> None: def _on_category_clicked(self, index: QModelIndex) -> None:
full_path = index.data(Qt.ItemDataRole.UserRole) full_path = index.data(Qt.ItemDataRole.UserRole)
if full_path: if full_path:
self._active_category = full_path
self._active_manufacturer = None
self._manufacturer_list.clearSelection() self._manufacturer_list.clearSelection()
self.category_selected.emit(full_path) self.category_selected.emit(full_path)
def _on_manufacturer_clicked(self, index: QModelIndex) -> None: def _on_manufacturer_clicked(self, index: QModelIndex) -> None:
manufacturer = index.data(Qt.ItemDataRole.DisplayRole) manufacturer = index.data(Qt.ItemDataRole.DisplayRole)
if manufacturer: if manufacturer:
self._active_manufacturer = manufacturer
self._active_category = None
self._category_tree.clearSelection() self._category_tree.clearSelection()
self.manufacturer_selected.emit(manufacturer) self.manufacturer_selected.emit(manufacturer)
@@ -431,26 +442,58 @@ class Sidebar(QWidget):
self._manufacturer_search.clear() self._manufacturer_search.clear()
def select_show_all(self) -> None: def select_show_all(self) -> None:
self._active_category = "Show All"
self._active_manufacturer = None
self._clear_selections() self._clear_selections()
self.category_selected.emit("Show All") self.category_selected.emit("Show All")
def select_uncategorized(self) -> None: def select_uncategorized(self) -> None:
self._active_category = None
self._active_manufacturer = None
self._clear_selections() self._clear_selections()
self._uncategorized.set_selected(True) self._uncategorized.set_selected(True)
self.category_selected.emit(None) self.category_selected.emit(None)
def focus_category_tree(self) -> None: def focus_category_tree(self) -> None:
self._category_tree.setFocus() self._category_tree.setFocus()
top_level_index = self._category_model.index_for_path("Top Level")
if top_level_index.isValid(): if self._active_category and self._active_category not in ("Show All", None):
self._category_tree.setCurrentIndex(top_level_index) target_path = self._active_category
else:
target_path = "Top Level"
target_index = self._category_model.index_for_path(target_path)
if target_index.isValid():
parent = target_index.parent()
while parent.isValid():
self._category_tree.expand(parent)
parent = parent.parent()
self._category_tree.selectionModel().setCurrentIndex(
target_index,
self._category_tree.selectionModel().SelectionFlag.ClearAndSelect,
)
def focus_manufacturer_list(self) -> None: def focus_manufacturer_list(self) -> None:
self._manufacturer_list.setFocus() self._manufacturer_list.setFocus()
if not self._manufacturer_list.selectionModel().hasSelection():
target_index = None
if self._active_manufacturer:
for row in range(self._manufacturer_proxy.rowCount()):
index = self._manufacturer_proxy.index(row, 0)
if index.data(Qt.ItemDataRole.DisplayRole) == self._active_manufacturer:
target_index = index
break
if target_index is None:
first_index = self._manufacturer_proxy.index(0, 0) first_index = self._manufacturer_proxy.index(0, 0)
if first_index.isValid(): if first_index.isValid():
self._manufacturer_list.setCurrentIndex(first_index) target_index = first_index
if target_index is not None:
self._manufacturer_list.selectionModel().setCurrentIndex(
target_index,
self._manufacturer_list.selectionModel().SelectionFlag.ClearAndSelect,
)
def _on_header_dragged(self, delta: int) -> None: def _on_header_dragged(self, delta: int) -> None:
sizes = self._splitter.sizes() sizes = self._splitter.sizes()
@@ -461,7 +504,10 @@ class Sidebar(QWidget):
def highlight_categories(self, category_paths: list[str]) -> None: def highlight_categories(self, category_paths: list[str]) -> None:
self._category_tree.clearSelection() self._category_tree.clearSelection()
if self._active_manufacturer is None:
self._manufacturer_list.clearSelection() self._manufacturer_list.clearSelection()
self._uncategorized.set_selected(False) self._uncategorized.set_selected(False)
if not category_paths: if not category_paths: