1 from __future__
import absolute_import
, division
, print_function
, unicode_literals
4 from qtpy
.QtCore
import Qt
5 from qtpy
.QtCore
import QEvent
6 from qtpy
.QtCore
import Signal
7 from qtpy
.QtGui
import QMouseEvent
8 from qtpy
.QtGui
import QSyntaxHighlighter
9 from qtpy
.QtGui
import QTextCharFormat
10 from qtpy
.QtGui
import QTextCursor
11 from qtpy
.QtWidgets
import QAction
13 from .. import qtutils
14 from .. import spellcheck
16 from .text
import HintedTextEdit
19 # pylint: disable=too-many-ancestors
20 class SpellCheckTextEdit(HintedTextEdit
):
21 def __init__(self
, context
, hint
, parent
=None):
22 HintedTextEdit
.__init
__(self
, context
, hint
, parent
)
24 # Default dictionary based on the current locale.
25 self
.spellcheck
= spellcheck
.NorvigSpellCheck()
26 self
.highlighter
= Highlighter(self
.document(), self
.spellcheck
)
28 def set_dictionary(self
, dictionary
):
29 self
.spellcheck
.set_dictionary(dictionary
)
31 def mousePressEvent(self
, event
):
32 if event
.button() == Qt
.RightButton
:
33 # Rewrite the mouse event to a left button event so the cursor is
34 # moved to the location of the pointer.
36 QEvent
.MouseButtonPress
,
42 HintedTextEdit
.mousePressEvent(self
, event
)
44 def context_menu(self
):
45 popup_menu
= HintedTextEdit
.createStandardContextMenu(self
)
47 # Select the word under the cursor.
48 cursor
= self
.textCursor()
49 cursor
.select(QTextCursor
.WordUnderCursor
)
50 self
.setTextCursor(cursor
)
52 # Check if the selected word is misspelled and offer spelling
53 # suggestions if it is.
55 if self
.textCursor().hasSelection():
56 text
= self
.textCursor().selectedText()
57 if not self
.spellcheck
.check(text
):
58 title
= N_('Spelling Suggestions')
59 spell_menu
= qtutils
.create_menu(title
, self
)
60 for word
in self
.spellcheck
.suggest(text
):
61 action
= SpellAction(word
, spell_menu
)
62 action
.result
.connect(self
.correct
)
63 spell_menu
.addAction(action
)
64 # Only add the spelling suggests to the menu if there are
66 if spell_menu
.actions():
67 popup_menu
.addSeparator()
68 popup_menu
.addMenu(spell_menu
)
70 return popup_menu
, spell_menu
72 def contextMenuEvent(self
, event
):
73 popup_menu
, _
= self
.context_menu()
74 popup_menu
.exec_(self
.mapToGlobal(event
.pos()))
76 def correct(self
, word
):
77 """Replaces the selected text with word."""
78 cursor
= self
.textCursor()
79 cursor
.beginEditBlock()
81 cursor
.removeSelectedText()
82 cursor
.insertText(word
)
87 class Highlighter(QSyntaxHighlighter
):
89 WORDS
= r
"(?iu)[\w']+"
91 def __init__(self
, doc
, spellcheck_widget
):
92 QSyntaxHighlighter
.__init
__(self
, doc
)
93 self
.spellcheck
= spellcheck_widget
96 def enable(self
, enabled
):
97 self
.enabled
= enabled
100 def highlightBlock(self
, text
):
103 fmt
= QTextCharFormat()
104 fmt
.setUnderlineColor(Qt
.red
)
105 fmt
.setUnderlineStyle(QTextCharFormat
.SpellCheckUnderline
)
107 for word_object
in re
.finditer(self
.WORDS
, text
):
108 if not self
.spellcheck
.check(word_object
.group()):
110 word_object
.start(), word_object
.end() - word_object
.start(), fmt
114 class SpellAction(QAction
):
115 """QAction that returns the text in a signal."""
117 result
= Signal(object)
119 def __init__(self
, *args
):
120 QAction
.__init
__(self
, *args
)
121 # pylint: disable=no-member
122 self
.triggered
.connect(self
.correct
)
125 self
.result
.emit(self
.text())