File indexing completed on 2024-04-21 03:57:41

0001 /*
0002     SPDX-FileCopyrightText: 2008-2010 Michel Ludwig <michel.ludwig@kdemail.net>
0003     SPDX-FileCopyrightText: 2009 Joseph Wenninger <jowenn@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef ONTHEFLYCHECK_H
0009 #define ONTHEFLYCHECK_H
0010 
0011 #include <QList>
0012 #include <QObject>
0013 #include <QPair>
0014 #include <QSet>
0015 #include <QString>
0016 #include <map>
0017 
0018 #include <sonnet/speller.h>
0019 
0020 #include "katedocument.h"
0021 
0022 namespace Sonnet
0023 {
0024 class BackgroundChecker;
0025 }
0026 
0027 class KateOnTheFlyChecker : public QObject, private KTextEditor::MovingRangeFeedback
0028 {
0029     enum ModificationType { TEXT_INSERTED = 0, TEXT_REMOVED };
0030 
0031     typedef QPair<KTextEditor::MovingRange *, QString> SpellCheckItem;
0032     typedef QList<KTextEditor::MovingRange *> MovingRangeList;
0033     typedef QPair<KTextEditor::MovingRange *, QString> MisspelledItem;
0034     typedef QList<MisspelledItem> MisspelledList;
0035 
0036     typedef QPair<ModificationType, KTextEditor::MovingRange *> ModificationItem;
0037     typedef QList<ModificationItem> ModificationList;
0038 
0039 public:
0040     explicit KateOnTheFlyChecker(KTextEditor::DocumentPrivate *document);
0041     ~KateOnTheFlyChecker() override;
0042 
0043     QPair<KTextEditor::Range, QString> getMisspelledItem(const KTextEditor::Cursor cursor) const;
0044     QString dictionaryForMisspelledRange(KTextEditor::Range range) const;
0045     MovingRangeList installedMovingRanges(KTextEditor::Range range) const;
0046 
0047     void clearMisspellingForWord(const QString &word);
0048 
0049 public:
0050     void textInserted(KTextEditor::Document *document, KTextEditor::Range range);
0051     void textRemoved(KTextEditor::Document *document, KTextEditor::Range range);
0052 
0053     void updateConfig();
0054     void refreshSpellCheck(KTextEditor::Range range = KTextEditor::Range::invalid());
0055 
0056     void updateInstalledMovingRanges(KTextEditor::ViewPrivate *view);
0057 
0058 protected:
0059     KTextEditor::DocumentPrivate *const m_document;
0060     Sonnet::Speller m_speller;
0061     QList<SpellCheckItem> m_spellCheckQueue;
0062     Sonnet::BackgroundChecker *m_backgroundChecker;
0063     SpellCheckItem m_currentlyCheckedItem;
0064     MisspelledList m_misspelledList;
0065     ModificationList m_modificationList;
0066     KTextEditor::DocumentPrivate::OffsetList m_currentDecToEncOffsetList;
0067     std::map<KTextEditor::View *, KTextEditor::Range> m_displayRangeMap;
0068 
0069     void freeDocument();
0070 
0071     void queueLineSpellCheck(KTextEditor::DocumentPrivate *document, int line);
0072     /**
0073      * 'range' must be on a single line
0074      **/
0075     void queueLineSpellCheck(KTextEditor::Range range, const QString &dictionary);
0076     void queueSpellCheckVisibleRange(KTextEditor::Range range);
0077     void queueSpellCheckVisibleRange(KTextEditor::ViewPrivate *view, KTextEditor::Range range);
0078 
0079     void addToSpellCheckQueue(KTextEditor::Range range, const QString &dictionary);
0080     void addToSpellCheckQueue(KTextEditor::MovingRange *range, const QString &dictionary);
0081 
0082     QTimer *m_viewRefreshTimer;
0083     QPointer<KTextEditor::ViewPrivate> m_refreshView;
0084 
0085     virtual void removeRangeFromEverything(KTextEditor::MovingRange *range);
0086     bool removeRangeFromCurrentSpellCheck(KTextEditor::MovingRange *range);
0087     bool removeRangeFromSpellCheckQueue(KTextEditor::MovingRange *range);
0088     void rangeEmpty(KTextEditor::MovingRange *range) override;
0089     void rangeInvalid(KTextEditor::MovingRange *range) override;
0090     void caretEnteredRange(KTextEditor::MovingRange *range, KTextEditor::View *view) override;
0091     void caretExitedRange(KTextEditor::MovingRange *range, KTextEditor::View *view) override;
0092 
0093     KTextEditor::Range findWordBoundaries(const KTextEditor::Cursor begin, const KTextEditor::Cursor end);
0094 
0095     void deleteMovingRange(KTextEditor::MovingRange *range);
0096     void deleteMovingRanges(const QList<KTextEditor::MovingRange *> &list);
0097     void deleteMovingRangeQuickly(KTextEditor::MovingRange *range);
0098     void stopCurrentSpellCheck();
0099 
0100 protected:
0101     void performSpellCheck();
0102     void addToDictionary(const QString &word);
0103     void addToSession(const QString &word);
0104     void misspelling(const QString &word, int start);
0105     void spellCheckDone();
0106 
0107     void viewDestroyed(QObject *obj);
0108     void addView(KTextEditor::Document *document, KTextEditor::View *view);
0109     void removeView(KTextEditor::View *view);
0110 
0111     void restartViewRefreshTimer(KTextEditor::ViewPrivate *view);
0112     void viewRefreshTimeout();
0113 
0114     void handleModifiedRanges();
0115     void handleInsertedText(KTextEditor::Range range);
0116     void handleRemovedText(KTextEditor::Range range);
0117     void handleRespellCheckBlock(int start, int end);
0118     bool removeRangeFromModificationList(KTextEditor::MovingRange *range);
0119     void clearModificationList();
0120 };
0121 
0122 #endif