File indexing completed on 2024-04-28 03:53:08
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 Q_PROPERTY(bool trapReturnKey READ trapReturnKey WRITE setTrapReturnKey) 0140 0141 public: 0142 /** 0143 * Constructs a read-only (or rather select-only) combo box. 0144 * 0145 * @param parent The parent object of this widget 0146 */ 0147 explicit KComboBox(QWidget *parent = nullptr); 0148 0149 /** 0150 * Constructs an editable or read-only combo box. 0151 * 0152 * @param rw When @c true, widget will be editable. 0153 * @param parent The parent object of this widget. 0154 */ 0155 explicit KComboBox(bool rw, QWidget *parent = nullptr); 0156 0157 /** 0158 * Destructor. 0159 */ 0160 ~KComboBox() override; 0161 0162 /** 0163 * Sets @p url into the edit field of the combo box. 0164 * 0165 * It uses QUrl::toDisplayString() so that the url is properly decoded for 0166 * displaying. 0167 */ 0168 void setEditUrl(const QUrl &url); 0169 0170 /** 0171 * Appends @p url to the combo box. 0172 * 0173 * QUrl::toDisplayString() is used so that the url is properly decoded 0174 * for displaying. 0175 */ 0176 void addUrl(const QUrl &url); 0177 0178 /** 0179 * Appends @p url with the @p icon to the combo box. 0180 * 0181 * QUrl::toDisplayString() is used so that the url is properly decoded 0182 * for displaying. 0183 */ 0184 void addUrl(const QIcon &icon, const QUrl &url); 0185 0186 /** 0187 * Inserts @p url at position @p index into the combo box. 0188 * 0189 * QUrl::toDisplayString() is used so that the url is properly decoded 0190 * for displaying. 0191 */ 0192 void insertUrl(int index, const QUrl &url); 0193 0194 /** 0195 * Inserts @p url with the @p icon at position @p index into 0196 * the combo box. 0197 * 0198 * QUrl::toDisplayString() is used so that the url is 0199 * properly decoded for displaying. 0200 */ 0201 void insertUrl(int index, const QIcon &icon, const QUrl &url); 0202 0203 /** 0204 * Replaces the item at position @p index with @p url. 0205 * 0206 * QUrl::toDisplayString() is used so that the url is properly decoded 0207 * for displaying. 0208 */ 0209 void changeUrl(int index, const QUrl &url); 0210 0211 /** 0212 * Replaces the item at position @p index with @p url and @p icon. 0213 * 0214 * QUrl::toDisplayString() is used so that the url is properly decoded 0215 * for displaying. 0216 */ 0217 void changeUrl(int index, const QIcon &icon, const QUrl &url); 0218 0219 /** 0220 * Returns the current cursor position. 0221 * 0222 * This method always returns a -1 if the combo box is @em not 0223 * editable (read-only). 0224 * 0225 * @return Current cursor position. 0226 */ 0227 int cursorPosition() const; 0228 0229 /** 0230 * Reimplemented from QComboBox. 0231 * 0232 * If @c true, the completion mode will be set to automatic. 0233 * Otherwise, it is defaulted to the global setting. This 0234 * method has been replaced by the more comprehensive 0235 * setCompletionMode(). 0236 * 0237 * @param autocomplete Flag to enable/disable automatic completion mode. 0238 */ 0239 virtual void setAutoCompletion(bool autocomplete); 0240 0241 /** 0242 * Reimplemented from QComboBox. 0243 * 0244 * Returns @c true if the current completion mode is set 0245 * to automatic. See its more comprehensive replacement 0246 * completionMode(). 0247 * 0248 * @return @c true when completion mode is automatic. 0249 */ 0250 bool autoCompletion() const; 0251 0252 /** 0253 * Returns @c true when decoded URL drops are enabled 0254 */ 0255 bool urlDropsEnabled() const; 0256 0257 /** 0258 * Convenience method which iterates over all items and checks if 0259 * any of them is equal to @p text. 0260 * 0261 * If @p text is an empty string, @c false 0262 * is returned. 0263 * 0264 * @return @c true if an item with the string @p text is in the combo box. 0265 */ 0266 bool contains(const QString &text) const; 0267 0268 /** 0269 * By default, KComboBox recognizes Key_Return and Key_Enter and emits the 0270 * returnPressed(const QString &) signal, but it also lets the event pass, 0271 * for example causing a dialog's default button to be called. 0272 * 0273 * Call this method with @p trap set to true to make KComboBox stop these 0274 * events. The signals will still be emitted of course. 0275 * 0276 * @note This only affects editable combo boxes. 0277 * 0278 * @see setTrapReturnKey() 0279 */ 0280 void setTrapReturnKey(bool trap); 0281 0282 /** 0283 * @return @c true if Key_Return or Key_Enter input events will be stopped or 0284 * @c false if they will be propagated. 0285 * 0286 * @see setTrapReturnKey() 0287 */ 0288 bool trapReturnKey() const; 0289 0290 /** 0291 * This method will create a completion box by calling 0292 * KLineEdit::completionBox, if none is there yet. 0293 * 0294 * @param create Set this to false if you don't want the box to be created 0295 * i.e. to test if it is available. 0296 * @returns the completion box that is used in completion mode 0297 * CompletionPopup and CompletionPopupAuto. 0298 */ 0299 KCompletionBox *completionBox(bool create = true); 0300 0301 /** 0302 * Reimplemented for internal reasons. API remains unaffected. 0303 * Note that QComboBox::setLineEdit is not virtual in Qt4, do not 0304 * use a KComboBox in a QComboBox pointer. 0305 * 0306 * NOTE: Only editable combo boxes can have a line editor. As such 0307 * any attempt to assign a line edit to a non-editable combo box will 0308 * simply be ignored. 0309 */ 0310 virtual void setLineEdit(QLineEdit *); 0311 0312 /** 0313 * Reimplemented so that setEditable(true) creates a KLineEdit 0314 * instead of QLineEdit. 0315 * 0316 * Note that QComboBox::setEditable is not virtual, so do not 0317 * use a KComboBox in a QComboBox pointer. 0318 */ 0319 void setEditable(bool editable); 0320 0321 /** 0322 * Pointer to KLineEdit's context menu, or nullptr if it does not exist at 0323 * the given moment. 0324 * 0325 * @since 5.78 0326 */ 0327 QMenu *contextMenu() const; 0328 0329 QSize minimumSizeHint() const override; 0330 0331 Q_SIGNALS: 0332 /** 0333 * Emitted when the user presses the Return or Enter key. 0334 * 0335 * The argument is the current text being edited. 0336 * 0337 * @note This signal is only emitted when the widget is editable. 0338 * 0339 */ 0340 void returnPressed(const QString &text); // clazy:exclude=overloaded-signal 0341 0342 /** 0343 * Emitted when the completion key is pressed. 0344 * 0345 * The argument is the current text being edited. 0346 * 0347 * Note that this signal is @em not available when the widget is non-editable 0348 * or the completion mode is set to @c CompletionNone. 0349 */ 0350 void completion(const QString &); 0351 0352 /** 0353 * Emitted when the shortcut for substring completion is pressed. 0354 */ 0355 void substringCompletion(const QString &); 0356 0357 /** 0358 * Emitted when the text rotation key bindings are pressed. 0359 * 0360 * The argument indicates which key binding was pressed. In this case this 0361 * can be either one of four values: @c PrevCompletionMatch, 0362 * @c NextCompletionMatch, @c RotateUp or @c RotateDown. 0363 * 0364 * Note that this signal is @em not emitted if the completion 0365 * mode is set to CompletionNone. 0366 * 0367 * @see KCompletionBase::setKeyBinding() for details 0368 */ 0369 void textRotation(KCompletionBase::KeyBindingType); 0370 0371 /** 0372 * Emitted whenever the completion mode is changed by the user 0373 * through the context menu. 0374 */ 0375 void completionModeChanged(KCompletion::CompletionMode); 0376 0377 /** 0378 * Emitted before the context menu is displayed. 0379 * 0380 * The signal allows you to add your own entries into the context menu. 0381 * Note that you <em>must not</em> store the pointer to the QPopupMenu since it is 0382 * created and deleted on demand. Otherwise, you can crash your app. 0383 * 0384 * @param contextMenu the context menu about to be displayed 0385 */ 0386 void aboutToShowContextMenu(QMenu *contextMenu); 0387 0388 public Q_SLOTS: 0389 0390 /** 0391 * Iterates through all possible matches of the completed text 0392 * or the history list. 0393 * 0394 * Depending on the value of the argument, this function either 0395 * iterates through the history list of this widget or all the 0396 * possible matches in whenever multiple matches result from a 0397 * text completion request. Note that the all-possible-match 0398 * iteration will not work if there are no previous matches, i.e. 0399 * no text has been completed and the *nix shell history list 0400 * rotation is only available if the insertion policy for this 0401 * widget is set either @c QComobBox::AtTop or @c QComboBox::AtBottom. 0402 * For other insertion modes whatever has been typed by the user 0403 * when the rotation event was initiated will be lost. 0404 * 0405 * @param type The key binding invoked. 0406 */ 0407 void rotateText(KCompletionBase::KeyBindingType type); 0408 0409 /** 0410 * Sets the completed text in the line edit appropriately. 0411 * 0412 * This function is an implementation for 0413 * KCompletionBase::setCompletedText. 0414 */ 0415 void setCompletedText(const QString &) override; 0416 0417 /** 0418 * Sets @p items into the completion box if completionMode() is 0419 * CompletionPopup. The popup will be shown immediately. 0420 */ 0421 void setCompletedItems(const QStringList &items, bool autoSuggest = true) override; 0422 0423 /** 0424 * Selects the first item that matches @p item. 0425 * 0426 * If there is no such item, it is inserted at position @p index 0427 * if @p insert is true. Otherwise, no item is selected. 0428 */ 0429 void setCurrentItem(const QString &item, bool insert = false, int index = -1); 0430 0431 protected Q_SLOTS: 0432 0433 /** 0434 * Completes text according to the completion mode. 0435 * 0436 * @note This method is not invoked if the completion mode is 0437 * set to @c CompletionNone. Also if the mode is set to @c CompletionShell 0438 * and multiple matches are found, this method will complete the 0439 * text to the first match with a beep to indicate that there are 0440 * more matches. Then any successive completion key event iterates 0441 * through the remaining matches. This way the rotation functionality 0442 * is left to iterate through the list as usual. 0443 */ 0444 virtual void makeCompletion(const QString &); 0445 0446 protected: 0447 /** 0448 * This function sets the line edit text and 0449 * highlights the text appropriately if the boolean 0450 * value is set to true. 0451 * 0452 * @param text The text to be set in the line edit 0453 * @param marked Whether the text inserted should be highlighted 0454 */ 0455 virtual void setCompletedText(const QString &text, bool marked); 0456 0457 protected: 0458 KCOMPLETION_NO_EXPORT KComboBox(KComboBoxPrivate &dd, QWidget *parent); 0459 0460 protected: 0461 std::unique_ptr<KComboBoxPrivate> const d_ptr; 0462 0463 private: 0464 Q_DECLARE_PRIVATE(KComboBox) 0465 }; 0466 0467 #endif