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
20class KCompTreeNode;
21class KCompletionPrivate;
22class KCompletionMatchesWrapper;
23class 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 */
117class 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
125public:
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 CompletionPopup,
152 /**
153 * Lists all possible matches in a popup list box to choose from, and automatically
154 * fills the result whenever possible.
155 */
156 CompletionPopupAuto,
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
366public 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
467Q_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
496protected:
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
554private:
555 Q_DISABLE_COPY(KCompletion)
556 std::unique_ptr<KCompletionPrivate> const d_ptr;
557};
558
559#endif // KCOMPLETION_H
560

source code of kcompletion/src/kcompletion.h