File indexing completed on 2024-04-28 03:53:08
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1999, 2000 Carsten Pfeiffer <pfeiffer@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #ifndef KCOMPLETION_H 0009 #define KCOMPLETION_H 0010 0011 #include <kcompletion_export.h> 0012 0013 #include <QKeySequence> 0014 #include <QObject> 0015 #include <QPointer> 0016 #include <QStringList> 0017 #include <functional> 0018 #include <memory> 0019 0020 class KCompTreeNode; 0021 class KCompletionPrivate; 0022 class KCompletionMatchesWrapper; 0023 class KCompletionMatches; 0024 0025 /** 0026 * @class KCompletion kcompletion.h KCompletion 0027 * 0028 * @short A generic class for completing QStrings 0029 * 0030 * This class offers easy use of "auto completion", "manual completion" or 0031 * "shell completion" on QString objects. A common use is completing filenames 0032 * or URLs (see KUrlCompletion()). 0033 * But it is not limited to URL-completion -- everything should be completable! 0034 * The user should be able to complete email addresses, telephone numbers, 0035 * commands, SQL queries... 0036 * Every time your program knows what the user can type into an edit field, you 0037 * should offer completion. With KCompletion, this is very easy, and if you are 0038 * using a line edit widget (KLineEdit), it is even easier. 0039 * Basically, you tell a KCompletion object what strings should be completable 0040 * and, whenever completion should be invoked, you call makeCompletion(). 0041 * KLineEdit and (an editable) KComboBox even do this automatically for you. 0042 * 0043 * KCompletion offers the completed string via the signal match() and 0044 * all matching strings (when the result is ambiguous) via the method 0045 * allMatches(). 0046 * 0047 * Notice: auto completion, shell completion and manual completion work 0048 * slightly differently: 0049 * 0050 * @li auto completion always returns a complete item as match. 0051 * When more than one matching item is available, it will deliver just 0052 * the first one (depending on sorting order). Iterating over all matches 0053 * is possible via nextMatch() and previousMatch(). 0054 * 0055 * @li popup completion works in the same way, the only difference being that 0056 * the completed items are not put into the edit widget, but into a 0057 * separate popup box. 0058 * 0059 * @li manual completion works the same way as auto completion, except that 0060 * it is not invoked automatically while the user is typing, 0061 * but only when the user presses a special key. The difference 0062 * of manual and auto completion is therefore only visible in UI classes. 0063 * KCompletion needs to know whether to deliver partial matches 0064 * (shell completion) or whole matches (auto/manual completion), therefore 0065 * KCompletion::CompletionMan and KCompletion::CompletionAuto have the exact 0066 * same effect in KCompletion. 0067 * 0068 * @li shell completion works like "tab completion" in a shell: 0069 * when multiple matches are available, the longest possible string of all 0070 * matches is returned (i.e. only a partial item). 0071 * Iterating over all matching items (complete, not partial) is possible 0072 * via nextMatch() and previousMatch(). 0073 * 0074 * As an application programmer, you do not normally have to worry about 0075 * the different completion modes; KCompletion handles 0076 * that for you, according to the setting setCompletionMode(). 0077 * The default setting is globally configured by the user and read 0078 * from completionMode(). 0079 * 0080 * A short example: 0081 * \code 0082 * KCompletion completion; 0083 * completion.setOrder(KCompletion::Sorted); 0084 * completion.addItem("pfeiffer@kde.org"); 0085 * completion.addItem("coolo@kde.org"); 0086 * completion.addItem("carpdjih@sp.zrz.tu-berlin.de"); 0087 * completion.addItem("carp@cs.tu-berlin.de"); 0088 * 0089 * cout << completion.makeCompletion("ca").latin1() << endl; 0090 * \endcode 0091 * 0092 * In shell-completion mode, this will be "carp"; in auto-completion 0093 * mode it will be "carp\@cs.tu-berlin.de", as that is alphabetically 0094 * smaller. 0095 * If setOrder was set to Insertion, "carpdjih\@sp.zrz.tu-berlin.de" 0096 * would be completed in auto-completion mode, as that was inserted before 0097 * "carp\@cs.tu-berlin.de". 0098 * 0099 * You can dynamically update the completable items by removing and adding them 0100 * whenever you want. 0101 * For advanced usage, you could even use multiple KCompletion objects. E.g. 0102 * imagine an editor like kwrite with multiple open files. You could store 0103 * items of each file in a different KCompletion object, so that you know (and 0104 * tell the user) where a completion comes from. 0105 * 0106 * @note KCompletion does not work with strings that contain 0x0 characters 0107 * (unicode null), as this is used internally as a delimiter. 0108 * 0109 * You may inherit from KCompletion and override makeCompletion() in 0110 * special cases (like reading directories or urls and then supplying the 0111 * contents to KCompletion, as KUrlCompletion does), but this is usually 0112 * not necessary. 0113 * 0114 * 0115 * @author Carsten Pfeiffer <pfeiffer@kde.org> 0116 */ 0117 class KCOMPLETION_EXPORT KCompletion : public QObject 0118 { 0119 Q_PROPERTY(CompOrder order READ order WRITE setOrder) 0120 Q_PROPERTY(bool ignoreCase READ ignoreCase WRITE setIgnoreCase) 0121 Q_PROPERTY(QStringList items READ items WRITE setItems) 0122 Q_OBJECT 0123 Q_DECLARE_PRIVATE(KCompletion) 0124 0125 public: 0126 /** 0127 * This enum describes the completion mode used for by the KCompletion class. 0128 * 0129 * @since 5.0 0130 */ 0131 enum CompletionMode { 0132 /** 0133 * No completion is used. 0134 */ 0135 CompletionNone = 1, 0136 /** 0137 * Text is automatically filled in whenever possible. 0138 */ 0139 CompletionAuto, 0140 /** 0141 * Same as automatic, but shortest match is used for completion. 0142 */ 0143 CompletionMan, 0144 /** 0145 * Completes text much in the same way as a typical *nix shell would. 0146 */ 0147 CompletionShell, 0148 /** 0149 * Lists all possible matches in a popup list box to choose from. 0150 */ 0151 CompletionPopup, 0152 /** 0153 * Lists all possible matches in a popup list box to choose from, and automatically 0154 * fills the result whenever possible. 0155 */ 0156 CompletionPopupAuto, 0157 }; 0158 0159 /** 0160 * Constants that represent the order in which KCompletion performs 0161 * completion lookups. 0162 */ 0163 enum CompOrder { 0164 Sorted, ///< Use alphabetically sorted order or custom sorter logic 0165 Insertion, ///< Use order of insertion 0166 Weighted, ///< Use weighted order 0167 }; 0168 Q_ENUM(CompOrder) 0169 0170 /** 0171 * The sorter function signature. Deriving classes may provide 0172 * custom sorting logic via the setSorterFunction method. 0173 * 0174 * @since 5.88 0175 */ 0176 using SorterFunction = std::function<void(QStringList &)>; 0177 0178 /** 0179 * Constructor, nothing special here :) 0180 */ 0181 KCompletion(); 0182 0183 /** 0184 * Destructor, nothing special here, either. 0185 */ 0186 ~KCompletion() override; 0187 0188 /** 0189 * Returns a list of all completion items that contain the given @p string. 0190 * @param string the string to complete 0191 * @return a list of items which contain @p text as a substring, 0192 * i.e. not necessarily at the beginning. 0193 * 0194 * @see makeCompletion 0195 */ 0196 QStringList substringCompletion(const QString &string) const; 0197 0198 /** 0199 * Returns the last match. Might be useful if you need to check whether 0200 * a completion is different from the last one. 0201 * @return the last match. QString() is returned when there is no 0202 * last match. 0203 */ 0204 virtual const QString &lastMatch() const; 0205 0206 /** 0207 * Returns a list of all items inserted into KCompletion. This is useful 0208 * if you need to save the state of a KCompletion object and restore it 0209 * later. 0210 * 0211 * @note When order() == Weighted, then every item in the 0212 * stringlist has its weight appended, delimited by a colon. E.g. an item 0213 * "www.kde.org" might look like "www.kde.org:4", where 4 is the weight. 0214 * This is necessary so that you can save the items along with its 0215 * weighting on disk and load them back with setItems(), restoring its 0216 * weight as well. If you really don't want the appended weightings, call 0217 * setOrder( KCompletion::Insertion ) before calling items(). 0218 * 0219 * @return a list of all items 0220 * @see setItems 0221 */ 0222 QStringList items() const; 0223 0224 /** 0225 * Returns true if the completion object contains no entries. 0226 */ 0227 bool isEmpty() const; 0228 0229 /** 0230 * Sets the completion mode. 0231 * @param mode the completion mode 0232 * @see CompletionMode 0233 */ 0234 virtual void setCompletionMode(CompletionMode mode); 0235 0236 /** 0237 * Returns the current completion mode. 0238 * 0239 * @return the current completion mode, default is CompletionPopup 0240 * @see setCompletionMode 0241 * @see CompletionMode 0242 */ 0243 CompletionMode completionMode() const; 0244 0245 /** 0246 * KCompletion offers three different ways in which it offers its items: 0247 * @li in the order of insertion 0248 * @li sorted alphabetically 0249 * @li weighted 0250 * 0251 * Choosing weighted makes KCompletion perform an implicit weighting based 0252 * on how often an item is inserted. Imagine a web browser with a location 0253 * bar, where the user enters URLs. The more often a URL is entered, the 0254 * higher priority it gets. 0255 * 0256 * @note Setting the order to sorted only affects new inserted items, 0257 * already existing items will stay in the current order. So you probably 0258 * want to call setOrder(Sorted) before inserting items if you want 0259 * everything sorted. 0260 * 0261 * Default is insertion order. 0262 * @param order the new order 0263 * @see order 0264 */ 0265 virtual void setOrder(CompOrder order); 0266 0267 /** 0268 * Returns the completion order. 0269 * @return the current completion order. 0270 * @see setOrder 0271 */ 0272 CompOrder order() const; 0273 0274 /** 0275 * Setting this to true makes KCompletion behave case insensitively. 0276 * E.g. makeCompletion("CA"); might return "carp\@cs.tu-berlin.de". 0277 * Default is false (case sensitive). 0278 * @param ignoreCase true to ignore the case 0279 * @see ignoreCase 0280 */ 0281 virtual void setIgnoreCase(bool ignoreCase); 0282 0283 /** 0284 * Returns whether KCompletion acts case insensitively or not. 0285 * Default is false (case sensitive). 0286 * @return true if the case will be ignored 0287 * @see setIgnoreCase 0288 */ 0289 bool ignoreCase() const; 0290 0291 /** 0292 * Informs the caller if they should display the auto-suggestion for the last completion operation performed. 0293 * Applies for CompletionPopupAuto and CompletionAuto modes. 0294 * Defaults to true, but deriving classes may set it to false in special cases via "setShouldAutoSuggest". 0295 * @return true if auto-suggestion should be displayed for the last completion operation performed. 0296 * @since 5.87 0297 */ 0298 bool shouldAutoSuggest() const; 0299 0300 /** 0301 * Returns a list of all items matching the last completed string. 0302 * It might take some time if you have a @em lot of items. 0303 * @return a list of all matches for the last completed string. 0304 * @see substringCompletion 0305 */ 0306 QStringList allMatches(); 0307 0308 /** 0309 * Returns a list of all items matching @p string. 0310 * @param string the string to match 0311 * @return the list of all matches 0312 */ 0313 QStringList allMatches(const QString &string); 0314 0315 /** 0316 * Returns a list of all items matching the last completed string. 0317 * It might take some time if you have a @em lot of items. 0318 * The matches are returned as KCompletionMatches, which also 0319 * keeps the weight of the matches, allowing 0320 * you to modify some matches or merge them with matches 0321 * from another call to allWeightedMatches(), and sort the matches 0322 * after that in order to have the matches ordered correctly. 0323 * 0324 * @return a list of all completion matches 0325 * @see substringCompletion 0326 */ 0327 KCompletionMatches allWeightedMatches(); 0328 0329 /** 0330 * Returns a list of all items matching @p string. 0331 * @param string the string to match 0332 * @return a list of all matches 0333 */ 0334 KCompletionMatches allWeightedMatches(const QString &string); 0335 0336 /** 0337 * Enables/disables emitting a sound when 0338 * @li makeCompletion() can't find a match 0339 * @li there is a partial completion (= multiple matches in 0340 * Shell-completion mode) 0341 * @li nextMatch() or previousMatch() hit the last possible 0342 * match and the list is rotated 0343 * 0344 * KNotifyClient() is used to emit the sounds. 0345 * 0346 * @param enable true to enable sounds 0347 * @see soundsEnabled 0348 */ 0349 virtual void setSoundsEnabled(bool enable); 0350 0351 /** 0352 * Tells you whether KCompletion will emit sounds on certain occasions. 0353 * Default is enabled. 0354 * @return true if sounds are enabled 0355 * @see setSoundsEnabled 0356 */ 0357 bool soundsEnabled() const; 0358 0359 /** 0360 * Returns true when more than one match is found. 0361 * @return true if there is more than one match 0362 * @see multipleMatches 0363 */ 0364 bool hasMultipleMatches() const; 0365 0366 public Q_SLOTS: 0367 /** 0368 * Attempts to find an item in the list of available completions 0369 * that begins with @p string. Will either return the first matching item 0370 * (if there is more than one match) or QString(), if no match is 0371 * found. 0372 * 0373 * In the latter case, a sound will be emitted, depending on 0374 * soundsEnabled(). 0375 * If a match is found, it will be emitted via the signal 0376 * match(). 0377 * 0378 * If this is called twice or more with the same string while no 0379 * items were added or removed in the meantime, all available completions 0380 * will be emitted via the signal matches(). 0381 * This happens only in shell-completion mode. 0382 * 0383 * @param string the string to complete 0384 * @return the matching item, or QString() if there is no matching 0385 * item. 0386 * @see substringCompletion 0387 */ 0388 virtual QString makeCompletion(const QString &string); 0389 0390 /** 0391 * Returns the next item from the list of matching items. 0392 * When reaching the beginning, the list is rotated so it will return the 0393 * last match and a sound is emitted (depending on soundsEnabled()). 0394 * @return the next item from the list of matching items. 0395 * When there is no match, QString() is returned and 0396 * a sound is emitted. 0397 */ 0398 QString previousMatch(); 0399 0400 /** 0401 * Returns the next item from the list of matching items. 0402 * When reaching the last item, the list is rotated, so it will return 0403 * the first match and a sound is emitted (depending on 0404 * soundsEnabled()). 0405 * @return the next item from the list of matching items. When there is no 0406 * match, QString() is returned and a sound is emitted. 0407 */ 0408 QString nextMatch(); 0409 0410 /** 0411 * Inserts @p items into the list of possible completions. 0412 * It does the same as setItems(), but without calling clear() before. 0413 * @param items the items to insert 0414 */ 0415 void insertItems(const QStringList &items); 0416 0417 /** 0418 * Sets the list of items available for completion. Removes all previous 0419 * items. 0420 * 0421 * @note When order() == Weighted, then the weighting is looked up for 0422 * every item in the stringlist. Every item should have ":number" appended, 0423 * where number is an unsigned integer, specifying the weighting. 0424 * If you don't like this, call 0425 * setOrder(KCompletion::Insertion) 0426 * before calling setItems(). 0427 * 0428 * @param itemList the list of items that are available for completion 0429 * @see items 0430 */ 0431 virtual void setItems(const QStringList &itemList); 0432 0433 /** 0434 * Adds an item to the list of available completions. 0435 * Resets the current item state (previousMatch() and nextMatch() 0436 * won't work the next time they are called). 0437 * @param item the item to add 0438 */ 0439 void addItem(const QString &item); 0440 0441 /** 0442 * Adds an item to the list of available completions. 0443 * Resets the current item state (previousMatch() and nextMatch() 0444 * won't work the next time they are called). 0445 * 0446 * Sets the weight of the item to @p weight or adds it to the current 0447 * weight if the item is already available. The weight has to be greater 0448 * than 1 to take effect (default weight is 1). 0449 * @param item the item to add 0450 * @param weight the weight of the item, default is 1 0451 */ 0452 void addItem(const QString &item, uint weight); 0453 0454 /** 0455 * Removes an item from the list of available completions. 0456 * Resets the current item state (previousMatch() and nextMatch() 0457 * won't work the next time they are called). 0458 * @param item the item to remove 0459 */ 0460 void removeItem(const QString &item); 0461 0462 /** 0463 * Removes all inserted items. 0464 */ 0465 virtual void clear(); 0466 0467 Q_SIGNALS: 0468 /** 0469 * This signal is emitted when a match is found. 0470 * 0471 * In particular, makeCompletion(), previousMatch() and nextMatch() 0472 * all emit this signal; makeCompletion() will only emit it when a 0473 * match is found, but the other methods will always emit it (and so 0474 * may emit it with an empty string). 0475 * 0476 * @param item the matching item, or QString() if there were no more 0477 * matching items. 0478 */ 0479 void match(const QString &item); 0480 0481 /** 0482 * This signal is emitted by makeCompletion() in shell-completion mode 0483 * when the same string is passed to makeCompletion() multiple times in 0484 * a row. 0485 * @param matchlist the list of all matching items 0486 */ 0487 void matches(const QStringList &matchlist); 0488 0489 /** 0490 * This signal is emitted when calling makeCompletion() and more than 0491 * one matching item is found. 0492 * @see hasMultipleMatches 0493 */ 0494 void multipleMatches(); 0495 0496 protected: 0497 /** 0498 * This method is called after a completion is found and before the 0499 * matching string is emitted. You can override this method to modify the 0500 * string that will be emitted. 0501 * This is necessary e.g. in KUrlCompletion(), where files with spaces 0502 * in their names are shown escaped ("filename\ with\ spaces"), but stored 0503 * unescaped inside KCompletion. 0504 * Never delete that pointer! 0505 * 0506 * Default implementation does nothing. 0507 * @param match the match to process 0508 * @see postProcessMatches 0509 */ 0510 virtual void postProcessMatch(QString *match) const; 0511 0512 /** 0513 * This method is called before a list of all available completions is 0514 * emitted via matches(). You can override this method to modify the 0515 * found items before match() or matches() are emitted. 0516 * Never delete that pointer! 0517 * 0518 * Default implementation does nothing. 0519 * @param matchList the matches to process 0520 * @see postProcessMatch 0521 */ 0522 virtual void postProcessMatches(QStringList *matchList) const; 0523 0524 /** 0525 * This method is called before a list of all available completions is 0526 * emitted via #matches(). You can override this method to modify the 0527 * found items before #match() or #matches() are emitted. 0528 * Never delete that pointer! 0529 * 0530 * Default implementation does nothing. 0531 * @param matches the matches to process 0532 * @see postProcessMatch 0533 */ 0534 virtual void postProcessMatches(KCompletionMatches *matches) const; 0535 0536 /** 0537 * Deriving classes may set this property and control whether the auto-suggestion should be displayed 0538 * for the last completion operation performed. 0539 * 0540 * Applies for CompletionPopupAuto and CompletionAuto modes. 0541 * @since 5.87 0542 */ 0543 void setShouldAutoSuggest(bool shouldAutosuggest); 0544 0545 /** 0546 * Sets a custom function to be used to sort the matches. 0547 * Can be set to nullptr to use the default sorting logic. 0548 * 0549 * Applies for CompOrder::Sorted mode. 0550 * @since 5.88 0551 */ 0552 void setSorterFunction(SorterFunction sortFunc); 0553 0554 private: 0555 Q_DISABLE_COPY(KCompletion) 0556 std::unique_ptr<KCompletionPrivate> const d_ptr; 0557 }; 0558 0559 #endif // KCOMPLETION_H