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