1 | /* |
2 | This file is part of the KDE libraries |
3 | |
4 | SPDX-FileCopyrightText: 2000, 2001 Dawit Alemayehu <adawit@kde.org> |
5 | SPDX-FileCopyrightText: 2000, 2001 Carsten Pfeiffer <pfeiffer@kde.org> |
6 | |
7 | SPDX-License-Identifier: LGPL-2.1-or-later |
8 | */ |
9 | |
10 | #ifndef KCOMBOBOX_H |
11 | #define KCOMBOBOX_H |
12 | |
13 | #include <kcompletion.h> |
14 | |
15 | #include <kcompletion_export.h> |
16 | #include <kcompletionbase.h> |
17 | |
18 | #include <QComboBox> |
19 | #include <memory> |
20 | |
21 | class KCompletionBox; |
22 | class KComboBoxPrivate; |
23 | |
24 | class QLineEdit; |
25 | class ; |
26 | |
27 | /** |
28 | * @class KComboBox kcombobox.h KComboBox |
29 | * |
30 | * @short A combo box with completion support. |
31 | * |
32 | * This widget inherits from QComboBox and implements the following |
33 | * additional features: |
34 | * @li a completion object that provides both automatic |
35 | * and manual text completion as well as text rotation |
36 | * @li configurable key bindings to activate these features |
37 | * @li a popup menu item that can be used to allow the user to change |
38 | * the text completion mode on the fly. |
39 | * |
40 | * To support these additional features, KComboBox emits a few additional signals |
41 | * such as completion(const QString&) and textRotation(KeyBindingType). |
42 | * |
43 | * The completion signal can be connected to a slot that will assist the user in |
44 | * filling out the remaining text while the rotation signal can be used to traverse |
45 | * through all possible matches whenever text completion results in multiple matches. |
46 | * Additionally, the returnPressed(const QString &) signal is emitted when the user |
47 | * presses the Return or Enter key. |
48 | * |
49 | * KCombobox by default creates a completion object when you invoke the |
50 | * completionObject(bool) member function for the first time or |
51 | * explicitly use setCompletionObject(KCompletion*, bool) to assign your |
52 | * own completion object. Additionally, to make this widget more functional, |
53 | * KComboBox will by default handle text rotation and completion events |
54 | * internally whenever a completion object is created through either one of the |
55 | * methods mentioned above. If you do not need this functionality, simply use |
56 | * KCompletionBase::setHandleSignals(bool) or alternatively set the boolean |
57 | * parameter in the @c setCompletionObject() call to @c false. |
58 | * |
59 | * Beware: The completion object can be deleted on you, especially if a call |
60 | * such as setEditable(false) is made. Store the pointer at your own risk, |
61 | * and consider using QPointer<KCompletion>. |
62 | * |
63 | * The default key bindings for completion and rotation are determined from the |
64 | * global settings in KStandardShortcut. These values, however, can be overridden |
65 | * locally by invoking KCompletionBase::setKeyBinding(). The values can |
66 | * easily be reverted back to the default settings by calling |
67 | * useGlobalSettings(). An alternate method would be to default individual |
68 | * key bindings by using setKeyBinding() with the default second argument. |
69 | * |
70 | * A non-editable combo box only has one completion mode, @c CompletionAuto. |
71 | * Unlike an editable combo box, the CompletionAuto mode works by matching |
72 | * any typed key with the first letter of entries in the combo box. Please note |
73 | * that if you call setEditable(false) to change an editable combo box to a |
74 | * non-editable one, the text completion object associated with the combo box will |
75 | * no longer exist unless you created the completion object yourself and assigned |
76 | * it to this widget or you called setAutoDeleteCompletionObject(false). In other |
77 | * words do not do the following: |
78 | * |
79 | * \code |
80 | * KComboBox* combo = new KComboBox(true, this); |
81 | * KCompletion* comp = combo->completionObject(); |
82 | * combo->setEditable(false); |
83 | * comp->clear(); // CRASH: completion object does not exist anymore. |
84 | * \endcode |
85 | * |
86 | * |
87 | * A read-only KComboBox will have the same background color as a |
88 | * disabled KComboBox, but its foreground color will be the one used for |
89 | * the editable mode. This differs from QComboBox's implementation |
90 | * and is done to give visual distinction between the three different modes: |
91 | * disabled, read-only, and editable. |
92 | * |
93 | * \b Usage |
94 | * |
95 | * To enable the basic completion feature: |
96 | * |
97 | * \code |
98 | * KComboBox *combo = new KComboBox(true, this); |
99 | * KCompletion *comp = combo->completionObject(); |
100 | * // Connect to the Return pressed signal - optional |
101 | * connect(combo, &KComboBox::returnPressed, comp, [this](const QString &text) { addItem(text); }); |
102 | * |
103 | * // Provide the to be completed strings. Note that those are separate from the combo's |
104 | * // contents. |
105 | * comp->insertItems(someQStringList); |
106 | * \endcode |
107 | * |
108 | * To use your own completion object: |
109 | * |
110 | * \code |
111 | * KComboBox *combo = new KComboBox(this); |
112 | * KUrlCompletion *comp = new KUrlCompletion(); |
113 | * // You can either delete the allocated completion object manually when you |
114 | * // don't need it anymore, or call setAutoDeleteCompletionObject(true) and it |
115 | * // will be deleted automatically |
116 | * comp->setAutoDeleteCompletionObject(true); |
117 | * combo->setCompletionObject(comp); |
118 | * // Connect to the return pressed signal - optional |
119 | * connect(combo, &KComboBox::returnPressed, comp, [this](const QString &text) { addItem(text); }); |
120 | * \endcode |
121 | * |
122 | * Miscellaneous function calls: |
123 | * |
124 | * \code |
125 | * // Tell the widget not to handle completion and rotation |
126 | * combo->setHandleSignals(false); |
127 | * // Set your own completion key for manual completions. |
128 | * combo->setKeyBinding(KCompletionBase::TextCompletion, Qt::End); |
129 | * \endcode |
130 | * |
131 | * \image html kcombobox.png "KComboBox widgets, one non-editable, one editable with KUrlCompletion" |
132 | * |
133 | * @author Dawit Alemayehu <adawit@kde.org> |
134 | */ |
135 | class KCOMPLETION_EXPORT KComboBox : public QComboBox, public KCompletionBase // krazy:exclude=qclasses |
136 | { |
137 | Q_OBJECT |
138 | Q_PROPERTY(bool autoCompletion READ autoCompletion WRITE setAutoCompletion) |
139 | Q_PROPERTY(bool trapReturnKey READ trapReturnKey WRITE setTrapReturnKey) |
140 | |
141 | public: |
142 | /** |
143 | * Constructs a read-only (or rather select-only) combo box. |
144 | * |
145 | * @param parent The parent object of this widget |
146 | */ |
147 | explicit KComboBox(QWidget *parent = nullptr); |
148 | |
149 | /** |
150 | * Constructs an editable or read-only combo box. |
151 | * |
152 | * @param rw When @c true, widget will be editable. |
153 | * @param parent The parent object of this widget. |
154 | */ |
155 | explicit KComboBox(bool rw, QWidget *parent = nullptr); |
156 | |
157 | /** |
158 | * Destructor. |
159 | */ |
160 | ~KComboBox() override; |
161 | |
162 | /** |
163 | * Sets @p url into the edit field of the combo box. |
164 | * |
165 | * It uses QUrl::toDisplayString() so that the url is properly decoded for |
166 | * displaying. |
167 | */ |
168 | void setEditUrl(const QUrl &url); |
169 | |
170 | /** |
171 | * Appends @p url to the combo box. |
172 | * |
173 | * QUrl::toDisplayString() is used so that the url is properly decoded |
174 | * for displaying. |
175 | */ |
176 | void addUrl(const QUrl &url); |
177 | |
178 | /** |
179 | * Appends @p url with the @p icon to the combo box. |
180 | * |
181 | * QUrl::toDisplayString() is used so that the url is properly decoded |
182 | * for displaying. |
183 | */ |
184 | void addUrl(const QIcon &icon, const QUrl &url); |
185 | |
186 | /** |
187 | * Inserts @p url at position @p index into the combo box. |
188 | * |
189 | * QUrl::toDisplayString() is used so that the url is properly decoded |
190 | * for displaying. |
191 | */ |
192 | void insertUrl(int index, const QUrl &url); |
193 | |
194 | /** |
195 | * Inserts @p url with the @p icon at position @p index into |
196 | * the combo box. |
197 | * |
198 | * QUrl::toDisplayString() is used so that the url is |
199 | * properly decoded for displaying. |
200 | */ |
201 | void insertUrl(int index, const QIcon &icon, const QUrl &url); |
202 | |
203 | /** |
204 | * Replaces the item at position @p index with @p url. |
205 | * |
206 | * QUrl::toDisplayString() is used so that the url is properly decoded |
207 | * for displaying. |
208 | */ |
209 | void changeUrl(int index, const QUrl &url); |
210 | |
211 | /** |
212 | * Replaces the item at position @p index with @p url and @p icon. |
213 | * |
214 | * QUrl::toDisplayString() is used so that the url is properly decoded |
215 | * for displaying. |
216 | */ |
217 | void changeUrl(int index, const QIcon &icon, const QUrl &url); |
218 | |
219 | /** |
220 | * Returns the current cursor position. |
221 | * |
222 | * This method always returns a -1 if the combo box is @em not |
223 | * editable (read-only). |
224 | * |
225 | * @return Current cursor position. |
226 | */ |
227 | int cursorPosition() const; |
228 | |
229 | /** |
230 | * Reimplemented from QComboBox. |
231 | * |
232 | * If @c true, the completion mode will be set to automatic. |
233 | * Otherwise, it is defaulted to the global setting. This |
234 | * method has been replaced by the more comprehensive |
235 | * setCompletionMode(). |
236 | * |
237 | * @param autocomplete Flag to enable/disable automatic completion mode. |
238 | */ |
239 | virtual void setAutoCompletion(bool autocomplete); |
240 | |
241 | /** |
242 | * Reimplemented from QComboBox. |
243 | * |
244 | * Returns @c true if the current completion mode is set |
245 | * to automatic. See its more comprehensive replacement |
246 | * completionMode(). |
247 | * |
248 | * @return @c true when completion mode is automatic. |
249 | */ |
250 | bool autoCompletion() const; |
251 | |
252 | /** |
253 | * Returns @c true when decoded URL drops are enabled |
254 | */ |
255 | bool urlDropsEnabled() const; |
256 | |
257 | /** |
258 | * Convenience method which iterates over all items and checks if |
259 | * any of them is equal to @p text. |
260 | * |
261 | * If @p text is an empty string, @c false |
262 | * is returned. |
263 | * |
264 | * @return @c true if an item with the string @p text is in the combo box. |
265 | */ |
266 | bool contains(const QString &text) const; |
267 | |
268 | /** |
269 | * By default, KComboBox recognizes Key_Return and Key_Enter and emits the |
270 | * returnPressed(const QString &) signal, but it also lets the event pass, |
271 | * for example causing a dialog's default button to be called. |
272 | * |
273 | * Call this method with @p trap set to true to make KComboBox stop these |
274 | * events. The signals will still be emitted of course. |
275 | * |
276 | * @note This only affects editable combo boxes. |
277 | * |
278 | * @see setTrapReturnKey() |
279 | */ |
280 | void setTrapReturnKey(bool trap); |
281 | |
282 | /** |
283 | * @return @c true if Key_Return or Key_Enter input events will be stopped or |
284 | * @c false if they will be propagated. |
285 | * |
286 | * @see setTrapReturnKey() |
287 | */ |
288 | bool trapReturnKey() const; |
289 | |
290 | /** |
291 | * This method will create a completion box by calling |
292 | * KLineEdit::completionBox, if none is there yet. |
293 | * |
294 | * @param create Set this to false if you don't want the box to be created |
295 | * i.e. to test if it is available. |
296 | * @returns the completion box that is used in completion mode |
297 | * CompletionPopup and CompletionPopupAuto. |
298 | */ |
299 | KCompletionBox *completionBox(bool create = true); |
300 | |
301 | /** |
302 | * Reimplemented for internal reasons. API remains unaffected. |
303 | * Note that QComboBox::setLineEdit is not virtual in Qt4, do not |
304 | * use a KComboBox in a QComboBox pointer. |
305 | * |
306 | * NOTE: Only editable combo boxes can have a line editor. As such |
307 | * any attempt to assign a line edit to a non-editable combo box will |
308 | * simply be ignored. |
309 | */ |
310 | virtual void setLineEdit(QLineEdit *); |
311 | |
312 | /** |
313 | * Reimplemented so that setEditable(true) creates a KLineEdit |
314 | * instead of QLineEdit. |
315 | * |
316 | * Note that QComboBox::setEditable is not virtual, so do not |
317 | * use a KComboBox in a QComboBox pointer. |
318 | */ |
319 | void setEditable(bool editable); |
320 | |
321 | /** |
322 | * Pointer to KLineEdit's context menu, or nullptr if it does not exist at |
323 | * the given moment. |
324 | * |
325 | * @since 5.78 |
326 | */ |
327 | QMenu *() const; |
328 | |
329 | QSize minimumSizeHint() const override; |
330 | |
331 | Q_SIGNALS: |
332 | /** |
333 | * Emitted when the user presses the Return or Enter key. |
334 | * |
335 | * The argument is the current text being edited. |
336 | * |
337 | * @note This signal is only emitted when the widget is editable. |
338 | * |
339 | */ |
340 | void returnPressed(const QString &text); // clazy:exclude=overloaded-signal |
341 | |
342 | /** |
343 | * Emitted when the completion key is pressed. |
344 | * |
345 | * The argument is the current text being edited. |
346 | * |
347 | * Note that this signal is @em not available when the widget is non-editable |
348 | * or the completion mode is set to @c CompletionNone. |
349 | */ |
350 | void completion(const QString &); |
351 | |
352 | /** |
353 | * Emitted when the shortcut for substring completion is pressed. |
354 | */ |
355 | void substringCompletion(const QString &); |
356 | |
357 | /** |
358 | * Emitted when the text rotation key bindings are pressed. |
359 | * |
360 | * The argument indicates which key binding was pressed. In this case this |
361 | * can be either one of four values: @c PrevCompletionMatch, |
362 | * @c NextCompletionMatch, @c RotateUp or @c RotateDown. |
363 | * |
364 | * Note that this signal is @em not emitted if the completion |
365 | * mode is set to CompletionNone. |
366 | * |
367 | * @see KCompletionBase::setKeyBinding() for details |
368 | */ |
369 | void textRotation(KCompletionBase::KeyBindingType); |
370 | |
371 | /** |
372 | * Emitted whenever the completion mode is changed by the user |
373 | * through the context menu. |
374 | */ |
375 | void completionModeChanged(KCompletion::CompletionMode); |
376 | |
377 | /** |
378 | * Emitted before the context menu is displayed. |
379 | * |
380 | * The signal allows you to add your own entries into the context menu. |
381 | * Note that you <em>must not</em> store the pointer to the QPopupMenu since it is |
382 | * created and deleted on demand. Otherwise, you can crash your app. |
383 | * |
384 | * @param contextMenu the context menu about to be displayed |
385 | */ |
386 | void (QMenu *); |
387 | |
388 | public Q_SLOTS: |
389 | |
390 | /** |
391 | * Iterates through all possible matches of the completed text |
392 | * or the history list. |
393 | * |
394 | * Depending on the value of the argument, this function either |
395 | * iterates through the history list of this widget or all the |
396 | * possible matches in whenever multiple matches result from a |
397 | * text completion request. Note that the all-possible-match |
398 | * iteration will not work if there are no previous matches, i.e. |
399 | * no text has been completed and the *nix shell history list |
400 | * rotation is only available if the insertion policy for this |
401 | * widget is set either @c QComobBox::AtTop or @c QComboBox::AtBottom. |
402 | * For other insertion modes whatever has been typed by the user |
403 | * when the rotation event was initiated will be lost. |
404 | * |
405 | * @param type The key binding invoked. |
406 | */ |
407 | void rotateText(KCompletionBase::KeyBindingType type); |
408 | |
409 | /** |
410 | * Sets the completed text in the line edit appropriately. |
411 | * |
412 | * This function is an implementation for |
413 | * KCompletionBase::setCompletedText. |
414 | */ |
415 | void setCompletedText(const QString &) override; |
416 | |
417 | /** |
418 | * Sets @p items into the completion box if completionMode() is |
419 | * CompletionPopup. The popup will be shown immediately. |
420 | */ |
421 | void setCompletedItems(const QStringList &items, bool autoSuggest = true) override; |
422 | |
423 | /** |
424 | * Selects the first item that matches @p item. |
425 | * |
426 | * If there is no such item, it is inserted at position @p index |
427 | * if @p insert is true. Otherwise, no item is selected. |
428 | */ |
429 | void setCurrentItem(const QString &item, bool insert = false, int index = -1); |
430 | |
431 | protected Q_SLOTS: |
432 | |
433 | /** |
434 | * Completes text according to the completion mode. |
435 | * |
436 | * @note This method is not invoked if the completion mode is |
437 | * set to @c CompletionNone. Also if the mode is set to @c CompletionShell |
438 | * and multiple matches are found, this method will complete the |
439 | * text to the first match with a beep to indicate that there are |
440 | * more matches. Then any successive completion key event iterates |
441 | * through the remaining matches. This way the rotation functionality |
442 | * is left to iterate through the list as usual. |
443 | */ |
444 | virtual void makeCompletion(const QString &); |
445 | |
446 | protected: |
447 | /** |
448 | * This function sets the line edit text and |
449 | * highlights the text appropriately if the boolean |
450 | * value is set to true. |
451 | * |
452 | * @param text The text to be set in the line edit |
453 | * @param marked Whether the text inserted should be highlighted |
454 | */ |
455 | virtual void setCompletedText(const QString &text, bool marked); |
456 | |
457 | protected: |
458 | KCOMPLETION_NO_EXPORT KComboBox(KComboBoxPrivate &dd, QWidget *parent); |
459 | |
460 | protected: |
461 | std::unique_ptr<KComboBoxPrivate> const d_ptr; |
462 | |
463 | private: |
464 | Q_DECLARE_PRIVATE(KComboBox) |
465 | }; |
466 | |
467 | #endif |
468 | |