File indexing completed on 2024-04-28 15:30:45

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 <QMap>
0013 #include <QObject>
0014 #include <QPair>
0015 #include <QSet>
0016 #include <QString>
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     Q_OBJECT
0030 
0031     enum ModificationType { TEXT_INSERTED = 0, TEXT_REMOVED };
0032 
0033     typedef QPair<KTextEditor::MovingRange *, QString> SpellCheckItem;
0034     typedef QList<KTextEditor::MovingRange *> MovingRangeList;
0035     typedef QPair<KTextEditor::MovingRange *, QString> MisspelledItem;
0036     typedef QList<MisspelledItem> MisspelledList;
0037 
0038     typedef QPair<ModificationType, KTextEditor::MovingRange *> ModificationItem;
0039     typedef QList<ModificationItem> ModificationList;
0040 
0041 public:
0042     explicit KateOnTheFlyChecker(KTextEditor::DocumentPrivate *document);
0043     ~KateOnTheFlyChecker() override;
0044 
0045     QPair<KTextEditor::Range, QString> getMisspelledItem(const KTextEditor::Cursor cursor) const;
0046     QString dictionaryForMisspelledRange(KTextEditor::Range range) const;
0047     MovingRangeList installedMovingRanges(KTextEditor::Range range) const;
0048 
0049     void clearMisspellingForWord(const QString &word);
0050 
0051 public Q_SLOTS:
0052     void textInserted(KTextEditor::Document *document, KTextEditor::Range range);
0053     void textRemoved(KTextEditor::Document *document, KTextEditor::Range range);
0054 
0055     void updateConfig();
0056     void refreshSpellCheck(KTextEditor::Range range = KTextEditor::Range::invalid());
0057 
0058     void updateInstalledMovingRanges(KTextEditor::ViewPrivate *view);
0059 
0060 protected:
0061     KTextEditor::DocumentPrivate *const m_document;
0062     Sonnet::Speller m_speller;
0063     QList<SpellCheckItem> m_spellCheckQueue;
0064     Sonnet::BackgroundChecker *m_backgroundChecker;
0065     SpellCheckItem m_currentlyCheckedItem;
0066     MisspelledList m_misspelledList;
0067     ModificationList m_modificationList;
0068     KTextEditor::DocumentPrivate::OffsetList m_currentDecToEncOffsetList;
0069     QMap<KTextEditor::View *, KTextEditor::Range> m_displayRangeMap;
0070 
0071     void freeDocument();
0072 
0073     void queueLineSpellCheck(KTextEditor::DocumentPrivate *document, int line);
0074     /**
0075      * 'range' must be on a single line
0076      **/
0077     void queueLineSpellCheck(KTextEditor::Range range, const QString &dictionary);
0078     void queueSpellCheckVisibleRange(KTextEditor::Range range);
0079     void queueSpellCheckVisibleRange(KTextEditor::ViewPrivate *view, KTextEditor::Range range);
0080 
0081     void addToSpellCheckQueue(KTextEditor::Range range, const QString &dictionary);
0082     void addToSpellCheckQueue(KTextEditor::MovingRange *range, const QString &dictionary);
0083 
0084     QTimer *m_viewRefreshTimer;
0085     QPointer<KTextEditor::ViewPrivate> m_refreshView;
0086 
0087     virtual void removeRangeFromEverything(KTextEditor::MovingRange *range);
0088     bool removeRangeFromCurrentSpellCheck(KTextEditor::MovingRange *range);
0089     bool removeRangeFromSpellCheckQueue(KTextEditor::MovingRange *range);
0090     void rangeEmpty(KTextEditor::MovingRange *range) override;
0091     void rangeInvalid(KTextEditor::MovingRange *range) override;
0092     void caretEnteredRange(KTextEditor::MovingRange *range, KTextEditor::View *view) override;
0093     void caretExitedRange(KTextEditor::MovingRange *range, KTextEditor::View *view) override;
0094 
0095     KTextEditor::Range findWordBoundaries(const KTextEditor::Cursor begin, const KTextEditor::Cursor end);
0096 
0097     void deleteMovingRange(KTextEditor::MovingRange *range);
0098     void deleteMovingRanges(const QList<KTextEditor::MovingRange *> &list);
0099     void deleteMovingRangeQuickly(KTextEditor::MovingRange *range);
0100     void stopCurrentSpellCheck();
0101 
0102 protected Q_SLOTS:
0103     void performSpellCheck();
0104     void addToDictionary(const QString &word);
0105     void addToSession(const QString &word);
0106     void misspelling(const QString &word, int start);
0107     void spellCheckDone();
0108 
0109     void viewDestroyed(QObject *obj);
0110     void addView(KTextEditor::Document *document, KTextEditor::View *view);
0111     void removeView(KTextEditor::View *view);
0112 
0113     void restartViewRefreshTimer(KTextEditor::ViewPrivate *view);
0114     void viewRefreshTimeout();
0115 
0116     void handleModifiedRanges();
0117     void handleInsertedText(KTextEditor::Range range);
0118     void handleRemovedText(KTextEditor::Range range);
0119     void handleRespellCheckBlock(int start, int end);
0120     bool removeRangeFromModificationList(KTextEditor::MovingRange *range);
0121     void clearModificationList();
0122 };
0123 
0124 #endif