diff --git a/nw/gui/dialogs/configeditor.py b/nw/gui/dialogs/configeditor.py index 1932e341..06dc5b92 100644 --- a/nw/gui/dialogs/configeditor.py +++ b/nw/gui/dialogs/configeditor.py @@ -264,6 +264,7 @@ class GuiConfigEditGeneral(QWidget): guiDark = self.guiDarkIcons.isChecked() spellTool = self.spellToolList.currentData() spellLanguage = self.spellLangList.currentData() + bigDocLimit = self.spellBigDoc.value() autoSaveDoc = self.autoSaveDoc.value() autoSaveProj = self.autoSaveProj.value() backupPath = self.projBackupPath.text() @@ -278,6 +279,7 @@ class GuiConfigEditGeneral(QWidget): self.mainConf.guiDark = guiDark self.mainConf.spellTool = spellTool self.mainConf.spellLanguage = spellLanguage + self.mainConf.bigDocLimit = bigDocLimit self.mainConf.autoSaveDoc = autoSaveDoc self.mainConf.autoSaveProj = autoSaveProj self.mainConf.backupPath = backupPath diff --git a/nw/gui/elements/doceditor.py b/nw/gui/elements/doceditor.py index 018e9645..83706fb5 100644 --- a/nw/gui/elements/doceditor.py +++ b/nw/gui/elements/doceditor.py @@ -304,9 +304,11 @@ class GuiDocEditor(QTextEdit): # Updating root frame triggers a QTextDocument->contentsChange # signal, which we do not want as it re-runs the syntax # highlighter and spell checker, so we block it briefly. + # We then emit a signal that does not trigger re-highlighting. self.qDocument.blockSignals(True) self.qDocument.rootFrame().setFrameFormat(docFormat) self.qDocument.blockSignals(False) + self.qDocument.contentsChange.emit(0,0,0) return @@ -372,18 +374,26 @@ class GuiDocEditor(QTextEdit): self.theParent.mainMenu.setSpellCheck(theMode) self.theProject.setSpellCheck(theMode) self.hLight.setSpellCheck(theMode) - self.hLight.rehighlight() + self.reHighlightDocument() logger.verbose("Spell check is set to %s" % str(theMode)) return True - def updateSpellCheck(self): + def reHighlightDocument(self): """Rerun the highlighter to update spell checking status of the - currently loaded text. + currently loaded text. The fastest way to do this, at least as + of Qt 5.13, is to clear the text and put it back. """ + if self.spellCheck: - self.hLight.rehighlight() + theText = self.getText() + self.clear() + bfTime = time() + self.setPlainText(theText) + afTime = time() + logger.debug("Document re-highlighted in %.3f milliseconds" % (1000*(afTime-bfTime))) + return True ## @@ -615,6 +625,9 @@ class GuiDocEditor(QTextEdit): return def _docChange(self, thePos, charsRemoved, charsAdded): + """Triggered by QTextDocument->contentsChanged. This also + triggers the syntax highlighter. + """ self.lastEdit = time() if not self.docChanged: self.setDocumentChanged(True) diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py index 179a6077..5966509d 100644 --- a/nw/gui/mainmenu.py +++ b/nw/gui/mainmenu.py @@ -618,7 +618,7 @@ class GuiMainMenu(QMenuBar): self.aReRunSpell = QAction("Re-Run Spell Check", self) self.aReRunSpell.setStatusTip("Run the spell checker on current document") self.aReRunSpell.setShortcut("F7") - self.aReRunSpell.triggered.connect(self.theParent.docEditor.updateSpellCheck) + self.aReRunSpell.triggered.connect(self.theParent.docEditor.reHighlightDocument) self.toolsMenu.addAction(self.aReRunSpell) # Tools > Separator diff --git a/nw/gui/tools/dochighlight.py b/nw/gui/tools/dochighlight.py index 1c8cd501..6cbd594c 100644 --- a/nw/gui/tools/dochighlight.py +++ b/nw/gui/tools/dochighlight.py @@ -201,6 +201,11 @@ class GuiDocHighlighter(QSyntaxHighlighter): ## def highlightBlock(self, theText): + """Highlight a single block. Prefer to check first character for + all formats that are defined by their initial characters. This + is significantly faster than running the regex checks we use for + text paragraphs. + """ if self.theHandle is None or not theText: return @@ -224,6 +229,10 @@ class GuiDocHighlighter(QSyntaxHighlighter): kwFmt.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline) self.setFormat(xPos, xLen, kwFmt) + # We never want to run the spell checker on keyword/values, + # so we force a return here + return + elif theText.startswith("# "): # Header 1 self.setFormat(0, 1, self.hStyles["header1"]) self.setFormat(1, len(theText), self.hStyles["header1h"]) @@ -277,6 +286,10 @@ class GuiDocHighlighter(QSyntaxHighlighter): ## def _makeFormat(self, fmtCol=None, fmtStyle=None, fmtSize=None): + """Generate a valid character format to be applied to the text + that is to be highlighted. + """ + theFormat = QTextCharFormat() if fmtCol is not None: