1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 1999, 2000 Carsten Pfeiffer <pfeiffer@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #ifndef KCOMPLETION_H |
9 | #define KCOMPLETION_H |
10 | |
11 | #include <kcompletion_export.h> |
12 | |
13 | #include <QKeySequence> |
14 | #include <QObject> |
15 | #include <QPointer> |
16 | #include <QStringList> |
17 | #include <functional> |
18 | #include <memory> |
19 | |
20 | class KCompTreeNode; |
21 | class KCompletionPrivate; |
22 | class KCompletionMatchesWrapper; |
23 | class KCompletionMatches; |
24 | |
25 | /** |
26 | * @class KCompletion kcompletion.h KCompletion |
27 | * |
28 | * @short A generic class for completing QStrings |
29 | * |
30 | * This class offers easy use of "auto completion", "manual completion" or |
31 | * "shell completion" on QString objects. A common use is completing filenames |
32 | * or URLs (see KUrlCompletion()). |
33 | * But it is not limited to URL-completion -- everything should be completable! |
34 | * The user should be able to complete email addresses, telephone numbers, |
35 | * commands, SQL queries... |
36 | * Every time your program knows what the user can type into an edit field, you |
37 | * should offer completion. With KCompletion, this is very easy, and if you are |
38 | * using a line edit widget (KLineEdit), it is even easier. |
39 | * Basically, you tell a KCompletion object what strings should be completable |
40 | * and, whenever completion should be invoked, you call makeCompletion(). |
41 | * KLineEdit and (an editable) KComboBox even do this automatically for you. |
42 | * |
43 | * KCompletion offers the completed string via the signal match() and |
44 | * all matching strings (when the result is ambiguous) via the method |
45 | * allMatches(). |
46 | * |
47 | * Notice: auto completion, shell completion and manual completion work |
48 | * slightly differently: |
49 | * |
50 | * @li auto completion always returns a complete item as match. |
51 | * When more than one matching item is available, it will deliver just |
52 | * the first one (depending on sorting order). Iterating over all matches |
53 | * is possible via nextMatch() and previousMatch(). |
54 | * |
55 | * @li popup completion works in the same way, the only difference being that |
56 | * the completed items are not put into the edit widget, but into a |
57 | * separate popup box. |
58 | * |
59 | * @li manual completion works the same way as auto completion, except that |
60 | * it is not invoked automatically while the user is typing, |
61 | * but only when the user presses a special key. The difference |
62 | * of manual and auto completion is therefore only visible in UI classes. |
63 | * KCompletion needs to know whether to deliver partial matches |
64 | * (shell completion) or whole matches (auto/manual completion), therefore |
65 | * KCompletion::CompletionMan and KCompletion::CompletionAuto have the exact |
66 | * same effect in KCompletion. |
67 | * |
68 | * @li shell completion works like "tab completion" in a shell: |
69 | * when multiple matches are available, the longest possible string of all |
70 | * matches is returned (i.e. only a partial item). |
71 | * Iterating over all matching items (complete, not partial) is possible |
72 | * via nextMatch() and previousMatch(). |
73 | * |
74 | * As an application programmer, you do not normally have to worry about |
75 | * the different completion modes; KCompletion handles |
76 | * that for you, according to the setting setCompletionMode(). |
77 | * The default setting is globally configured by the user and read |
78 | * from completionMode(). |
79 | * |
80 | * A short example: |
81 | * \code |
82 | * KCompletion completion; |
83 | * completion.setOrder(KCompletion::Sorted); |
84 | * completion.addItem("pfeiffer@kde.org"); |
85 | * completion.addItem("coolo@kde.org"); |
86 | * completion.addItem("carpdjih@sp.zrz.tu-berlin.de"); |
87 | * completion.addItem("carp@cs.tu-berlin.de"); |
88 | * |
89 | * cout << completion.makeCompletion("ca").latin1() << endl; |
90 | * \endcode |
91 | * |
92 | * In shell-completion mode, this will be "carp"; in auto-completion |
93 | * mode it will be "carp\@cs.tu-berlin.de", as that is alphabetically |
94 | * smaller. |
95 | * If setOrder was set to Insertion, "carpdjih\@sp.zrz.tu-berlin.de" |
96 | * would be completed in auto-completion mode, as that was inserted before |
97 | * "carp\@cs.tu-berlin.de". |
98 | * |
99 | * You can dynamically update the completable items by removing and adding them |
100 | * whenever you want. |
101 | * For advanced usage, you could even use multiple KCompletion objects. E.g. |
102 | * imagine an editor like kwrite with multiple open files. You could store |
103 | * items of each file in a different KCompletion object, so that you know (and |
104 | * tell the user) where a completion comes from. |
105 | * |
106 | * @note KCompletion does not work with strings that contain 0x0 characters |
107 | * (unicode null), as this is used internally as a delimiter. |
108 | * |
109 | * You may inherit from KCompletion and override makeCompletion() in |
110 | * special cases (like reading directories or urls and then supplying the |
111 | * contents to KCompletion, as KUrlCompletion does), but this is usually |
112 | * not necessary. |
113 | * |
114 | * |
115 | * @author Carsten Pfeiffer <pfeiffer@kde.org> |
116 | */ |
117 | class KCOMPLETION_EXPORT KCompletion : public QObject |
118 | { |
119 | Q_PROPERTY(CompOrder order READ order WRITE setOrder) |
120 | Q_PROPERTY(bool ignoreCase READ ignoreCase WRITE setIgnoreCase) |
121 | Q_PROPERTY(QStringList items READ items WRITE setItems) |
122 | Q_OBJECT |
123 | Q_DECLARE_PRIVATE(KCompletion) |
124 | |
125 | public: |
126 | /** |
127 | * This enum describes the completion mode used for by the KCompletion class. |
128 | * |
129 | * @since 5.0 |
130 | */ |
131 | enum CompletionMode { |
132 | /** |
133 | * No completion is used. |
134 | */ |
135 | CompletionNone = 1, |
136 | /** |
137 | * Text is automatically filled in whenever possible. |
138 | */ |
139 | CompletionAuto, |
140 | /** |
141 | * Same as automatic, but shortest match is used for completion. |
142 | */ |
143 | CompletionMan, |
144 | /** |
145 | * Completes text much in the same way as a typical *nix shell would. |
146 | */ |
147 | CompletionShell, |
148 | /** |
149 | * Lists all possible matches in a popup list box to choose from. |
150 | */ |
151 | , |
152 | /** |
153 | * Lists all possible matches in a popup list box to choose from, and automatically |
154 | * fills the result whenever possible. |
155 | */ |
156 | , |
157 | }; |
158 | |
159 | /** |
160 | * Constants that represent the order in which KCompletion performs |
161 | * completion lookups. |
162 | */ |
163 | enum CompOrder { |
164 | Sorted, ///< Use alphabetically sorted order or custom sorter logic |
165 | Insertion, ///< Use order of insertion |
166 | Weighted, ///< Use weighted order |
167 | }; |
168 | Q_ENUM(CompOrder) |
169 | |
170 | /** |
171 | * The sorter function signature. Deriving classes may provide |
172 | * custom sorting logic via the setSorterFunction method. |
173 | * |
174 | * @since 5.88 |
175 | */ |
176 | using SorterFunction = std::function<void(QStringList &)>; |
177 | |
178 | /** |
179 | * Constructor, nothing special here :) |
180 | */ |
181 | KCompletion(); |
182 | |
183 | /** |
184 | * Destructor, nothing special here, either. |
185 | */ |
186 | ~KCompletion() override; |
187 | |
188 | /** |
189 | * Returns a list of all completion items that contain the given @p string. |
190 | * @param string the string to complete |
191 | * @return a list of items which contain @p text as a substring, |
192 | * i.e. not necessarily at the beginning. |
193 | * |
194 | * @see makeCompletion |
195 | */ |
196 | QStringList substringCompletion(const QString &string) const; |
197 | |
198 | /** |
199 | * Returns the last match. Might be useful if you need to check whether |
200 | * a completion is different from the last one. |
201 | * @return the last match. QString() is returned when there is no |
202 | * last match. |
203 | */ |
204 | virtual const QString &lastMatch() const; |
205 | |
206 | /** |
207 | * Returns a list of all items inserted into KCompletion. This is useful |
208 | * if you need to save the state of a KCompletion object and restore it |
209 | * later. |
210 | * |
211 | * @note When order() == Weighted, then every item in the |
212 | * stringlist has its weight appended, delimited by a colon. E.g. an item |
213 | * "www.kde.org" might look like "www.kde.org:4", where 4 is the weight. |
214 | * This is necessary so that you can save the items along with its |
215 | * weighting on disk and load them back with setItems(), restoring its |
216 | * weight as well. If you really don't want the appended weightings, call |
217 | * setOrder( KCompletion::Insertion ) before calling items(). |
218 | * |
219 | * @return a list of all items |
220 | * @see setItems |
221 | */ |
222 | QStringList items() const; |
223 | |
224 | /** |
225 | * Returns true if the completion object contains no entries. |
226 | */ |
227 | bool isEmpty() const; |
228 | |
229 | /** |
230 | * Sets the completion mode. |
231 | * @param mode the completion mode |
232 | * @see CompletionMode |
233 | */ |
234 | virtual void setCompletionMode(CompletionMode mode); |
235 | |
236 | /** |
237 | * Returns the current completion mode. |
238 | * |
239 | * @return the current completion mode, default is CompletionPopup |
240 | * @see setCompletionMode |
241 | * @see CompletionMode |
242 | */ |
243 | CompletionMode completionMode() const; |
244 | |
245 | /** |
246 | * KCompletion offers three different ways in which it offers its items: |
247 | * @li in the order of insertion |
248 | * @li sorted alphabetically |
249 | * @li weighted |
250 | * |
251 | * Choosing weighted makes KCompletion perform an implicit weighting based |
252 | * on how often an item is inserted. Imagine a web browser with a location |
253 | * bar, where the user enters URLs. The more often a URL is entered, the |
254 | * higher priority it gets. |
255 | * |
256 | * @note Setting the order to sorted only affects new inserted items, |
257 | * already existing items will stay in the current order. So you probably |
258 | * want to call setOrder(Sorted) before inserting items if you want |
259 | * everything sorted. |
260 | * |
261 | * Default is insertion order. |
262 | * @param order the new order |
263 | * @see order |
264 | */ |
265 | virtual void setOrder(CompOrder order); |
266 | |
267 | /** |
268 | * Returns the completion order. |
269 | * @return the current completion order. |
270 | * @see setOrder |
271 | */ |
272 | CompOrder order() const; |
273 | |
274 | /** |
275 | * Setting this to true makes KCompletion behave case insensitively. |
276 | * E.g. makeCompletion("CA"); might return "carp\@cs.tu-berlin.de". |
277 | * Default is false (case sensitive). |
278 | * @param ignoreCase true to ignore the case |
279 | * @see ignoreCase |
280 | */ |
281 | virtual void setIgnoreCase(bool ignoreCase); |
282 | |
283 | /** |
284 | * Returns whether KCompletion acts case insensitively or not. |
285 | * Default is false (case sensitive). |
286 | * @return true if the case will be ignored |
287 | * @see setIgnoreCase |
288 | */ |
289 | bool ignoreCase() const; |
290 | |
291 | /** |
292 | * Informs the caller if they should display the auto-suggestion for the last completion operation performed. |
293 | * Applies for CompletionPopupAuto and CompletionAuto modes. |
294 | * Defaults to true, but deriving classes may set it to false in special cases via "setShouldAutoSuggest". |
295 | * @return true if auto-suggestion should be displayed for the last completion operation performed. |
296 | * @since 5.87 |
297 | */ |
298 | bool shouldAutoSuggest() const; |
299 | |
300 | /** |
301 | * Returns a list of all items matching the last completed string. |
302 | * It might take some time if you have a @em lot of items. |
303 | * @return a list of all matches for the last completed string. |
304 | * @see substringCompletion |
305 | */ |
306 | QStringList allMatches(); |
307 | |
308 | /** |
309 | * Returns a list of all items matching @p string. |
310 | * @param string the string to match |
311 | * @return the list of all matches |
312 | */ |
313 | QStringList allMatches(const QString &string); |
314 | |
315 | /** |
316 | * Returns a list of all items matching the last completed string. |
317 | * It might take some time if you have a @em lot of items. |
318 | * The matches are returned as KCompletionMatches, which also |
319 | * keeps the weight of the matches, allowing |
320 | * you to modify some matches or merge them with matches |
321 | * from another call to allWeightedMatches(), and sort the matches |
322 | * after that in order to have the matches ordered correctly. |
323 | * |
324 | * @return a list of all completion matches |
325 | * @see substringCompletion |
326 | */ |
327 | KCompletionMatches allWeightedMatches(); |
328 | |
329 | /** |
330 | * Returns a list of all items matching @p string. |
331 | * @param string the string to match |
332 | * @return a list of all matches |
333 | */ |
334 | KCompletionMatches allWeightedMatches(const QString &string); |
335 | |
336 | /** |
337 | * Enables/disables emitting a sound when |
338 | * @li makeCompletion() can't find a match |
339 | * @li there is a partial completion (= multiple matches in |
340 | * Shell-completion mode) |
341 | * @li nextMatch() or previousMatch() hit the last possible |
342 | * match and the list is rotated |
343 | * |
344 | * KNotifyClient() is used to emit the sounds. |
345 | * |
346 | * @param enable true to enable sounds |
347 | * @see soundsEnabled |
348 | */ |
349 | virtual void setSoundsEnabled(bool enable); |
350 | |
351 | /** |
352 | * Tells you whether KCompletion will emit sounds on certain occasions. |
353 | * Default is enabled. |
354 | * @return true if sounds are enabled |
355 | * @see setSoundsEnabled |
356 | */ |
357 | bool soundsEnabled() const; |
358 | |
359 | /** |
360 | * Returns true when more than one match is found. |
361 | * @return true if there is more than one match |
362 | * @see multipleMatches |
363 | */ |
364 | bool hasMultipleMatches() const; |
365 | |
366 | public Q_SLOTS: |
367 | /** |
368 | * Attempts to find an item in the list of available completions |
369 | * that begins with @p string. Will either return the first matching item |
370 | * (if there is more than one match) or QString(), if no match is |
371 | * found. |
372 | * |
373 | * In the latter case, a sound will be emitted, depending on |
374 | * soundsEnabled(). |
375 | * If a match is found, it will be emitted via the signal |
376 | * match(). |
377 | * |
378 | * If this is called twice or more with the same string while no |
379 | * items were added or removed in the meantime, all available completions |
380 | * will be emitted via the signal matches(). |
381 | * This happens only in shell-completion mode. |
382 | * |
383 | * @param string the string to complete |
384 | * @return the matching item, or QString() if there is no matching |
385 | * item. |
386 | * @see substringCompletion |
387 | */ |
388 | virtual QString makeCompletion(const QString &string); |
389 | |
390 | /** |
391 | * Returns the next item from the list of matching items. |
392 | * When reaching the beginning, the list is rotated so it will return the |
393 | * last match and a sound is emitted (depending on soundsEnabled()). |
394 | * @return the next item from the list of matching items. |
395 | * When there is no match, QString() is returned and |
396 | * a sound is emitted. |
397 | */ |
398 | QString previousMatch(); |
399 | |
400 | /** |
401 | * Returns the next item from the list of matching items. |
402 | * When reaching the last item, the list is rotated, so it will return |
403 | * the first match and a sound is emitted (depending on |
404 | * soundsEnabled()). |
405 | * @return the next item from the list of matching items. When there is no |
406 | * match, QString() is returned and a sound is emitted. |
407 | */ |
408 | QString nextMatch(); |
409 | |
410 | /** |
411 | * Inserts @p items into the list of possible completions. |
412 | * It does the same as setItems(), but without calling clear() before. |
413 | * @param items the items to insert |
414 | */ |
415 | void insertItems(const QStringList &items); |
416 | |
417 | /** |
418 | * Sets the list of items available for completion. Removes all previous |
419 | * items. |
420 | * |
421 | * @note When order() == Weighted, then the weighting is looked up for |
422 | * every item in the stringlist. Every item should have ":number" appended, |
423 | * where number is an unsigned integer, specifying the weighting. |
424 | * If you don't like this, call |
425 | * setOrder(KCompletion::Insertion) |
426 | * before calling setItems(). |
427 | * |
428 | * @param itemList the list of items that are available for completion |
429 | * @see items |
430 | */ |
431 | virtual void setItems(const QStringList &itemList); |
432 | |
433 | /** |
434 | * Adds an item to the list of available completions. |
435 | * Resets the current item state (previousMatch() and nextMatch() |
436 | * won't work the next time they are called). |
437 | * @param item the item to add |
438 | */ |
439 | void addItem(const QString &item); |
440 | |
441 | /** |
442 | * Adds an item to the list of available completions. |
443 | * Resets the current item state (previousMatch() and nextMatch() |
444 | * won't work the next time they are called). |
445 | * |
446 | * Sets the weight of the item to @p weight or adds it to the current |
447 | * weight if the item is already available. The weight has to be greater |
448 | * than 1 to take effect (default weight is 1). |
449 | * @param item the item to add |
450 | * @param weight the weight of the item, default is 1 |
451 | */ |
452 | void addItem(const QString &item, uint weight); |
453 | |
454 | /** |
455 | * Removes an item from the list of available completions. |
456 | * Resets the current item state (previousMatch() and nextMatch() |
457 | * won't work the next time they are called). |
458 | * @param item the item to remove |
459 | */ |
460 | void removeItem(const QString &item); |
461 | |
462 | /** |
463 | * Removes all inserted items. |
464 | */ |
465 | virtual void clear(); |
466 | |
467 | Q_SIGNALS: |
468 | /** |
469 | * This signal is emitted when a match is found. |
470 | * |
471 | * In particular, makeCompletion(), previousMatch() and nextMatch() |
472 | * all emit this signal; makeCompletion() will only emit it when a |
473 | * match is found, but the other methods will always emit it (and so |
474 | * may emit it with an empty string). |
475 | * |
476 | * @param item the matching item, or QString() if there were no more |
477 | * matching items. |
478 | */ |
479 | void match(const QString &item); |
480 | |
481 | /** |
482 | * This signal is emitted by makeCompletion() in shell-completion mode |
483 | * when the same string is passed to makeCompletion() multiple times in |
484 | * a row. |
485 | * @param matchlist the list of all matching items |
486 | */ |
487 | void matches(const QStringList &matchlist); |
488 | |
489 | /** |
490 | * This signal is emitted when calling makeCompletion() and more than |
491 | * one matching item is found. |
492 | * @see hasMultipleMatches |
493 | */ |
494 | void multipleMatches(); |
495 | |
496 | protected: |
497 | /** |
498 | * This method is called after a completion is found and before the |
499 | * matching string is emitted. You can override this method to modify the |
500 | * string that will be emitted. |
501 | * This is necessary e.g. in KUrlCompletion(), where files with spaces |
502 | * in their names are shown escaped ("filename\ with\ spaces"), but stored |
503 | * unescaped inside KCompletion. |
504 | * Never delete that pointer! |
505 | * |
506 | * Default implementation does nothing. |
507 | * @param match the match to process |
508 | * @see postProcessMatches |
509 | */ |
510 | virtual void postProcessMatch(QString *match) const; |
511 | |
512 | /** |
513 | * This method is called before a list of all available completions is |
514 | * emitted via matches(). You can override this method to modify the |
515 | * found items before match() or matches() are emitted. |
516 | * Never delete that pointer! |
517 | * |
518 | * Default implementation does nothing. |
519 | * @param matchList the matches to process |
520 | * @see postProcessMatch |
521 | */ |
522 | virtual void postProcessMatches(QStringList *matchList) const; |
523 | |
524 | /** |
525 | * This method is called before a list of all available completions is |
526 | * emitted via #matches(). You can override this method to modify the |
527 | * found items before #match() or #matches() are emitted. |
528 | * Never delete that pointer! |
529 | * |
530 | * Default implementation does nothing. |
531 | * @param matches the matches to process |
532 | * @see postProcessMatch |
533 | */ |
534 | virtual void postProcessMatches(KCompletionMatches *matches) const; |
535 | |
536 | /** |
537 | * Deriving classes may set this property and control whether the auto-suggestion should be displayed |
538 | * for the last completion operation performed. |
539 | * |
540 | * Applies for CompletionPopupAuto and CompletionAuto modes. |
541 | * @since 5.87 |
542 | */ |
543 | void setShouldAutoSuggest(bool shouldAutosuggest); |
544 | |
545 | /** |
546 | * Sets a custom function to be used to sort the matches. |
547 | * Can be set to nullptr to use the default sorting logic. |
548 | * |
549 | * Applies for CompOrder::Sorted mode. |
550 | * @since 5.88 |
551 | */ |
552 | void setSorterFunction(SorterFunction sortFunc); |
553 | |
554 | private: |
555 | Q_DISABLE_COPY(KCompletion) |
556 | std::unique_ptr<KCompletionPrivate> const d_ptr; |
557 | }; |
558 | |
559 | #endif // KCOMPLETION_H |
560 | |