File indexing completed on 2024-05-12 15:33:59
0001 /* 0002 This file is part of the KDE libraries 0003 0004 SPDX-FileCopyrightText: 2000, 2001 Dawit Alemayehu <adawit@kde.org> 0005 SPDX-FileCopyrightText: 2000, 2001 Carsten Pfeiffer <pfeiffer@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.1-or-later 0008 */ 0009 0010 #ifndef KCOMBOBOX_H 0011 #define KCOMBOBOX_H 0012 0013 #include <kcompletion.h> 0014 0015 #include <kcompletion_export.h> 0016 #include <kcompletionbase.h> 0017 0018 #include <QComboBox> 0019 #include <memory> 0020 0021 class KCompletionBox; 0022 class KComboBoxPrivate; 0023 0024 class QLineEdit; 0025 class QMenu; 0026 0027 /** 0028 * @class KComboBox kcombobox.h KComboBox 0029 * 0030 * @short A combo box with completion support. 0031 * 0032 * This widget inherits from QComboBox and implements the following 0033 * additional features: 0034 * @li a completion object that provides both automatic 0035 * and manual text completion as well as text rotation 0036 * @li configurable key bindings to activate these features 0037 * @li a popup menu item that can be used to allow the user to change 0038 * the text completion mode on the fly. 0039 * 0040 * To support these additional features, KComboBox emits a few additional signals 0041 * such as completion(const QString&) and textRotation(KeyBindingType). 0042 * 0043 * The completion signal can be connected to a slot that will assist the user in 0044 * filling out the remaining text while the rotation signal can be used to traverse 0045 * through all possible matches whenever text completion results in multiple matches. 0046 * Additionally, the returnPressed(const QString &) signal is emitted when the user 0047 * presses the Return or Enter key. 0048 * 0049 * KCombobox by default creates a completion object when you invoke the 0050 * completionObject(bool) member function for the first time or 0051 * explicitly use setCompletionObject(KCompletion*, bool) to assign your 0052 * own completion object. Additionally, to make this widget more functional, 0053 * KComboBox will by default handle text rotation and completion events 0054 * internally whenever a completion object is created through either one of the 0055 * methods mentioned above. If you do not need this functionality, simply use 0056 * KCompletionBase::setHandleSignals(bool) or alternatively set the boolean 0057 * parameter in the @c setCompletionObject() call to @c false. 0058 * 0059 * Beware: The completion object can be deleted on you, especially if a call 0060 * such as setEditable(false) is made. Store the pointer at your own risk, 0061 * and consider using QPointer<KCompletion>. 0062 * 0063 * The default key bindings for completion and rotation are determined from the 0064 * global settings in KStandardShortcut. These values, however, can be overridden 0065 * locally by invoking KCompletionBase::setKeyBinding(). The values can 0066 * easily be reverted back to the default settings by calling 0067 * useGlobalSettings(). An alternate method would be to default individual 0068 * key bindings by using setKeyBinding() with the default second argument. 0069 * 0070 * A non-editable combo box only has one completion mode, @c CompletionAuto. 0071 * Unlike an editable combo box, the CompletionAuto mode works by matching 0072 * any typed key with the first letter of entries in the combo box. Please note 0073 * that if you call setEditable(false) to change an editable combo box to a 0074 * non-editable one, the text completion object associated with the combo box will 0075 * no longer exist unless you created the completion object yourself and assigned 0076 * it to this widget or you called setAutoDeleteCompletionObject(false). In other 0077 * words do not do the following: 0078 * 0079 * \code 0080 * KComboBox* combo = new KComboBox(true, this); 0081 * KCompletion* comp = combo->completionObject(); 0082 * combo->setEditable(false); 0083 * comp->clear(); // CRASH: completion object does not exist anymore. 0084 * \endcode 0085 * 0086 * 0087 * A read-only KComboBox will have the same background color as a 0088 * disabled KComboBox, but its foreground color will be the one used for 0089 * the editable mode. This differs from QComboBox's implementation 0090 * and is done to give visual distinction between the three different modes: 0091 * disabled, read-only, and editable. 0092 * 0093 * \b Usage 0094 * 0095 * To enable the basic completion feature: 0096 * 0097 * \code 0098 * KComboBox *combo = new KComboBox(true, this); 0099 * KCompletion *comp = combo->completionObject(); 0100 * // Connect to the Return pressed signal - optional 0101 * connect(combo, &KComboBox::returnPressed, comp, [this](const QString &text) { addItem(text); }); 0102 * 0103 * // Provide the to be completed strings. Note that those are separate from the combo's 0104 * // contents. 0105 * comp->insertItems(someQStringList); 0106 * \endcode 0107 * 0108 * To use your own completion object: 0109 * 0110 * \code 0111 * KComboBox *combo = new KComboBox(this); 0112 * KUrlCompletion *comp = new KUrlCompletion(); 0113 * // You can either delete the allocated completion object manually when you 0114 * // don't need it anymore, or call setAutoDeleteCompletionObject(true) and it 0115 * // will be deleted automatically 0116 * comp->setAutoDeleteCompletionObject(true); 0117 * combo->setCompletionObject(comp); 0118 * // Connect to the return pressed signal - optional 0119 * connect(combo, &KComboBox::returnPressed, comp, [this](const QString &text) { addItem(text); }); 0120 * \endcode 0121 * 0122 * Miscellaneous function calls: 0123 * 0124 * \code 0125 * // Tell the widget not to handle completion and rotation 0126 * combo->setHandleSignals(false); 0127 * // Set your own completion key for manual completions. 0128 * combo->setKeyBinding(KCompletionBase::TextCompletion, Qt::End); 0129 * \endcode 0130 * 0131 * \image html kcombobox.png "KComboBox widgets, one non-editable, one editable with KUrlCompletion" 0132 * 0133 * @author Dawit Alemayehu <adawit@kde.org> 0134 */ 0135 class KCOMPLETION_EXPORT KComboBox : public QComboBox, public KCompletionBase // krazy:exclude=qclasses 0136 { 0137 Q_OBJECT 0138 Q_PROPERTY(bool autoCompletion READ autoCompletion WRITE setAutoCompletion) 0139 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 0) 0140 Q_PROPERTY(bool urlDropsEnabled READ urlDropsEnabled WRITE setUrlDropsEnabled) 0141 #endif 0142 Q_PROPERTY(bool trapReturnKey READ trapReturnKey WRITE setTrapReturnKey) 0143 0144 public: 0145 /** 0146 * Constructs a read-only (or rather select-only) combo box. 0147 * 0148 * @param parent The parent object of this widget 0149 */ 0150 explicit KComboBox(QWidget *parent = nullptr); 0151 0152 /** 0153 * Constructs an editable or read-only combo box. 0154 * 0155 * @param rw When @c true, widget will be editable. 0156 * @param parent The parent object of this widget. 0157 */ 0158 explicit KComboBox(bool rw, QWidget *parent = nullptr); 0159 0160 /** 0161 * Destructor. 0162 */ 0163 ~KComboBox() override; 0164 0165 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5) 0166 /** 0167 * Deprecated to reflect Qt api changes 0168 * @deprecated since 4.5 0169 */ 0170 KCOMPLETION_DEPRECATED_VERSION(4, 5, "Use KComboBox::insertUrl(int, const QUrl&)") 0171 void insertURL(const QUrl &url, int index = -1) 0172 { 0173 insertUrl(index < 0 ? count() : index, url); 0174 } 0175 KCOMPLETION_DEPRECATED_VERSION(4, 5, "Use KComboBox::insertUrl(int, const QIcon&, const QUrl&)") 0176 void insertURL(const QPixmap &pixmap, const QUrl &url, int index = -1) 0177 { 0178 insertUrl(index < 0 ? count() : index, QIcon(pixmap), url); 0179 } 0180 KCOMPLETION_DEPRECATED_VERSION(4, 5, "Use KComboBox::changeUrl(int, const QUrl&)") 0181 void changeURL(const QUrl &url, int index) 0182 { 0183 changeUrl(index, url); 0184 } 0185 KCOMPLETION_DEPRECATED_VERSION(4, 5, "Use KComboBox::changeUrl(int, const QIcon&, const QUrl&)") 0186 void changeURL(const QPixmap &pixmap, const QUrl &url, int index) 0187 { 0188 changeUrl(index, QIcon(pixmap), url); 0189 } 0190 #endif 0191 0192 /** 0193 * Sets @p url into the edit field of the combo box. 0194 * 0195 * It uses QUrl::toDisplayString() so that the url is properly decoded for 0196 * displaying. 0197 */ 0198 void setEditUrl(const QUrl &url); 0199 0200 /** 0201 * Appends @p url to the combo box. 0202 * 0203 * QUrl::toDisplayString() is used so that the url is properly decoded 0204 * for displaying. 0205 */ 0206 void addUrl(const QUrl &url); 0207 0208 /** 0209 * Appends @p url with the @p icon to the combo box. 0210 * 0211 * QUrl::toDisplayString() is used so that the url is properly decoded 0212 * for displaying. 0213 */ 0214 void addUrl(const QIcon &icon, const QUrl &url); 0215 0216 /** 0217 * Inserts @p url at position @p index into the combo box. 0218 * 0219 * QUrl::toDisplayString() is used so that the url is properly decoded 0220 * for displaying. 0221 */ 0222 void insertUrl(int index, const QUrl &url); 0223 0224 /** 0225 * Inserts @p url with the @p icon at position @p index into 0226 * the combo box. 0227 * 0228 * QUrl::toDisplayString() is used so that the url is 0229 * properly decoded for displaying. 0230 */ 0231 void insertUrl(int index, const QIcon &icon, const QUrl &url); 0232 0233 /** 0234 * Replaces the item at position @p index with @p url. 0235 * 0236 * QUrl::toDisplayString() is used so that the url is properly decoded 0237 * for displaying. 0238 */ 0239 void changeUrl(int index, const QUrl &url); 0240 0241 /** 0242 * Replaces the item at position @p index with @p url and @p icon. 0243 * 0244 * QUrl::toDisplayString() is used so that the url is properly decoded 0245 * for displaying. 0246 */ 0247 void changeUrl(int index, const QIcon &icon, const QUrl &url); 0248 0249 /** 0250 * Returns the current cursor position. 0251 * 0252 * This method always returns a -1 if the combo box is @em not 0253 * editable (read-only). 0254 * 0255 * @return Current cursor position. 0256 */ 0257 int cursorPosition() const; 0258 0259 /** 0260 * Reimplemented from QComboBox. 0261 * 0262 * If @c true, the completion mode will be set to automatic. 0263 * Otherwise, it is defaulted to the global setting. This 0264 * method has been replaced by the more comprehensive 0265 * setCompletionMode(). 0266 * 0267 * @param autocomplete Flag to enable/disable automatic completion mode. 0268 */ 0269 virtual void setAutoCompletion(bool autocomplete); 0270 0271 /** 0272 * Reimplemented from QComboBox. 0273 * 0274 * Returns @c true if the current completion mode is set 0275 * to automatic. See its more comprehensive replacement 0276 * completionMode(). 0277 * 0278 * @return @c true when completion mode is automatic. 0279 */ 0280 bool autoCompletion() const; 0281 0282 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(4, 5) 0283 /** 0284 * Enables or disables the popup (context) menu. 0285 * 0286 * This method only works if this widget is editable, and 0287 * allows you to enable/disable the context menu. It does nothing if invoked 0288 * for a non-editable combo box. 0289 * 0290 * By default, the context menu is created if this widget is editable. 0291 * Call this function with the argument set to false to disable the popup 0292 * menu. 0293 * 0294 * @param showMenu If @c true, show the context menu. 0295 * @deprecated since 4.5, use setContextMenuPolicy instead 0296 */ 0297 KCOMPLETION_DEPRECATED_VERSION(4, 5, "Use QWidget::setContextMenuPolicy(...)") 0298 virtual void setContextMenuEnabled(bool showMenu); 0299 #endif 0300 0301 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(5, 0) 0302 /** 0303 * Enables/Disables handling of URL drops. 0304 * 0305 * If enabled and the user drops an URL, the decoded URL will 0306 * be inserted. Otherwise the default behavior of QComboBox is used, 0307 * which inserts the encoded URL. 0308 * 0309 * @param enable If @c true, insert decoded URLs 0310 * @deprecated since 5.0. Use lineEdit()->installEventFilter with a LineEditUrlDropEventFilter 0311 */ 0312 KCOMPLETION_DEPRECATED_VERSION(5, 0, "Use KComboBox::lineEdit()->installEventFilter(...) with a LineEditUrlDropEventFilter") 0313 void setUrlDropsEnabled(bool enable); 0314 #endif 0315 0316 /** 0317 * Returns @c true when decoded URL drops are enabled 0318 */ 0319 bool urlDropsEnabled() const; 0320 0321 /** 0322 * Convenience method which iterates over all items and checks if 0323 * any of them is equal to @p text. 0324 * 0325 * If @p text is an empty string, @c false 0326 * is returned. 0327 * 0328 * @return @c true if an item with the string @p text is in the combo box. 0329 */ 0330 bool contains(const QString &text) const; 0331 0332 /** 0333 * By default, KComboBox recognizes Key_Return and Key_Enter and emits the 0334 * returnPressed(const QString &) signal, but it also lets the event pass, 0335 * for example causing a dialog's default button to be called. 0336 * 0337 * Call this method with @p trap set to true to make KComboBox stop these 0338 * events. The signals will still be emitted of course. 0339 * 0340 * @note This only affects editable combo boxes. 0341 * 0342 * @see setTrapReturnKey() 0343 */ 0344 void setTrapReturnKey(bool trap); 0345 0346 /** 0347 * @return @c true if Key_Return or Key_Enter input events will be stopped or 0348 * @c false if they will be propagated. 0349 * 0350 * @see setTrapReturnKey() 0351 */ 0352 bool trapReturnKey() const; 0353 0354 /** 0355 * This method will create a completion box by calling 0356 * KLineEdit::completionBox, if none is there yet. 0357 * 0358 * @param create Set this to false if you don't want the box to be created 0359 * i.e. to test if it is available. 0360 * @returns the completion box that is used in completion mode 0361 * CompletionPopup and CompletionPopupAuto. 0362 */ 0363 KCompletionBox *completionBox(bool create = true); 0364 0365 /** 0366 * Reimplemented for internal reasons. API remains unaffected. 0367 * Note that QComboBox::setLineEdit is not virtual in Qt4, do not 0368 * use a KComboBox in a QComboBox pointer. 0369 * 0370 * NOTE: Only editable combo boxes can have a line editor. As such 0371 * any attempt to assign a line edit to a non-editable combo box will 0372 * simply be ignored. 0373 */ 0374 virtual void setLineEdit(QLineEdit *); 0375 0376 /** 0377 * Reimplemented so that setEditable(true) creates a KLineEdit 0378 * instead of QLineEdit. 0379 * 0380 * Note that QComboBox::setEditable is not virtual, so do not 0381 * use a KComboBox in a QComboBox pointer. 0382 */ 0383 void setEditable(bool editable); 0384 0385 /** 0386 * Pointer to KLineEdit's context menu, or nullptr if it does not exist at 0387 * the given moment. 0388 * 0389 * @since 5.78 0390 */ 0391 QMenu *contextMenu() const; 0392 0393 Q_SIGNALS: 0394 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(5, 81) 0395 /** 0396 * Emitted when the user presses the Enter key. 0397 * 0398 * Note that this signal is only emitted when the widget is editable. 0399 * 0400 * @deprecated since 5.81, use the KComboBox::returnPressed(const QString &) signal 0401 */ 0402 KCOMPLETION_DEPRECATED_VERSION(5, 81, "Use the KComboBox::returnPressed(const QString &) signal instead") 0403 void returnPressed(); // clazy:exclude=overloaded-signal 0404 #endif 0405 0406 /** 0407 * Emitted when the user presses the Return or Enter key. 0408 * 0409 * The argument is the current text being edited. 0410 * 0411 * @note This signal is only emitted when the widget is editable. 0412 * 0413 */ 0414 void returnPressed(const QString &text); // clazy:exclude=overloaded-signal 0415 0416 /** 0417 * Emitted when the completion key is pressed. 0418 * 0419 * The argument is the current text being edited. 0420 * 0421 * Note that this signal is @em not available when the widget is non-editable 0422 * or the completion mode is set to @c CompletionNone. 0423 */ 0424 void completion(const QString &); 0425 0426 /** 0427 * Emitted when the shortcut for substring completion is pressed. 0428 */ 0429 void substringCompletion(const QString &); 0430 0431 /** 0432 * Emitted when the text rotation key bindings are pressed. 0433 * 0434 * The argument indicates which key binding was pressed. In this case this 0435 * can be either one of four values: @c PrevCompletionMatch, 0436 * @c NextCompletionMatch, @c RotateUp or @c RotateDown. 0437 * 0438 * Note that this signal is @em not emitted if the completion 0439 * mode is set to CompletionNone. 0440 * 0441 * @see KCompletionBase::setKeyBinding() for details 0442 */ 0443 void textRotation(KCompletionBase::KeyBindingType); 0444 0445 /** 0446 * Emitted whenever the completion mode is changed by the user 0447 * through the context menu. 0448 */ 0449 void completionModeChanged(KCompletion::CompletionMode); 0450 0451 /** 0452 * Emitted before the context menu is displayed. 0453 * 0454 * The signal allows you to add your own entries into the context menu. 0455 * Note that you <em>must not</em> store the pointer to the QPopupMenu since it is 0456 * created and deleted on demand. Otherwise, you can crash your app. 0457 * 0458 * @param contextMenu the context menu about to be displayed 0459 */ 0460 void aboutToShowContextMenu(QMenu *contextMenu); 0461 0462 public Q_SLOTS: 0463 0464 /** 0465 * Iterates through all possible matches of the completed text 0466 * or the history list. 0467 * 0468 * Depending on the value of the argument, this function either 0469 * iterates through the history list of this widget or all the 0470 * possible matches in whenever multiple matches result from a 0471 * text completion request. Note that the all-possible-match 0472 * iteration will not work if there are no previous matches, i.e. 0473 * no text has been completed and the *nix shell history list 0474 * rotation is only available if the insertion policy for this 0475 * widget is set either @c QComobBox::AtTop or @c QComboBox::AtBottom. 0476 * For other insertion modes whatever has been typed by the user 0477 * when the rotation event was initiated will be lost. 0478 * 0479 * @param type The key binding invoked. 0480 */ 0481 void rotateText(KCompletionBase::KeyBindingType type); 0482 0483 /** 0484 * Sets the completed text in the line edit appropriately. 0485 * 0486 * This function is an implementation for 0487 * KCompletionBase::setCompletedText. 0488 */ 0489 void setCompletedText(const QString &) override; 0490 0491 /** 0492 * Sets @p items into the completion box if completionMode() is 0493 * CompletionPopup. The popup will be shown immediately. 0494 */ 0495 void setCompletedItems(const QStringList &items, bool autoSuggest = true) override; 0496 0497 /** 0498 * Selects the first item that matches @p item. 0499 * 0500 * If there is no such item, it is inserted at position @p index 0501 * if @p insert is true. Otherwise, no item is selected. 0502 */ 0503 void setCurrentItem(const QString &item, bool insert = false, int index = -1); 0504 0505 protected Q_SLOTS: 0506 0507 /** 0508 * Completes text according to the completion mode. 0509 * 0510 * @note This method is not invoked if the completion mode is 0511 * set to @c CompletionNone. Also if the mode is set to @c CompletionShell 0512 * and multiple matches are found, this method will complete the 0513 * text to the first match with a beep to indicate that there are 0514 * more matches. Then any successive completion key event iterates 0515 * through the remaining matches. This way the rotation functionality 0516 * is left to iterate through the list as usual. 0517 */ 0518 virtual void makeCompletion(const QString &); 0519 0520 protected: 0521 /** 0522 * This function sets the line edit text and 0523 * highlights the text appropriately if the boolean 0524 * value is set to true. 0525 * 0526 * @param text The text to be set in the line edit 0527 * @param marked Whether the text inserted should be highlighted 0528 */ 0529 virtual void setCompletedText(const QString &text, bool marked); 0530 0531 // TODO KF6: make public like in base classes, so consumers do not need to cast to base classes 0532 // when they have a KComboBox (or subclasses) object and want to access this property 0533 QSize minimumSizeHint() const override; 0534 0535 protected: 0536 KCOMPLETION_NO_EXPORT KComboBox(KComboBoxPrivate &dd, QWidget *parent); 0537 0538 private: 0539 friend class KHistoryComboBox; 0540 Q_DECLARE_PRIVATE(KComboBox) 0541 std::unique_ptr<KComboBoxPrivate> const d_ptr; 0542 // KF6 TODO: change private d_ptr to protected d_ptr, remove friend 0543 }; 0544 0545 #endif