2 from __future__
import division
, absolute_import
, unicode_literals
5 from qtpy
.QtCore
import Qt
6 from qtpy
.QtCore
import QEvent
7 from qtpy
.QtCore
import Signal
8 from qtpy
.QtGui
import QMouseEvent
9 from qtpy
.QtGui
import QSyntaxHighlighter
10 from qtpy
.QtGui
import QTextCharFormat
11 from qtpy
.QtGui
import QTextCursor
12 from qtpy
.QtWidgets
import QAction
14 from .. import qtutils
15 from .. import spellcheck
17 from .text
import HintedTextEdit
20 # pylint: disable=too-many-ancestors
21 class SpellCheckTextEdit(HintedTextEdit
):
22 def __init__(self
, context
, hint
, parent
=None):
23 HintedTextEdit
.__init
__(self
, context
, hint
, parent
)
25 # Default dictionary based on the current locale.
26 self
.spellcheck
= spellcheck
.NorvigSpellCheck()
27 self
.highlighter
= Highlighter(self
.document(), self
.spellcheck
)
29 def set_dictionary(self
, dictionary
):
30 self
.spellcheck
.set_dictionary(dictionary
)
32 def mousePressEvent(self
, event
):
33 if event
.button() == Qt
.RightButton
:
34 # Rewrite the mouse event to a left button event so the cursor is
35 # moved to the location of the pointer.
37 QEvent
.MouseButtonPress
,
43 HintedTextEdit
.mousePressEvent(self
, event
)
45 def context_menu(self
):
46 popup_menu
= HintedTextEdit
.createStandardContextMenu(self
)
48 # Select the word under the cursor.
49 cursor
= self
.textCursor()
50 cursor
.select(QTextCursor
.WordUnderCursor
)
51 self
.setTextCursor(cursor
)
53 # Check if the selected word is misspelled and offer spelling
54 # suggestions if it is.
56 if self
.textCursor().hasSelection():
57 text
= self
.textCursor().selectedText()
58 if not self
.spellcheck
.check(text
):
59 title
= N_('Spelling Suggestions')
60 spell_menu
= qtutils
.create_menu(title
, self
)
61 for word
in self
.spellcheck
.suggest(text
):
62 action
= SpellAction(word
, spell_menu
)
63 action
.result
.connect(self
.correct
)
64 spell_menu
.addAction(action
)
65 # Only add the spelling suggests to the menu if there are
67 if spell_menu
.actions():
68 popup_menu
.addSeparator()
69 popup_menu
.addMenu(spell_menu
)
71 return popup_menu
, spell_menu
73 def contextMenuEvent(self
, event
):
74 popup_menu
, _
= self
.context_menu()
75 popup_menu
.exec_(self
.mapToGlobal(event
.pos()))
77 def correct(self
, word
):
78 """Replaces the selected text with word."""
79 cursor
= self
.textCursor()
80 cursor
.beginEditBlock()
82 cursor
.removeSelectedText()
83 cursor
.insertText(word
)
88 class Highlighter(QSyntaxHighlighter
):
90 WORDS
= r
"(?iu)[\w']+"
92 def __init__(self
, doc
, spellcheck_widget
):
93 QSyntaxHighlighter
.__init
__(self
, doc
)
94 self
.spellcheck
= spellcheck_widget
97 def enable(self
, enabled
):
98 self
.enabled
= enabled
101 def highlightBlock(self
, text
):
104 fmt
= QTextCharFormat()
105 fmt
.setUnderlineColor(Qt
.red
)
106 fmt
.setUnderlineStyle(QTextCharFormat
.SpellCheckUnderline
)
108 for word_object
in re
.finditer(self
.WORDS
, text
):
109 if not self
.spellcheck
.check(word_object
.group()):
111 word_object
.start(), word_object
.end() - word_object
.start(), fmt
115 class SpellAction(QAction
):
116 """QAction that returns the text in a signal."""
118 result
= Signal(object)
120 def __init__(self
, *args
):
121 QAction
.__init
__(self
, *args
)
122 # pylint: disable=no-member
123 self
.triggered
.connect(self
.correct
)
126 self
.result
.emit(self
.text())