eric7/EricWidgets/EricSpellCheckedTextEdit.py

branch
eric7
changeset 8432
074407b4c107
parent 8431
bed315a45088
child 8629
1b58dc890b87
equal deleted inserted replaced
8431:bed315a45088 8432:074407b4c107
23 from PyQt6.QtGui import ( 23 from PyQt6.QtGui import (
24 QAction, QActionGroup, QSyntaxHighlighter, QTextBlockUserData, 24 QAction, QActionGroup, QSyntaxHighlighter, QTextBlockUserData,
25 QTextCharFormat, QTextCursor 25 QTextCharFormat, QTextCursor
26 ) 26 )
27 from PyQt6.QtWidgets import QMenu, QTextEdit, QPlainTextEdit 27 from PyQt6.QtWidgets import QMenu, QTextEdit, QPlainTextEdit
28
29 # TODO: add user dictionaries with respective menu entries
30 28
31 if ENCHANT_AVAILABLE: 29 if ENCHANT_AVAILABLE:
32 class SpellCheckMixin(): 30 class SpellCheckMixin():
33 """ 31 """
34 Class implementing the spell-check mixin for the widget classes. 32 Class implementing the spell-check mixin for the widget classes.
89 menu = self.createStandardContextMenu(pos) 87 menu = self.createStandardContextMenu(pos)
90 88
91 # Add a submenu for setting the spell-check language and 89 # Add a submenu for setting the spell-check language and
92 # document format. 90 # document format.
93 menu.addSeparator() 91 menu.addSeparator()
92 self.__addRemoveEntry(self.__cursorForPosition(pos), menu)
94 menu.addMenu(self.__createLanguagesMenu(menu)) 93 menu.addMenu(self.__createLanguagesMenu(menu))
95 menu.addMenu(self.__createFormatsMenu(menu)) 94 menu.addMenu(self.__createFormatsMenu(menu))
96 95
97 # Try to retrieve a menu of corrections for the right-clicked word 96 # Try to retrieve a menu of corrections for the right-clicked word
98 spellMenu = self.__createCorrectionsMenu( 97 spellMenu = self.__createCorrectionsMenu(
130 parent) 129 parent)
131 for word in suggestions: 130 for word in suggestions:
132 act = spellMenu.addAction(word) 131 act = spellMenu.addAction(word)
133 act.setData((cursor, word)) 132 act.setData((cursor, word))
134 133
135 # Only return the menu if it's non-empty 134 if suggestions:
136 if spellMenu.actions(): 135 spellMenu.addSeparator()
137 spellMenu.triggered.connect(self.__correctWord) 136
138 return spellMenu 137 # add management entry
139 138 act = spellMenu.addAction(QCoreApplication.translate(
140 return None 139 "SpellCheckMixin", "Add to Dictionary"))
140 act.setData((cursor, text, "add"))
141
142 spellMenu.triggered.connect(self.__spellMenuTriggered)
143 return spellMenu
144
145 def __addRemoveEntry(self, cursor, menu):
146 """
147 Private method to create a menu entry to remove the word at the
148 menu position.
149
150 @param cursor reference to the text cursor for the misspelled word
151 @type QTextCursor
152 @param menu reference to the context menu
153 @type QMenu
154 """
155 if cursor is None:
156 return
157
158 text = cursor.selectedText()
159 menu.addAction(QCoreApplication.translate(
160 "SpellCheckMixin",
161 "Remove '{0}' from Dictionary").format(text),
162 lambda: self.__addToUserDict(text, "remove"))
141 163
142 def __createLanguagesMenu(self, parent=None): 164 def __createLanguagesMenu(self, parent=None):
143 """ 165 """
144 Private method to create a menu for selecting the spell-check 166 Private method to create a menu for selecting the spell-check
145 language. 167 language.
160 act.setCheckable(True) 182 act.setCheckable(True)
161 act.setChecked(language.lower() == curLanguage) 183 act.setChecked(language.lower() == curLanguage)
162 act.setData(language) 184 act.setData(language)
163 languageMenu.addAction(act) 185 languageMenu.addAction(act)
164 186
165 # TODO: add action to add a word to the lists
166 languageMenu.triggered.connect(self.__setLanguage) 187 languageMenu.triggered.connect(self.__setLanguage)
167 return languageMenu 188 return languageMenu
168 189
169 def __createFormatsMenu(self, parent=None): 190 def __createFormatsMenu(self, parent=None):
170 """ 191 """
194 formatMenu.addAction(act) 215 formatMenu.addAction(act)
195 216
196 formatMenu.triggered.connect(self.__setFormat) 217 formatMenu.triggered.connect(self.__setFormat)
197 return formatMenu 218 return formatMenu
198 219
220 def __cursorForPosition(self, pos):
221 """
222 Private method to create a text cursor selecting the word at the
223 given position.
224
225 @param pos position of the misspelled word
226 @type QPoint
227 @return text cursor for the word
228 @rtype QTextCursor
229 """
230 cursor = self.cursorForPosition(pos)
231 cursor.select(QTextCursor.SelectionType.WordUnderCursor)
232
233 if cursor.hasSelection():
234 return cursor
235 else:
236 return None
237
199 def __cursorForMisspelling(self, pos): 238 def __cursorForMisspelling(self, pos):
200 """ 239 """
201 Private method to create a text cursor selecting the misspelled 240 Private method to create a text cursor selecting the misspelled
202 word. 241 word.
203 242
224 if cursor.hasSelection(): 263 if cursor.hasSelection():
225 return cursor 264 return cursor
226 else: 265 else:
227 return None 266 return None
228 267
229 @pyqtSlot(QAction) 268 def __correctWord(self, cursor, word):
230 def __correctWord(self, act): 269 """
231 """ 270 Private method to replace some misspelled text.
232 Private slot to correct the misspelled word with the selected 271
233 correction. 272 @param cursor reference to the text cursor for the misspelled word
234 273 @type QTextCursor
235 @param act reference to the selected action 274 @param word replacement text
236 @type QAction 275 @type str
237 """ 276 """
238 cursor, word = act.data()
239
240 cursor.beginEditBlock() 277 cursor.beginEditBlock()
241 cursor.removeSelectedText() 278 cursor.removeSelectedText()
242 cursor.insertText(word) 279 cursor.insertText(word)
243 cursor.endEditBlock() 280 cursor.endEditBlock()
281
282 def __addToUserDict(self, word, command):
283 """
284 Private method to add a word to the user word or exclude list.
285
286 @param word text to be added
287 @type str
288 @param command command indicating the user dictionary type
289 @type str
290 """
291 if word:
292 dictionary = self.__highlighter.dict()
293 if command == "add":
294 dictionary.add(word)
295 elif command == "remove":
296 dictionary.remove(word)
297
298 self.__highlighter.rehighlight()
299
300 @pyqtSlot(QAction)
301 def __spellMenuTriggered(self, act):
302 """
303 Private slot to handle a selection of the spell menu.
304
305 @param act reference to the selected action
306 @type QAction
307 """
308 data = act.data()
309 if len(data) == 2:
310 # replace the misspelled word
311 self.__correctWord(*data)
312
313 elif len(data) == 3:
314 # dictionary management action
315 _, word, command = data
316 self.__addToUserDict(word, command)
244 317
245 @pyqtSlot(QAction) 318 @pyqtSlot(QAction)
246 def __setLanguage(self, act): 319 def __setLanguage(self, act):
247 """ 320 """
248 Private slot to set the selected language. 321 Private slot to set the selected language.
298 @type emchant.Dict 371 @type emchant.Dict
299 """ 372 """
300 self.__highlighter.setDict(spellDict) 373 self.__highlighter.setDict(spellDict)
301 374
302 @classmethod 375 @classmethod
303 def setDefaultLanguage(cls, language, pwl="", pel=""): 376 def setDefaultLanguage(cls, language, pwl=None, pel=None):
304 """ 377 """
305 Class method to set the default spell-check language. 378 Class method to set the default spell-check language.
306 379
307 @param language language to be set as default 380 @param language language to be set as default
308 @type str 381 @type str
309 @param pwl file name of the personal word list 382 @param pwl file name of the personal word list
310 @type str 383 @type str
311 @param pel name of the personal exclude list 384 @param pel file name of the personal exclude list
312 @type str 385 @type str
313 """ 386 """
314 with contextlib.suppress(DictNotFoundError): 387 with contextlib.suppress(DictNotFoundError):
315 cls.DefaultUserWordList = pwl 388 cls.DefaultUserWordList = pwl
316 cls.DefaultUserExceptionList = pel 389 cls.DefaultUserExceptionList = pel
465 EricSpellCheckedPlainTextEdit = QPlainTextEdit 538 EricSpellCheckedPlainTextEdit = QPlainTextEdit
466 EricSpellCheckedTextEdit = QTextEdit 539 EricSpellCheckedTextEdit = QTextEdit
467 540
468 if __name__ == '__main__': 541 if __name__ == '__main__':
469 import sys 542 import sys
543 import os
470 from PyQt6.QtWidgets import QApplication 544 from PyQt6.QtWidgets import QApplication
471 545
472 if ENCHANT_AVAILABLE: 546 if ENCHANT_AVAILABLE:
473 SpellCheckMixin.setDefaultLanguage("en_US") 547 dictPath = os.path.expanduser(os.path.join("~", ".eric7", "spelling"))
548 SpellCheckMixin.setDefaultLanguage(
549 "en_US",
550 os.path.join(dictPath, "pwl.dic"),
551 os.path.join(dictPath, "pel.dic")
552 )
474 553
475 app = QApplication(sys.argv) 554 app = QApplication(sys.argv)
476 spellEdit = EricSpellCheckedPlainTextEdit() 555 spellEdit = EricSpellCheckedPlainTextEdit()
477 spellEdit.show() 556 spellEdit.show()
478 557

eric ide

mercurial