| 1 | /* |
| 2 | This file is part of the KDE libraries |
| 3 | |
| 4 | This class was originally inspired by Torben Weis' |
| 5 | fileentry.cpp for KFM II. |
| 6 | |
| 7 | SPDX-FileCopyrightText: 1997 Sven Radej <sven.radej@iname.com> |
| 8 | SPDX-FileCopyrightText: 1999 Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com> |
| 9 | SPDX-FileCopyrightText: 1999 Preston Brown <pbrown@kde.org> |
| 10 | |
| 11 | Completely re-designed: |
| 12 | SPDX-FileCopyrightText: 2000, 2001 Dawit Alemayehu <adawit@kde.org> |
| 13 | |
| 14 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 15 | */ |
| 16 | |
| 17 | #ifndef KLINEEDIT_H |
| 18 | #define KLINEEDIT_H |
| 19 | |
| 20 | #include <kcompletion.h> |
| 21 | #include <kcompletion_export.h> |
| 22 | #include <kcompletionbase.h> |
| 23 | |
| 24 | #include <QLineEdit> |
| 25 | #include <memory> |
| 26 | |
| 27 | class QAction; |
| 28 | class ; |
| 29 | class KCompletionBox; |
| 30 | class QUrl; |
| 31 | class KLineEditPrivate; |
| 32 | |
| 33 | /*! |
| 34 | * \class KLineEdit |
| 35 | * \inmodule KCompletion |
| 36 | * |
| 37 | * \brief An enhanced QLineEdit widget for inputting text. |
| 38 | * |
| 39 | * This widget inherits from QLineEdit and implements the following |
| 40 | * additional functionalities: |
| 41 | * \list |
| 42 | * \li a completion object that provides both automatic and manual text |
| 43 | * completion as well as multiple match iteration features |
| 44 | * \li configurable key-bindings to activate these features |
| 45 | * \li a popup-menu item that can be used to allow the user to set text |
| 46 | * completion modes on the fly based on their preference |
| 47 | * \endlist |
| 48 | * |
| 49 | * To support these features KLineEdit also emits a few more additional |
| 50 | * signals: |
| 51 | * \list |
| 52 | * \li completion(const QString &): this signal can be connected to |
| 53 | * a slot that will assist the user in filling out the remaining text |
| 54 | * \li textRotation(KeyBindingType): this signal is intended to be |
| 55 | * used to iterate through the list of all possible matches whenever |
| 56 | * there is more than one match for the entered text |
| 57 | * \li returnKeyPressed(const QString &): this signal provides the |
| 58 | * current text in the widget as its argument whenever appropriate (this |
| 59 | * is in addition to the QLineEdit::returnPressed() signal which KLineEdit |
| 60 | * inherits from QLineEdit). |
| 61 | * \endlist |
| 62 | * |
| 63 | * This widget by default creates a completion object when you invoke |
| 64 | * the completionObject(bool) member function for the first time or |
| 65 | * use setCompletionObject(KCompletion *, bool) to assign your own |
| 66 | * completion object. Additionally, to make this widget more functional, |
| 67 | * KLineEdit will by default handle the text rotation and completion |
| 68 | * events internally when a completion object is created through either one |
| 69 | * of the methods mentioned above. If you do not need this functionality, |
| 70 | * simply use KCompletionBase::setHandleSignals(bool) or set the boolean |
| 71 | * parameter in the above functions to false. |
| 72 | * |
| 73 | * The default key-bindings for completion and rotation is determined |
| 74 | * from the global settings in KStandardShortcut. These values, however, |
| 75 | * can be overridden locally by invoking KCompletionBase::setKeyBinding(). |
| 76 | * The values can easily be reverted back to the default setting, by simply |
| 77 | * calling useGlobalSettings(). An alternate method would be to default |
| 78 | * individual key-bindings by using setKeyBinding() with the default |
| 79 | * second argument. |
| 80 | * |
| 81 | * If EchoMode for this widget is set to something other than QLineEdit::Normal, |
| 82 | * the completion mode will always be defaulted to CompletionNone. |
| 83 | * This is done purposefully to guard against protected entries, such as |
| 84 | * passwords, being cached in KCompletion's list. Hence, if the EchoMode |
| 85 | * is not QLineEdit::Normal, the completion mode is automatically disabled. |
| 86 | * |
| 87 | * A read-only KLineEdit will have the same background color as a disabled |
| 88 | * KLineEdit, but its foreground color will be the one used for the read-write |
| 89 | * mode. This differs from QLineEdit's implementation and is done to give visual |
| 90 | * distinction between the three different modes: disabled, read-only, and read-write. |
| 91 | * |
| 92 | * To enable the basic completion feature: |
| 93 | * |
| 94 | * \code |
| 95 | * KLineEdit *edit = new KLineEdit(this); |
| 96 | * KCompletion *comp = edit->completionObject(); |
| 97 | * // Connect to the Return pressed signal - optional |
| 98 | * connect(edit, &KLineEdit::returnKeyPressed, comp, [this](const QString &text) { addItem(text); }); |
| 99 | * \endcode |
| 100 | * |
| 101 | * To use a customized completion object or your own completion object: |
| 102 | * |
| 103 | * \code |
| 104 | * KLineEdit *edit = new KLineEdit(this); |
| 105 | * KUrlCompletion *comp = new KUrlCompletion(); |
| 106 | * edit->setCompletionObject(comp); |
| 107 | * // Connect to the return pressed signal - optional |
| 108 | * connect(edit, &KLineEdit::returnKeyPressed, comp, [this](const QString &text) { addItem(text); }); |
| 109 | * \endcode |
| 110 | * |
| 111 | * Note if you specify your own completion object you have to either delete |
| 112 | * it when you don't need it anymore, or you can tell KLineEdit to delete it |
| 113 | * for you: |
| 114 | * \code |
| 115 | * edit->setAutoDeleteCompletionObject(true); |
| 116 | * \endcode |
| 117 | * |
| 118 | * Miscellaneous function calls: |
| 119 | * |
| 120 | * \code |
| 121 | * // Tell the widget to not handle completion and iteration automatically |
| 122 | * edit->setHandleSignals(false); |
| 123 | * |
| 124 | * // Set your own key-bindings for a text completion mode |
| 125 | * edit->setKeyBinding(KCompletionBase::TextCompletion, Qt::End); |
| 126 | * |
| 127 | * // Hide the context (popup) menu |
| 128 | * edit->setContextMenuPolicy(Qt::NoContextMenu); |
| 129 | * |
| 130 | * // Default the key-bindings back to the default system settings |
| 131 | * edit->useGlobalKeyBindings(); |
| 132 | * \endcode |
| 133 | * |
| 134 | * \image klineedit.png "KLineEdit widgets with clear-button" |
| 135 | */ |
| 136 | |
| 137 | class KCOMPLETION_EXPORT KLineEdit : public QLineEdit, public KCompletionBase // krazy:exclude=qclasses |
| 138 | { |
| 139 | friend class KComboBox; |
| 140 | friend class KLineEditStyle; |
| 141 | |
| 142 | Q_OBJECT |
| 143 | Q_DECLARE_PRIVATE(KLineEdit) |
| 144 | |
| 145 | /*! |
| 146 | * \property KLineEdit::trapEnterKeyEvent |
| 147 | */ |
| 148 | Q_PROPERTY(bool trapEnterKeyEvent READ trapReturnKey WRITE setTrapReturnKey) |
| 149 | |
| 150 | /*! |
| 151 | * \property KLineEdit::squeezedTextEnabled |
| 152 | */ |
| 153 | Q_PROPERTY(bool squeezedTextEnabled READ isSqueezedTextEnabled WRITE setSqueezedTextEnabled) |
| 154 | |
| 155 | public: |
| 156 | /*! |
| 157 | * Constructs a KLineEdit object with a default text, a parent, |
| 158 | * and a name. |
| 159 | * |
| 160 | * \a string Text to be shown in the edit widget. |
| 161 | * \a parent The parent widget of the line edit. |
| 162 | */ |
| 163 | explicit KLineEdit(const QString &string, QWidget *parent = nullptr); |
| 164 | |
| 165 | /*! |
| 166 | * Constructs a line edit |
| 167 | * \a parent The parent widget of the line edit. |
| 168 | */ |
| 169 | explicit KLineEdit(QWidget *parent = nullptr); |
| 170 | |
| 171 | ~KLineEdit() override; |
| 172 | |
| 173 | /*! |
| 174 | * Sets \a url into the lineedit. It uses QUrl::toDisplayString() so |
| 175 | * that the url is properly decoded for displaying. |
| 176 | */ |
| 177 | void setUrl(const QUrl &url); |
| 178 | |
| 179 | /* |
| 180 | * Reimplemented from KCompletionBase for internal reasons. |
| 181 | * |
| 182 | * This function is re-implemented in order to make sure that |
| 183 | * the EchoMode is acceptable before we set the completion mode. |
| 184 | * |
| 185 | * See KCompletionBase::setCompletionMode |
| 186 | */ |
| 187 | void setCompletionMode(KCompletion::CompletionMode mode) override; |
| 188 | |
| 189 | /*! |
| 190 | * Disables completion modes by making them non-checkable. |
| 191 | * |
| 192 | * The context menu allows to change the completion mode. |
| 193 | * This method allows to disable some modes. |
| 194 | */ |
| 195 | void setCompletionModeDisabled(KCompletion::CompletionMode mode, bool disable = true); |
| 196 | |
| 197 | /*! |
| 198 | * Returns \c true when decoded URL drops are enabled |
| 199 | */ |
| 200 | bool urlDropsEnabled() const; |
| 201 | |
| 202 | /*! |
| 203 | * By default, KLineEdit recognizes \c Key_Return and \c Key_Enter and emits |
| 204 | * the returnPressed() signals, but it also lets the event pass, |
| 205 | * for example causing a dialog's default-button to be called. |
| 206 | * |
| 207 | * Call this method with \a trap = \c true to make KLineEdit stop these |
| 208 | * events. The signals will still be emitted of course. |
| 209 | * |
| 210 | * \sa trapReturnKey() |
| 211 | */ |
| 212 | void setTrapReturnKey(bool trap); |
| 213 | |
| 214 | /*! |
| 215 | * Returns \c true if keyevents of \c Key_Return or |
| 216 | * \c Key_Enter will be stopped or if they will be propagated. |
| 217 | * |
| 218 | * \sa setTrapReturnKey() |
| 219 | */ |
| 220 | bool trapReturnKey() const; |
| 221 | |
| 222 | /*! |
| 223 | * This method will create a completion-box if none is there, yet. |
| 224 | * |
| 225 | * \a create Set this to false if you don't want the box to be created |
| 226 | * i.e. to test if it is available. |
| 227 | * |
| 228 | * Returns the completion-box, that is used in completion mode |
| 229 | * CompletionPopup. |
| 230 | */ |
| 231 | virtual KCompletionBox *completionBox(bool create = true); |
| 232 | |
| 233 | void setCompletionObject(KCompletion *, bool handle = true) override; |
| 234 | |
| 235 | virtual void copy() const; |
| 236 | |
| 237 | /*! |
| 238 | * Enable text squeezing whenever the supplied text is too long. |
| 239 | * Only works for "read-only" mode. |
| 240 | * |
| 241 | * Note that once text squeezing is enabled, QLineEdit::text() |
| 242 | * and QLineEdit::displayText() return the squeezed text. If |
| 243 | * you want the original text, use originalText. |
| 244 | * |
| 245 | * \sa QLineEdit |
| 246 | */ |
| 247 | void setSqueezedTextEnabled(bool enable); |
| 248 | |
| 249 | /*! |
| 250 | * Returns \c true if text squeezing is enabled. |
| 251 | * |
| 252 | * This is only valid when the widget is in read-only mode. |
| 253 | */ |
| 254 | bool isSqueezedTextEnabled() const; |
| 255 | |
| 256 | /*! |
| 257 | * Returns the original text if text squeezing is enabled. |
| 258 | * If the widget is not in "read-only" mode, this function |
| 259 | * returns the same thing as QLineEdit::text(). |
| 260 | * |
| 261 | * \sa QLineEdit |
| 262 | */ |
| 263 | QString originalText() const; |
| 264 | |
| 265 | /*! |
| 266 | * Returns the text as given by the user (i.e. not autocompleted) |
| 267 | * if the widget has autocompletion disabled, this function |
| 268 | * returns the same as QLineEdit::text(). |
| 269 | * \since 4.2.2 |
| 270 | */ |
| 271 | QString userText() const; |
| 272 | |
| 273 | /*! |
| 274 | * Set the completion-box to be used in completion mode |
| 275 | * CompletionPopup. |
| 276 | * This will do nothing if a completion-box already exists. |
| 277 | * |
| 278 | * \a box The KCompletionBox to set |
| 279 | */ |
| 280 | void setCompletionBox(KCompletionBox *box); |
| 281 | |
| 282 | /*! |
| 283 | * Returns the size used by the clear button |
| 284 | * \since 4.1 |
| 285 | */ |
| 286 | QSize clearButtonUsedSize() const; |
| 287 | |
| 288 | /*! |
| 289 | * Do completion now. This is called automatically when typing a key for instance. |
| 290 | * Emits completion() and/or calls makeCompletion(), depending on |
| 291 | * emitSignals and handleSignals. |
| 292 | * |
| 293 | * \since 4.2.1 |
| 294 | */ |
| 295 | void doCompletion(const QString &text); |
| 296 | |
| 297 | Q_SIGNALS: |
| 298 | /*! |
| 299 | * Emitted whenever the completion box is activated. |
| 300 | */ |
| 301 | void completionBoxActivated(const QString &); |
| 302 | |
| 303 | /*! |
| 304 | * Emitted when the user presses the Return or Enter key. |
| 305 | * |
| 306 | * The argument is the current text. Note that this signal is \e not emitted |
| 307 | * if the widget's \c EchoMode is set to QLineEdit::EchoMode. |
| 308 | * |
| 309 | * \since 5.81 |
| 310 | */ |
| 311 | void returnKeyPressed(const QString &text); |
| 312 | |
| 313 | /*! |
| 314 | * Emitted when the completion key is pressed. |
| 315 | * |
| 316 | * Please note that this signal is \e not emitted if the |
| 317 | * completion mode is set to CompletionNone or EchoMode is |
| 318 | * \e normal. |
| 319 | */ |
| 320 | void completion(const QString &); |
| 321 | |
| 322 | /*! |
| 323 | * Emitted when the shortcut for substring completion is pressed. |
| 324 | */ |
| 325 | void substringCompletion(const QString &); |
| 326 | |
| 327 | /*! |
| 328 | * Emitted when the text rotation key-bindings are pressed. |
| 329 | * |
| 330 | * The argument indicates which key-binding was pressed. |
| 331 | * In KLineEdit's case this can be either one of two values: |
| 332 | * PrevCompletionMatch or NextCompletionMatch. See |
| 333 | * KCompletionBase::setKeyBinding for details. |
| 334 | * |
| 335 | * Note that this signal is not emitted if the completion |
| 336 | * mode is set to CompletionNone or echoMode() is \e not normal. |
| 337 | */ |
| 338 | void textRotation(KCompletionBase::KeyBindingType); |
| 339 | |
| 340 | /*! |
| 341 | * Emitted when the user changed the completion mode by using the |
| 342 | * popupmenu. |
| 343 | */ |
| 344 | void completionModeChanged(KCompletion::CompletionMode); |
| 345 | |
| 346 | /*! |
| 347 | * Emitted before the context menu is displayed. |
| 348 | * |
| 349 | * The signal allows you to add your own entries into the |
| 350 | * the context menu that is created on demand. |
| 351 | * |
| 352 | * \note Do not store the pointer to the QMenu |
| 353 | * provided through since it is created and deleted |
| 354 | * on demand. |
| 355 | * |
| 356 | * \a contextMenu the context menu about to be displayed |
| 357 | */ |
| 358 | void (QMenu *); |
| 359 | |
| 360 | /*! |
| 361 | * Emitted when the user clicked on the clear button |
| 362 | */ |
| 363 | void clearButtonClicked(); |
| 364 | |
| 365 | public Q_SLOTS: |
| 366 | |
| 367 | /*! |
| 368 | * Sets the lineedit to read-only. Similar to QLineEdit::setReadOnly |
| 369 | * but also takes care of the background color, and the clear button. |
| 370 | */ |
| 371 | virtual void setReadOnly(bool); |
| 372 | |
| 373 | /*! |
| 374 | * Iterates through all possible matches of the completed text or |
| 375 | * the history list. |
| 376 | * |
| 377 | * This function simply iterates over all possible matches in case |
| 378 | * multiple matches are found as a result of a text completion request. |
| 379 | * It will have no effect if only a single match is found. |
| 380 | * |
| 381 | * \a type The key-binding invoked. |
| 382 | */ |
| 383 | void rotateText(KCompletionBase::KeyBindingType type); |
| 384 | |
| 385 | void setCompletedText(const QString &) override; |
| 386 | |
| 387 | /*! |
| 388 | * Same as the above function except it allows you to temporarily |
| 389 | * turn off text completion in CompletionPopupAuto mode. |
| 390 | * |
| 391 | * \a items list of completion matches to be shown in the completion box. |
| 392 | * |
| 393 | * \a autoSuggest true if you want automatic text completion (suggestion) enabled. |
| 394 | */ |
| 395 | void setCompletedItems(const QStringList &items, bool autoSuggest = true) override; |
| 396 | |
| 397 | /*! |
| 398 | * Squeezes \a text into the line edit. |
| 399 | * |
| 400 | * This can only be used with read-only line-edits. |
| 401 | */ |
| 402 | void setSqueezedText(const QString &text); |
| 403 | |
| 404 | virtual void setText(const QString &); |
| 405 | |
| 406 | protected Q_SLOTS: |
| 407 | |
| 408 | /*! |
| 409 | * Completes the remaining text with a matching one from |
| 410 | * a given list. |
| 411 | */ |
| 412 | virtual void makeCompletion(const QString &); |
| 413 | |
| 414 | /*! |
| 415 | * Resets the current displayed text. |
| 416 | * Call this function to revert a text completion if the user |
| 417 | * cancels the request. Mostly applies to popup completions. |
| 418 | */ |
| 419 | void userCancelled(const QString &cancelText); |
| 420 | |
| 421 | protected: |
| 422 | bool event(QEvent *) override; |
| 423 | |
| 424 | void resizeEvent(QResizeEvent *) override; |
| 425 | |
| 426 | void keyPressEvent(QKeyEvent *) override; |
| 427 | |
| 428 | void mousePressEvent(QMouseEvent *) override; |
| 429 | |
| 430 | void mouseReleaseEvent(QMouseEvent *) override; |
| 431 | |
| 432 | void mouseDoubleClickEvent(QMouseEvent *) override; |
| 433 | |
| 434 | void (QContextMenuEvent *) override; |
| 435 | |
| 436 | QMenu *createStandardContextMenu(); |
| 437 | |
| 438 | /*! |
| 439 | * This function simply sets the lineedit text and |
| 440 | * highlights the text appropriately if the boolean |
| 441 | * value is set to \c true. |
| 442 | */ |
| 443 | virtual void setCompletedText(const QString & /*text*/, bool /*marked*/); |
| 444 | |
| 445 | /*! |
| 446 | * Sets the widget in userSelection mode or in automatic completion |
| 447 | * selection mode. This changes the colors of selections. |
| 448 | */ |
| 449 | void setUserSelection(bool userSelection); |
| 450 | |
| 451 | /*! |
| 452 | * Whether in current state text should be auto-suggested |
| 453 | */ |
| 454 | bool autoSuggest() const; |
| 455 | |
| 456 | void paintEvent(QPaintEvent *ev) override; |
| 457 | |
| 458 | private: |
| 459 | std::unique_ptr<KLineEditPrivate> const d_ptr; |
| 460 | }; |
| 461 | |
| 462 | #endif |
| 463 | |