spelling_highlighter.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include <QtWidgets/QWidget> // input_fields.h
  9. #include "base/timer.h"
  10. #include "spellcheck/platform/platform_spellcheck.h"
  11. #include "spellcheck/spellcheck_types.h"
  12. #include "ui/widgets/fields/input_field.h"
  13. #include <QtGui/QSyntaxHighlighter>
  14. #include <QtGui/QTextBlock>
  15. #include <QtWidgets/QMenu>
  16. #include <QtWidgets/QTextEdit>
  17. #include <rpl/event_stream.h>
  18. namespace Ui {
  19. struct ExtendedContextMenu;
  20. class PopupMenu;
  21. } // namespace Ui
  22. namespace Spellchecker {
  23. class SpellingHighlighter final : public QSyntaxHighlighter {
  24. public:
  25. struct CustomContextMenuItem {
  26. QString title;
  27. Fn<void()> callback;
  28. };
  29. SpellingHighlighter(
  30. not_null<Ui::InputField*> field,
  31. rpl::producer<bool> enabled,
  32. std::optional<CustomContextMenuItem> customContextMenuItem
  33. = std::nullopt);
  34. void contentsChange(int pos, int removed, int added);
  35. void checkCurrentText();
  36. bool enabled();
  37. auto contextMenuCreated() {
  38. return _contextMenuCreated.events();
  39. }
  40. // Windows system spellchecker forces us to perform spell operations
  41. // In another thread, so the word check and getting a list of suggestions
  42. // Are run asynchronously.
  43. // And then the context menu is filled in the main thread.
  44. void addSpellcheckerActions(
  45. not_null<QMenu*> parentMenu,
  46. QTextCursor cursorForPosition,
  47. Fn<void()> showMenuCallback,
  48. QPoint mousePosition);
  49. void fillSpellcheckerMenu(
  50. not_null<QMenu*> menu,
  51. QTextCursor cursorForPosition,
  52. FnMut<void(int firstSuggestionIndex)> show);
  53. protected:
  54. void highlightBlock(const QString &text) override;
  55. bool eventFilter(QObject *o, QEvent *e) override;
  56. private:
  57. void updatePalette();
  58. void setEnabled(bool enabled);
  59. void checkText(const QString &text);
  60. void showSpellcheckerMenu();
  61. void invokeCheckText(
  62. int textPosition,
  63. int textLength,
  64. Fn<void(MisspelledWords &&ranges)> callback);
  65. void checkChangedText();
  66. void checkSingleWord(const MisspelledWord &singleWord);
  67. MisspelledWords filterSkippableWords(MisspelledWords &ranges);
  68. bool isSkippableWord(const MisspelledWord &range);
  69. bool isSkippableWord(int position, int length);
  70. bool hasUnspellcheckableTag(int begin, int length);
  71. MisspelledWord getWordUnderPosition(int position);
  72. QString documentText();
  73. void updateDocumentText();
  74. QString partDocumentText(int pos, int length);
  75. int compareDocumentText(const QString &text, int textPos, int textLen);
  76. QString _lastPlainText;
  77. std::vector<QTextBlock> blocksFromRange(int pos, int length);
  78. int size();
  79. QTextBlock findBlock(int pos);
  80. int _countOfCheckingTextAsync = 0;
  81. QTextCharFormat _misspelledFormat;
  82. QTextCursor _cursor;
  83. MisspelledWords _cachedRanges;
  84. EntitiesInText _cachedSkippableEntities;
  85. int _addedSymbols = 0;
  86. int _removedSymbols = 0;
  87. int _lastPosition = 0;
  88. bool _enabled = true;
  89. bool _isLastKeyRepeat = false;
  90. base::Timer _coldSpellcheckingTimer;
  91. not_null<Ui::InputField*> _field;
  92. not_null<QTextEdit*> _textEdit;
  93. base::unique_qptr<Ui::PopupMenu> _menu;
  94. const std::optional<CustomContextMenuItem> _customContextMenuItem;
  95. rpl::lifetime _lifetime;
  96. using ContextMenu = Ui::InputField::ExtendedContextMenu;
  97. rpl::event_stream<ContextMenu> _contextMenuCreated;
  98. };
  99. } // namespace Spellchecker