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
21class KCompletionBox;
22class KComboBoxPrivate;
23
24class QLineEdit;
25class QMenu;
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 */
136class 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
150public:
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 *contextMenu() const;
331
332 QSize minimumSizeHint() const override;
333
334Q_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 aboutToShowContextMenu(QMenu *contextMenu);
390
391public 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
434protected 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
449protected:
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
461protected:
462 KCOMPLETION_NO_EXPORT KComboBox(KComboBoxPrivate &dd, QWidget *parent);
463
464protected:
465 std::unique_ptr<KComboBoxPrivate> const d_ptr;
466
467private:
468 Q_DECLARE_PRIVATE(KComboBox)
469};
470
471#endif
472

source code of kcompletion/src/kcombobox.h