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