certflow.widgets.quick_search 源代码

"""可复用快查框控件(公共 widgets 模块)。

从 ``import_dialog.order_quick_search`` 与 ``FilterBar`` 内联快查框抽取为独立控件,
统一「editable + completer 模糊匹配」交互(§1.7 收益:导入快查框可复用到已导入库查询)。

与快查逻辑 :class:`certflow.widgets.quick_search_preset.QuickSearchPresetMixin` 同处
``widgets/`` 包,做到「控件 + 逻辑」语义聚拢。

设计要点:
- **数据源无关**:仅负责「去重候选项 → 模糊匹配 → 选中转发」交互,候选数据由宿主提供。
- **双信号(动态搜索模式切换)**:

  - ``typing``:用户在输入框键入(真实输入、非程序赋值)时发出,携带当前文本。
    驱动「模糊匹配模式」——下拉由 completer 做模糊初步筛选,宿主再做防抖的初步数据筛
    选。程序化的 ``set_items`` / ``setCurrentText`` 不会触发,避免噪声。
  - ``activated``:用户点击/回车**选中某个具体条目**时发出(对齐
    ``QComboBox.textActivated`` 的 QString 重载,避开 ``activated(int)`` 默认重载收到索引
    的坑),驱动「精确匹配模式」——按字段逐段精确回填并查询。
"""

from __future__ import annotations

from PySide6.QtCore import Qt, Signal
from PySide6.QtWidgets import QComboBox, QCompleter


[文档] class QuickSearch(QComboBox): """可编辑模糊匹配快查框。""" # 模糊模式:用户正在输入(候选下拉已做模糊匹配) typing = Signal(str) # 精确模式:用户选中了某个具体候选条目 activated = Signal(str) def __init__( self, parent=None, *, placeholder: str = "", min_width: int = 260, filter_mode=Qt.MatchContains, ) -> None: super().__init__(parent) self.setEditable(True) self.setMinimumWidth(min_width) if placeholder: self.setPlaceholderText(placeholder) self._filter_mode = filter_mode # 程序化改文本(填充候选项 / 清空输入)时不向宿主发 typing 信号 self._suppress_typing = False self.textActivated.connect(self._on_activated) self.currentTextChanged.connect(self._on_text_changed) # 回车确认:将当前输入作为一次显式查询请求(避免「边输入边查询」)。 # 与选中下拉候选(textActivated→activated)走同一确认路径;若文本恰好是候选 # 项则由 textActivated 负责发出,避免重复查询。 self.lineEdit().returnPressed.connect(self._on_return_pressed) def _on_activated(self, text: str) -> None: self.activated.emit(text) def _on_text_changed(self, text: str) -> None: # 仅对「真实用户输入」发模糊信号;选中条目时 textActivated 会随后触发精确模式 if self._suppress_typing: return self.typing.emit(text or "") def _on_return_pressed(self) -> None: text = self.currentText() # 当前文本正好是某个候选项时,textActivated 已会发出 activated,跳过以免重复查询 if self.findText(text) != -1: return self.activated.emit(text)
[文档] def set_items(self, items: list[str]) -> None: """填充候选项(editable + completer 模糊匹配),并清空当前输入。""" self._suppress_typing = True self.blockSignals(True) self.clear() self.addItems(items) self.setCurrentText("") self.blockSignals(False) self._suppress_typing = False completer = QCompleter(items) completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) completer.setFilterMode(self._filter_mode) self.setCompleter(completer)