Coverage for src / ezqt_widgets / widgets / input / auto_complete_input.py: 98.55%
65 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-31 10:03 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-31 10:03 +0000
1# ///////////////////////////////////////////////////////////////
2# AUTO_COMPLETE_INPUT - Auto-Complete Input Widget
3# Project: ezqt_widgets
4# ///////////////////////////////////////////////////////////////
6"""
7Auto-complete input widget module.
9Provides a QLineEdit subclass with autocompletion support for PySide6
10applications.
11"""
13from __future__ import annotations
15# ///////////////////////////////////////////////////////////////
16# IMPORTS
17# ///////////////////////////////////////////////////////////////
18# Standard library imports
19from typing import Any
21# Third-party imports
22from PySide6.QtCore import QStringListModel, Qt
23from PySide6.QtWidgets import QCompleter, QLineEdit
25# Local imports
26from ...types import WidgetParent
28# ///////////////////////////////////////////////////////////////
29# CLASSES
30# ///////////////////////////////////////////////////////////////
33class AutoCompleteInput(QLineEdit):
34 """QLineEdit subclass with autocompletion support.
36 Provides a text input widget with autocompletion functionality.
37 You can provide a list of suggestions (strings) to be used for
38 autocompletion.
40 Args:
41 parent: The parent widget (default: None).
42 suggestions: List of strings to use for autocompletion
43 (default: empty list).
44 case_sensitive: Whether the autocompletion is case sensitive
45 (default: False).
46 filter_mode: Filter mode for completion
47 (default: Qt.MatchFlag.MatchContains).
48 completion_mode: Completion mode
49 (default: QCompleter.CompletionMode.PopupCompletion).
50 *args: Additional arguments passed to QLineEdit.
51 **kwargs: Additional keyword arguments passed to QLineEdit.
53 Properties:
54 suggestions: Get or set the list of suggestions for autocompletion.
55 case_sensitive: Get or set whether autocompletion is case sensitive.
56 filter_mode: Get or set the filter mode for completion.
57 completion_mode: Get or set the completion mode.
59 Example:
60 >>> from ezqt_widgets import AutoCompleteInput
61 >>> inp = AutoCompleteInput(suggestions=["Alice", "Bob", "Charlie"])
62 >>> inp.case_sensitive = False
63 >>> inp.suggestions = ["Alice", "Bob", "Charlie", "Dave"]
64 >>> inp.show()
65 """
67 # ///////////////////////////////////////////////////////////////
68 # INIT
69 # ///////////////////////////////////////////////////////////////
71 def __init__(
72 self,
73 parent: WidgetParent = None,
74 suggestions: list[str] | None = None,
75 case_sensitive: bool = False,
76 filter_mode: Qt.MatchFlag = Qt.MatchFlag.MatchContains,
77 completion_mode: QCompleter.CompletionMode = QCompleter.CompletionMode.PopupCompletion,
78 *args: Any,
79 **kwargs: Any,
80 ) -> None:
81 """Initialize the auto-complete input."""
82 super().__init__(parent, *args, **kwargs)
84 # Initialize properties
85 self._suggestions: list[str] = suggestions or []
86 self._case_sensitive: bool = case_sensitive
87 self._filter_mode: Qt.MatchFlag = filter_mode
88 self._completion_mode: QCompleter.CompletionMode = completion_mode
90 # Setup completer
91 self._setup_completer()
93 # ------------------------------------------------
94 # PRIVATE METHODS
95 # ------------------------------------------------
97 def _setup_completer(self) -> None:
98 """Setup the completer with current settings."""
99 self._completer = QCompleter(self)
100 self._model = QStringListModel(self._suggestions, self)
102 # Configure completer
103 self._completer.setModel(self._model)
104 self._completer.setCaseSensitivity(
105 Qt.CaseSensitivity.CaseSensitive
106 if self._case_sensitive
107 else Qt.CaseSensitivity.CaseInsensitive
108 )
109 self._completer.setFilterMode(self._filter_mode)
110 self._completer.setCompletionMode(self._completion_mode)
111 self.setCompleter(self._completer)
113 # ///////////////////////////////////////////////////////////////
114 # PROPERTIES
115 # ///////////////////////////////////////////////////////////////
117 @property
118 def suggestions(self) -> list[str]:
119 """Get the list of suggestions.
121 Returns:
122 A copy of the current suggestions list.
123 """
124 return self._suggestions.copy()
126 @suggestions.setter
127 def suggestions(self, value: list[str]) -> None:
128 """Set the list of suggestions.
130 Args:
131 value: The new list of suggestions.
132 """
133 self._suggestions = value or []
134 self._model.setStringList(self._suggestions)
136 @property
137 def case_sensitive(self) -> bool:
138 """Get whether autocompletion is case sensitive.
140 Returns:
141 True if case sensitive, False otherwise.
142 """
143 return self._case_sensitive
145 @case_sensitive.setter
146 def case_sensitive(self, value: bool) -> None:
147 """Set whether autocompletion is case sensitive.
149 Args:
150 value: Whether to enable case sensitivity.
151 """
152 self._case_sensitive = bool(value)
153 self._completer.setCaseSensitivity(
154 Qt.CaseSensitivity.CaseSensitive
155 if self._case_sensitive
156 else Qt.CaseSensitivity.CaseInsensitive
157 )
159 @property
160 def filter_mode(self) -> Qt.MatchFlag:
161 """Get the filter mode for completion.
163 Returns:
164 The current filter mode.
165 """
166 return self._filter_mode
168 @filter_mode.setter
169 def filter_mode(self, value: Qt.MatchFlag) -> None:
170 """Set the filter mode for completion.
172 Args:
173 value: The new filter mode.
174 """
175 self._filter_mode = value
176 self._completer.setFilterMode(self._filter_mode)
178 @property
179 def completion_mode(self) -> QCompleter.CompletionMode:
180 """Get the completion mode.
182 Returns:
183 The current completion mode.
184 """
185 return self._completion_mode
187 @completion_mode.setter
188 def completion_mode(self, value: QCompleter.CompletionMode) -> None:
189 """Set the completion mode.
191 Args:
192 value: The new completion mode.
193 """
194 self._completion_mode = value
195 self._completer.setCompletionMode(self._completion_mode)
197 # ///////////////////////////////////////////////////////////////
198 # PUBLIC METHODS
199 # ///////////////////////////////////////////////////////////////
201 def addSuggestion(self, suggestion: str) -> None:
202 """Add a suggestion to the list.
204 Args:
205 suggestion: The suggestion string to add.
206 """
207 if suggestion and suggestion not in self._suggestions:
208 self._suggestions.append(suggestion)
209 self._model.setStringList(self._suggestions)
211 def removeSuggestion(self, suggestion: str) -> None:
212 """Remove a suggestion from the list.
214 Args:
215 suggestion: The suggestion string to remove.
216 """
217 if suggestion in self._suggestions: 217 ↛ exitline 217 didn't return from function 'removeSuggestion' because the condition on line 217 was always true
218 self._suggestions.remove(suggestion)
219 self._model.setStringList(self._suggestions)
221 def clearSuggestions(self) -> None:
222 """Clear all suggestions."""
223 self._suggestions.clear()
224 self._model.setStringList(self._suggestions)
226 # ///////////////////////////////////////////////////////////////
227 # STYLE METHODS
228 # ///////////////////////////////////////////////////////////////
230 def refreshStyle(self) -> None:
231 """Refresh the widget's style.
233 Useful after dynamic stylesheet changes.
234 """
235 self.style().unpolish(self)
236 self.style().polish(self)
237 self.update()
240# ///////////////////////////////////////////////////////////////
241# PUBLIC API
242# ///////////////////////////////////////////////////////////////
244__all__ = ["AutoCompleteInput"]