cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
560 lines
19 KiB
C++
560 lines
19 KiB
C++
/*
|
|
This file is part of the KDE libraries
|
|
SPDX-FileCopyrightText: 1999, 2000 Carsten Pfeiffer <pfeiffer@kde.org>
|
|
|
|
SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
|
|
#ifndef KCOMPLETION_H
|
|
#define KCOMPLETION_H
|
|
|
|
#include <kcompletion_export.h>
|
|
|
|
#include <QKeySequence>
|
|
#include <QObject>
|
|
#include <QPointer>
|
|
#include <QStringList>
|
|
#include <functional>
|
|
#include <memory>
|
|
|
|
class KCompTreeNode;
|
|
class KCompletionPrivate;
|
|
class KCompletionMatchesWrapper;
|
|
class KCompletionMatches;
|
|
|
|
/**
|
|
* @class KCompletion kcompletion.h KCompletion
|
|
*
|
|
* @short A generic class for completing QStrings
|
|
*
|
|
* This class offers easy use of "auto completion", "manual completion" or
|
|
* "shell completion" on QString objects. A common use is completing filenames
|
|
* or URLs (see KUrlCompletion()).
|
|
* But it is not limited to URL-completion -- everything should be completable!
|
|
* The user should be able to complete email addresses, telephone numbers,
|
|
* commands, SQL queries...
|
|
* Every time your program knows what the user can type into an edit field, you
|
|
* should offer completion. With KCompletion, this is very easy, and if you are
|
|
* using a line edit widget (KLineEdit), it is even easier.
|
|
* Basically, you tell a KCompletion object what strings should be completable
|
|
* and, whenever completion should be invoked, you call makeCompletion().
|
|
* KLineEdit and (an editable) KComboBox even do this automatically for you.
|
|
*
|
|
* KCompletion offers the completed string via the signal match() and
|
|
* all matching strings (when the result is ambiguous) via the method
|
|
* allMatches().
|
|
*
|
|
* Notice: auto completion, shell completion and manual completion work
|
|
* slightly differently:
|
|
*
|
|
* @li auto completion always returns a complete item as match.
|
|
* When more than one matching item is available, it will deliver just
|
|
* the first one (depending on sorting order). Iterating over all matches
|
|
* is possible via nextMatch() and previousMatch().
|
|
*
|
|
* @li popup completion works in the same way, the only difference being that
|
|
* the completed items are not put into the edit widget, but into a
|
|
* separate popup box.
|
|
*
|
|
* @li manual completion works the same way as auto completion, except that
|
|
* it is not invoked automatically while the user is typing,
|
|
* but only when the user presses a special key. The difference
|
|
* of manual and auto completion is therefore only visible in UI classes.
|
|
* KCompletion needs to know whether to deliver partial matches
|
|
* (shell completion) or whole matches (auto/manual completion), therefore
|
|
* KCompletion::CompletionMan and KCompletion::CompletionAuto have the exact
|
|
* same effect in KCompletion.
|
|
*
|
|
* @li shell completion works like "tab completion" in a shell:
|
|
* when multiple matches are available, the longest possible string of all
|
|
* matches is returned (i.e. only a partial item).
|
|
* Iterating over all matching items (complete, not partial) is possible
|
|
* via nextMatch() and previousMatch().
|
|
*
|
|
* As an application programmer, you do not normally have to worry about
|
|
* the different completion modes; KCompletion handles
|
|
* that for you, according to the setting setCompletionMode().
|
|
* The default setting is globally configured by the user and read
|
|
* from completionMode().
|
|
*
|
|
* A short example:
|
|
* \code
|
|
* KCompletion completion;
|
|
* completion.setOrder(KCompletion::Sorted);
|
|
* completion.addItem("pfeiffer@kde.org");
|
|
* completion.addItem("coolo@kde.org");
|
|
* completion.addItem("carpdjih@sp.zrz.tu-berlin.de");
|
|
* completion.addItem("carp@cs.tu-berlin.de");
|
|
*
|
|
* cout << completion.makeCompletion("ca").latin1() << endl;
|
|
* \endcode
|
|
*
|
|
* In shell-completion mode, this will be "carp"; in auto-completion
|
|
* mode it will be "carp\@cs.tu-berlin.de", as that is alphabetically
|
|
* smaller.
|
|
* If setOrder was set to Insertion, "carpdjih\@sp.zrz.tu-berlin.de"
|
|
* would be completed in auto-completion mode, as that was inserted before
|
|
* "carp\@cs.tu-berlin.de".
|
|
*
|
|
* You can dynamically update the completable items by removing and adding them
|
|
* whenever you want.
|
|
* For advanced usage, you could even use multiple KCompletion objects. E.g.
|
|
* imagine an editor like kwrite with multiple open files. You could store
|
|
* items of each file in a different KCompletion object, so that you know (and
|
|
* tell the user) where a completion comes from.
|
|
*
|
|
* @note KCompletion does not work with strings that contain 0x0 characters
|
|
* (unicode null), as this is used internally as a delimiter.
|
|
*
|
|
* You may inherit from KCompletion and override makeCompletion() in
|
|
* special cases (like reading directories or urls and then supplying the
|
|
* contents to KCompletion, as KUrlCompletion does), but this is usually
|
|
* not necessary.
|
|
*
|
|
*
|
|
* @author Carsten Pfeiffer <pfeiffer@kde.org>
|
|
*/
|
|
class KCOMPLETION_EXPORT KCompletion : public QObject
|
|
{
|
|
Q_PROPERTY(CompOrder order READ order WRITE setOrder)
|
|
Q_PROPERTY(bool ignoreCase READ ignoreCase WRITE setIgnoreCase)
|
|
Q_PROPERTY(QStringList items READ items WRITE setItems)
|
|
Q_OBJECT
|
|
Q_DECLARE_PRIVATE(KCompletion)
|
|
|
|
public:
|
|
/**
|
|
* This enum describes the completion mode used for by the KCompletion class.
|
|
*
|
|
* @since 5.0
|
|
*/
|
|
enum CompletionMode {
|
|
/**
|
|
* No completion is used.
|
|
*/
|
|
CompletionNone = 1,
|
|
/**
|
|
* Text is automatically filled in whenever possible.
|
|
*/
|
|
CompletionAuto,
|
|
/**
|
|
* Same as automatic, but shortest match is used for completion.
|
|
*/
|
|
CompletionMan,
|
|
/**
|
|
* Completes text much in the same way as a typical *nix shell would.
|
|
*/
|
|
CompletionShell,
|
|
/**
|
|
* Lists all possible matches in a popup list box to choose from.
|
|
*/
|
|
CompletionPopup,
|
|
/**
|
|
* Lists all possible matches in a popup list box to choose from, and automatically
|
|
* fills the result whenever possible.
|
|
*/
|
|
CompletionPopupAuto,
|
|
};
|
|
|
|
/**
|
|
* Constants that represent the order in which KCompletion performs
|
|
* completion lookups.
|
|
*/
|
|
enum CompOrder {
|
|
Sorted, ///< Use alphabetically sorted order or custom sorter logic
|
|
Insertion, ///< Use order of insertion
|
|
Weighted, ///< Use weighted order
|
|
};
|
|
Q_ENUM(CompOrder)
|
|
|
|
/**
|
|
* The sorter function signature. Deriving classes may provide
|
|
* custom sorting logic via the setSorterFunction method.
|
|
*
|
|
* @since 5.88
|
|
*/
|
|
using SorterFunction = std::function<void(QStringList &)>;
|
|
|
|
/**
|
|
* Constructor, nothing special here :)
|
|
*/
|
|
KCompletion();
|
|
|
|
/**
|
|
* Destructor, nothing special here, either.
|
|
*/
|
|
~KCompletion() override;
|
|
|
|
/**
|
|
* Returns a list of all completion items that contain the given @p string.
|
|
* @param string the string to complete
|
|
* @return a list of items which contain @p text as a substring,
|
|
* i.e. not necessarily at the beginning.
|
|
*
|
|
* @see makeCompletion
|
|
*/
|
|
QStringList substringCompletion(const QString &string) const;
|
|
|
|
/**
|
|
* Returns the last match. Might be useful if you need to check whether
|
|
* a completion is different from the last one.
|
|
* @return the last match. QString() is returned when there is no
|
|
* last match.
|
|
*/
|
|
virtual const QString &lastMatch() const;
|
|
|
|
/**
|
|
* Returns a list of all items inserted into KCompletion. This is useful
|
|
* if you need to save the state of a KCompletion object and restore it
|
|
* later.
|
|
*
|
|
* @note When order() == Weighted, then every item in the
|
|
* stringlist has its weight appended, delimited by a colon. E.g. an item
|
|
* "www.kde.org" might look like "www.kde.org:4", where 4 is the weight.
|
|
* This is necessary so that you can save the items along with its
|
|
* weighting on disk and load them back with setItems(), restoring its
|
|
* weight as well. If you really don't want the appended weightings, call
|
|
* setOrder( KCompletion::Insertion ) before calling items().
|
|
*
|
|
* @return a list of all items
|
|
* @see setItems
|
|
*/
|
|
QStringList items() const;
|
|
|
|
/**
|
|
* Returns true if the completion object contains no entries.
|
|
*/
|
|
bool isEmpty() const;
|
|
|
|
/**
|
|
* Sets the completion mode.
|
|
* @param mode the completion mode
|
|
* @see CompletionMode
|
|
*/
|
|
virtual void setCompletionMode(CompletionMode mode);
|
|
|
|
/**
|
|
* Returns the current completion mode.
|
|
*
|
|
* @return the current completion mode, default is CompletionPopup
|
|
* @see setCompletionMode
|
|
* @see CompletionMode
|
|
*/
|
|
CompletionMode completionMode() const;
|
|
|
|
/**
|
|
* KCompletion offers three different ways in which it offers its items:
|
|
* @li in the order of insertion
|
|
* @li sorted alphabetically
|
|
* @li weighted
|
|
*
|
|
* Choosing weighted makes KCompletion perform an implicit weighting based
|
|
* on how often an item is inserted. Imagine a web browser with a location
|
|
* bar, where the user enters URLs. The more often a URL is entered, the
|
|
* higher priority it gets.
|
|
*
|
|
* @note Setting the order to sorted only affects new inserted items,
|
|
* already existing items will stay in the current order. So you probably
|
|
* want to call setOrder(Sorted) before inserting items if you want
|
|
* everything sorted.
|
|
*
|
|
* Default is insertion order.
|
|
* @param order the new order
|
|
* @see order
|
|
*/
|
|
virtual void setOrder(CompOrder order);
|
|
|
|
/**
|
|
* Returns the completion order.
|
|
* @return the current completion order.
|
|
* @see setOrder
|
|
*/
|
|
CompOrder order() const;
|
|
|
|
/**
|
|
* Setting this to true makes KCompletion behave case insensitively.
|
|
* E.g. makeCompletion("CA"); might return "carp\@cs.tu-berlin.de".
|
|
* Default is false (case sensitive).
|
|
* @param ignoreCase true to ignore the case
|
|
* @see ignoreCase
|
|
*/
|
|
virtual void setIgnoreCase(bool ignoreCase);
|
|
|
|
/**
|
|
* Returns whether KCompletion acts case insensitively or not.
|
|
* Default is false (case sensitive).
|
|
* @return true if the case will be ignored
|
|
* @see setIgnoreCase
|
|
*/
|
|
bool ignoreCase() const;
|
|
|
|
/**
|
|
* Informs the caller if they should display the auto-suggestion for the last completion operation performed.
|
|
* Applies for CompletionPopupAuto and CompletionAuto modes.
|
|
* Defaults to true, but deriving classes may set it to false in special cases via "setShouldAutoSuggest".
|
|
* @return true if auto-suggestion should be displayed for the last completion operation performed.
|
|
* @since 5.87
|
|
*/
|
|
bool shouldAutoSuggest() const;
|
|
|
|
/**
|
|
* Returns a list of all items matching the last completed string.
|
|
* It might take some time if you have a @em lot of items.
|
|
* @return a list of all matches for the last completed string.
|
|
* @see substringCompletion
|
|
*/
|
|
QStringList allMatches();
|
|
|
|
/**
|
|
* Returns a list of all items matching @p string.
|
|
* @param string the string to match
|
|
* @return the list of all matches
|
|
*/
|
|
QStringList allMatches(const QString &string);
|
|
|
|
/**
|
|
* Returns a list of all items matching the last completed string.
|
|
* It might take some time if you have a @em lot of items.
|
|
* The matches are returned as KCompletionMatches, which also
|
|
* keeps the weight of the matches, allowing
|
|
* you to modify some matches or merge them with matches
|
|
* from another call to allWeightedMatches(), and sort the matches
|
|
* after that in order to have the matches ordered correctly.
|
|
*
|
|
* @return a list of all completion matches
|
|
* @see substringCompletion
|
|
*/
|
|
KCompletionMatches allWeightedMatches();
|
|
|
|
/**
|
|
* Returns a list of all items matching @p string.
|
|
* @param string the string to match
|
|
* @return a list of all matches
|
|
*/
|
|
KCompletionMatches allWeightedMatches(const QString &string);
|
|
|
|
/**
|
|
* Enables/disables emitting a sound when
|
|
* @li makeCompletion() can't find a match
|
|
* @li there is a partial completion (= multiple matches in
|
|
* Shell-completion mode)
|
|
* @li nextMatch() or previousMatch() hit the last possible
|
|
* match and the list is rotated
|
|
*
|
|
* KNotifyClient() is used to emit the sounds.
|
|
*
|
|
* @param enable true to enable sounds
|
|
* @see soundsEnabled
|
|
*/
|
|
virtual void setSoundsEnabled(bool enable);
|
|
|
|
/**
|
|
* Tells you whether KCompletion will emit sounds on certain occasions.
|
|
* Default is enabled.
|
|
* @return true if sounds are enabled
|
|
* @see setSoundsEnabled
|
|
*/
|
|
bool soundsEnabled() const;
|
|
|
|
/**
|
|
* Returns true when more than one match is found.
|
|
* @return true if there is more than one match
|
|
* @see multipleMatches
|
|
*/
|
|
bool hasMultipleMatches() const;
|
|
|
|
public Q_SLOTS:
|
|
/**
|
|
* Attempts to find an item in the list of available completions
|
|
* that begins with @p string. Will either return the first matching item
|
|
* (if there is more than one match) or QString(), if no match is
|
|
* found.
|
|
*
|
|
* In the latter case, a sound will be emitted, depending on
|
|
* soundsEnabled().
|
|
* If a match is found, it will be emitted via the signal
|
|
* match().
|
|
*
|
|
* If this is called twice or more with the same string while no
|
|
* items were added or removed in the meantime, all available completions
|
|
* will be emitted via the signal matches().
|
|
* This happens only in shell-completion mode.
|
|
*
|
|
* @param string the string to complete
|
|
* @return the matching item, or QString() if there is no matching
|
|
* item.
|
|
* @see substringCompletion
|
|
*/
|
|
virtual QString makeCompletion(const QString &string);
|
|
|
|
/**
|
|
* Returns the next item from the list of matching items.
|
|
* When reaching the beginning, the list is rotated so it will return the
|
|
* last match and a sound is emitted (depending on soundsEnabled()).
|
|
* @return the next item from the list of matching items.
|
|
* When there is no match, QString() is returned and
|
|
* a sound is emitted.
|
|
*/
|
|
QString previousMatch();
|
|
|
|
/**
|
|
* Returns the next item from the list of matching items.
|
|
* When reaching the last item, the list is rotated, so it will return
|
|
* the first match and a sound is emitted (depending on
|
|
* soundsEnabled()).
|
|
* @return the next item from the list of matching items. When there is no
|
|
* match, QString() is returned and a sound is emitted.
|
|
*/
|
|
QString nextMatch();
|
|
|
|
/**
|
|
* Inserts @p items into the list of possible completions.
|
|
* It does the same as setItems(), but without calling clear() before.
|
|
* @param items the items to insert
|
|
*/
|
|
void insertItems(const QStringList &items);
|
|
|
|
/**
|
|
* Sets the list of items available for completion. Removes all previous
|
|
* items.
|
|
*
|
|
* @note When order() == Weighted, then the weighting is looked up for
|
|
* every item in the stringlist. Every item should have ":number" appended,
|
|
* where number is an unsigned integer, specifying the weighting.
|
|
* If you don't like this, call
|
|
* setOrder(KCompletion::Insertion)
|
|
* before calling setItems().
|
|
*
|
|
* @param itemList the list of items that are available for completion
|
|
* @see items
|
|
*/
|
|
virtual void setItems(const QStringList &itemList);
|
|
|
|
/**
|
|
* Adds an item to the list of available completions.
|
|
* Resets the current item state (previousMatch() and nextMatch()
|
|
* won't work the next time they are called).
|
|
* @param item the item to add
|
|
*/
|
|
void addItem(const QString &item);
|
|
|
|
/**
|
|
* Adds an item to the list of available completions.
|
|
* Resets the current item state (previousMatch() and nextMatch()
|
|
* won't work the next time they are called).
|
|
*
|
|
* Sets the weight of the item to @p weight or adds it to the current
|
|
* weight if the item is already available. The weight has to be greater
|
|
* than 1 to take effect (default weight is 1).
|
|
* @param item the item to add
|
|
* @param weight the weight of the item, default is 1
|
|
*/
|
|
void addItem(const QString &item, uint weight);
|
|
|
|
/**
|
|
* Removes an item from the list of available completions.
|
|
* Resets the current item state (previousMatch() and nextMatch()
|
|
* won't work the next time they are called).
|
|
* @param item the item to remove
|
|
*/
|
|
void removeItem(const QString &item);
|
|
|
|
/**
|
|
* Removes all inserted items.
|
|
*/
|
|
virtual void clear();
|
|
|
|
Q_SIGNALS:
|
|
/**
|
|
* This signal is emitted when a match is found.
|
|
*
|
|
* In particular, makeCompletion(), previousMatch() and nextMatch()
|
|
* all emit this signal; makeCompletion() will only emit it when a
|
|
* match is found, but the other methods will always emit it (and so
|
|
* may emit it with an empty string).
|
|
*
|
|
* @param item the matching item, or QString() if there were no more
|
|
* matching items.
|
|
*/
|
|
void match(const QString &item);
|
|
|
|
/**
|
|
* This signal is emitted by makeCompletion() in shell-completion mode
|
|
* when the same string is passed to makeCompletion() multiple times in
|
|
* a row.
|
|
* @param matchlist the list of all matching items
|
|
*/
|
|
void matches(const QStringList &matchlist);
|
|
|
|
/**
|
|
* This signal is emitted when calling makeCompletion() and more than
|
|
* one matching item is found.
|
|
* @see hasMultipleMatches
|
|
*/
|
|
void multipleMatches();
|
|
|
|
protected:
|
|
/**
|
|
* This method is called after a completion is found and before the
|
|
* matching string is emitted. You can override this method to modify the
|
|
* string that will be emitted.
|
|
* This is necessary e.g. in KUrlCompletion(), where files with spaces
|
|
* in their names are shown escaped ("filename\ with\ spaces"), but stored
|
|
* unescaped inside KCompletion.
|
|
* Never delete that pointer!
|
|
*
|
|
* Default implementation does nothing.
|
|
* @param match the match to process
|
|
* @see postProcessMatches
|
|
*/
|
|
virtual void postProcessMatch(QString *match) const;
|
|
|
|
/**
|
|
* This method is called before a list of all available completions is
|
|
* emitted via matches(). You can override this method to modify the
|
|
* found items before match() or matches() are emitted.
|
|
* Never delete that pointer!
|
|
*
|
|
* Default implementation does nothing.
|
|
* @param matchList the matches to process
|
|
* @see postProcessMatch
|
|
*/
|
|
virtual void postProcessMatches(QStringList *matchList) const;
|
|
|
|
/**
|
|
* This method is called before a list of all available completions is
|
|
* emitted via #matches(). You can override this method to modify the
|
|
* found items before #match() or #matches() are emitted.
|
|
* Never delete that pointer!
|
|
*
|
|
* Default implementation does nothing.
|
|
* @param matches the matches to process
|
|
* @see postProcessMatch
|
|
*/
|
|
virtual void postProcessMatches(KCompletionMatches *matches) const;
|
|
|
|
/**
|
|
* Deriving classes may set this property and control whether the auto-suggestion should be displayed
|
|
* for the last completion operation performed.
|
|
*
|
|
* Applies for CompletionPopupAuto and CompletionAuto modes.
|
|
* @since 5.87
|
|
*/
|
|
void setShouldAutoSuggest(bool shouldAutosuggest);
|
|
|
|
/**
|
|
* Sets a custom function to be used to sort the matches.
|
|
* Can be set to nullptr to use the default sorting logic.
|
|
*
|
|
* Applies for CompOrder::Sorted mode.
|
|
* @since 5.88
|
|
*/
|
|
void setSorterFunction(SorterFunction sortFunc);
|
|
|
|
private:
|
|
Q_DISABLE_COPY(KCompletion)
|
|
std::unique_ptr<KCompletionPrivate> const d_ptr;
|
|
};
|
|
|
|
#endif // KCOMPLETION_H
|