--- a/eric7/EricWidgets/EricSpellCheckedTextEdit.py Thu Jun 17 18:56:21 2021 +0200 +++ b/eric7/EricWidgets/EricSpellCheckedTextEdit.py Sat Jun 19 12:17:17 2021 +0200 @@ -26,8 +26,6 @@ ) from PyQt6.QtWidgets import QMenu, QTextEdit, QPlainTextEdit -# TODO: add user dictionaries with respective menu entries - if ENCHANT_AVAILABLE: class SpellCheckMixin(): """ @@ -91,6 +89,7 @@ # Add a submenu for setting the spell-check language and # document format. menu.addSeparator() + self.__addRemoveEntry(self.__cursorForPosition(pos), menu) menu.addMenu(self.__createLanguagesMenu(menu)) menu.addMenu(self.__createFormatsMenu(menu)) @@ -132,12 +131,35 @@ act = spellMenu.addAction(word) act.setData((cursor, word)) - # Only return the menu if it's non-empty - if spellMenu.actions(): - spellMenu.triggered.connect(self.__correctWord) - return spellMenu + if suggestions: + spellMenu.addSeparator() + + # add management entry + act = spellMenu.addAction(QCoreApplication.translate( + "SpellCheckMixin", "Add to Dictionary")) + act.setData((cursor, text, "add")) - return None + spellMenu.triggered.connect(self.__spellMenuTriggered) + return spellMenu + + def __addRemoveEntry(self, cursor, menu): + """ + Private method to create a menu entry to remove the word at the + menu position. + + @param cursor reference to the text cursor for the misspelled word + @type QTextCursor + @param menu reference to the context menu + @type QMenu + """ + if cursor is None: + return + + text = cursor.selectedText() + menu.addAction(QCoreApplication.translate( + "SpellCheckMixin", + "Remove '{0}' from Dictionary").format(text), + lambda: self.__addToUserDict(text, "remove")) def __createLanguagesMenu(self, parent=None): """ @@ -162,7 +184,6 @@ act.setData(language) languageMenu.addAction(act) - # TODO: add action to add a word to the lists languageMenu.triggered.connect(self.__setLanguage) return languageMenu @@ -196,6 +217,24 @@ formatMenu.triggered.connect(self.__setFormat) return formatMenu + def __cursorForPosition(self, pos): + """ + Private method to create a text cursor selecting the word at the + given position. + + @param pos position of the misspelled word + @type QPoint + @return text cursor for the word + @rtype QTextCursor + """ + cursor = self.cursorForPosition(pos) + cursor.select(QTextCursor.SelectionType.WordUnderCursor) + + if cursor.hasSelection(): + return cursor + else: + return None + def __cursorForMisspelling(self, pos): """ Private method to create a text cursor selecting the misspelled @@ -226,21 +265,55 @@ else: return None - @pyqtSlot(QAction) - def __correctWord(self, act): + def __correctWord(self, cursor, word): + """ + Private method to replace some misspelled text. + + @param cursor reference to the text cursor for the misspelled word + @type QTextCursor + @param word replacement text + @type str + """ + cursor.beginEditBlock() + cursor.removeSelectedText() + cursor.insertText(word) + cursor.endEditBlock() + + def __addToUserDict(self, word, command): """ - Private slot to correct the misspelled word with the selected - correction. + Private method to add a word to the user word or exclude list. + + @param word text to be added + @type str + @param command command indicating the user dictionary type + @type str + """ + if word: + dictionary = self.__highlighter.dict() + if command == "add": + dictionary.add(word) + elif command == "remove": + dictionary.remove(word) + + self.__highlighter.rehighlight() + + @pyqtSlot(QAction) + def __spellMenuTriggered(self, act): + """ + Private slot to handle a selection of the spell menu. @param act reference to the selected action @type QAction """ - cursor, word = act.data() + data = act.data() + if len(data) == 2: + # replace the misspelled word + self.__correctWord(*data) - cursor.beginEditBlock() - cursor.removeSelectedText() - cursor.insertText(word) - cursor.endEditBlock() + elif len(data) == 3: + # dictionary management action + _, word, command = data + self.__addToUserDict(word, command) @pyqtSlot(QAction) def __setLanguage(self, act): @@ -300,7 +373,7 @@ self.__highlighter.setDict(spellDict) @classmethod - def setDefaultLanguage(cls, language, pwl="", pel=""): + def setDefaultLanguage(cls, language, pwl=None, pel=None): """ Class method to set the default spell-check language. @@ -308,7 +381,7 @@ @type str @param pwl file name of the personal word list @type str - @param pel name of the personal exclude list + @param pel file name of the personal exclude list @type str """ with contextlib.suppress(DictNotFoundError): @@ -467,10 +540,16 @@ if __name__ == '__main__': import sys + import os from PyQt6.QtWidgets import QApplication if ENCHANT_AVAILABLE: - SpellCheckMixin.setDefaultLanguage("en_US") + dictPath = os.path.expanduser(os.path.join("~", ".eric7", "spelling")) + SpellCheckMixin.setDefaultLanguage( + "en_US", + os.path.join(dictPath, "pwl.dic"), + os.path.join(dictPath, "pel.dic") + ) app = QApplication(sys.argv) spellEdit = EricSpellCheckedPlainTextEdit()