File indexing completed on 2024-05-12 11:47: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 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(5, 0)
0411     /**
0412      * Attempts to complete "string" and emits the completion via match().
0413      * Same as makeCompletion(), but in this case as a slot.
0414      * @param string the string to complete
0415      * @see makeCompletion
0416      * @deprecated since 5.0, use makeCompletion() instead
0417      */
0418     KCOMPLETION_DEPRECATED_VERSION(5, 0, "Use KCompletion::makeCompletion(const QString &)")
0419     void slotMakeCompletion(const QString &string) // inline (redirect)
0420     {
0421         (void)makeCompletion(string);
0422     }
0423 #endif
0424 
0425 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(5, 0)
0426     /**
0427      * Searches the previous matching item and emits it via match().
0428      * Same as previousMatch(), but in this case as a slot.
0429      * @see previousMatch
0430      * @deprecated since 5.0, use previousMatch() instead
0431      */
0432     KCOMPLETION_DEPRECATED_VERSION(5, 0, "Use KCompletion::previousMatch()")
0433     void slotPreviousMatch() // inline (redirect)
0434     {
0435         (void)previousMatch();
0436     }
0437 #endif
0438 
0439 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(5, 0)
0440     /**
0441      * Searches the next matching item and emits it via match().
0442      * Same as nextMatch(), but in this case as a slot.
0443      * @see nextMatch
0444      * @deprecated since 5.0, use nextMatch() instead
0445      */
0446     KCOMPLETION_DEPRECATED_VERSION(5, 0, "Use KCompletion::nextMatch()")
0447     void slotNextMatch() // inline (redirect)
0448     {
0449         (void)nextMatch();
0450     }
0451 #endif
0452 
0453     /**
0454      * Inserts @p items into the list of possible completions.
0455      * It does the same as setItems(), but without calling clear() before.
0456      * @param items the items to insert
0457      */
0458     void insertItems(const QStringList &items);
0459 
0460     /**
0461      * Sets the list of items available for completion. Removes all previous
0462      * items.
0463      *
0464      * @note When order() == Weighted, then the weighting is looked up for
0465      * every item in the stringlist. Every item should have ":number" appended,
0466      * where number is an unsigned integer, specifying the weighting.
0467      * If you don't like this, call
0468      * setOrder(KCompletion::Insertion)
0469      * before calling setItems().
0470      *
0471      * @param itemList the list of items that are available for completion
0472      * @see items
0473      */
0474     virtual void setItems(const QStringList &itemList);
0475 
0476     /**
0477      * Adds an item to the list of available completions.
0478      * Resets the current item state (previousMatch() and nextMatch()
0479      * won't work the next time they are called).
0480      * @param item the item to add
0481      */
0482     void addItem(const QString &item);
0483 
0484     /**
0485      * Adds an item to the list of available completions.
0486      * Resets the current item state (previousMatch() and nextMatch()
0487      * won't work the next time they are called).
0488      *
0489      * Sets the weight of the item to @p weight or adds it to the current
0490      * weight if the item is already available. The weight has to be greater
0491      * than 1 to take effect (default weight is 1).
0492      * @param item the item to add
0493      * @param weight the weight of the item, default is 1
0494      */
0495     void addItem(const QString &item, uint weight);
0496 
0497     /**
0498      * Removes an item from the list of available completions.
0499      * Resets the current item state (previousMatch() and nextMatch()
0500      * won't work the next time they are called).
0501      * @param item the item to remove
0502      */
0503     void removeItem(const QString &item);
0504 
0505     /**
0506      * Removes all inserted items.
0507      */
0508     virtual void clear();
0509 
0510 Q_SIGNALS:
0511     /**
0512      * This signal is emitted when a match is found.
0513      *
0514      * In particular, makeCompletion(), previousMatch() and nextMatch()
0515      * all emit this signal; makeCompletion() will only emit it when a
0516      * match is found, but the other methods will always emit it (and so
0517      * may emit it with an empty string).
0518      *
0519      * @param item the matching item, or QString() if there were no more
0520      * matching items.
0521      */
0522     void match(const QString &item);
0523 
0524     /**
0525      * This signal is emitted by makeCompletion() in shell-completion mode
0526      * when the same string is passed to makeCompletion() multiple times in
0527      * a row.
0528      * @param matchlist the list of all matching items
0529      */
0530     void matches(const QStringList &matchlist);
0531 
0532     /**
0533      * This signal is emitted when calling makeCompletion() and more than
0534      * one matching item is found.
0535      * @see hasMultipleMatches
0536      */
0537     void multipleMatches();
0538 
0539 protected:
0540     /**
0541      * This method is called after a completion is found and before the
0542      * matching string is emitted. You can override this method to modify the
0543      * string that will be emitted.
0544      * This is necessary e.g. in KUrlCompletion(), where files with spaces
0545      * in their names are shown escaped ("filename\ with\ spaces"), but stored
0546      * unescaped inside KCompletion.
0547      * Never delete that pointer!
0548      *
0549      * Default implementation does nothing.
0550      * @param match the match to process
0551      * @see postProcessMatches
0552      */
0553     virtual void postProcessMatch(QString *match) const;
0554 
0555     /**
0556      * This method is called before a list of all available completions is
0557      * emitted via matches(). You can override this method to modify the
0558      * found items before match() or matches() are emitted.
0559      * Never delete that pointer!
0560      *
0561      * Default implementation does nothing.
0562      * @param matchList the matches to process
0563      * @see postProcessMatch
0564      */
0565     virtual void postProcessMatches(QStringList *matchList) const;
0566 
0567     /**
0568      * This method is called before a list of all available completions is
0569      * emitted via #matches(). You can override this method to modify the
0570      * found items before #match() or #matches() are emitted.
0571      * Never delete that pointer!
0572      *
0573      * Default implementation does nothing.
0574      * @param matches the matches to process
0575      * @see postProcessMatch
0576      */
0577     virtual void postProcessMatches(KCompletionMatches *matches) const;
0578 
0579     /**
0580      * Deriving classes may set this property and control whether the auto-suggestion should be displayed
0581      * for the last completion operation performed.
0582      *
0583      * Applies for CompletionPopupAuto and CompletionAuto modes.
0584      * @since 5.87
0585      */
0586     void setShouldAutoSuggest(bool shouldAutosuggest);
0587 
0588     /**
0589      * Sets a custom function to be used to sort the matches.
0590      * Can be set to nullptr to use the default sorting logic.
0591      *
0592      * Applies for CompOrder::Sorted mode.
0593      * @since 5.88
0594      */
0595     void setSorterFunction(SorterFunction sortFunc);
0596 
0597 private:
0598     Q_DISABLE_COPY(KCompletion)
0599     std::unique_ptr<KCompletionPrivate> const d_ptr;
0600 };
0601 
0602 #endif // KCOMPLETION_H