Merge pull request #145 from vkbo/language_status

Language on Status Bar
This commit is contained in:
Veronica K. Berglyd Olsen
2019-11-16 12:34:18 +01:00
committed by GitHub
10 changed files with 80 additions and 31 deletions
+28 -1
View File
@@ -314,17 +314,41 @@ class GuiDocEditor(QTextEdit):
## ##
def setDictionaries(self): def setDictionaries(self):
"""Set the spell checker dictionary language, and update the
status bar to show the one actually loaded by the spell checker
class.
"""
self.theDict.setLanguage(self.mainConf.spellLanguage, self.theProject.projDict) self.theDict.setLanguage(self.mainConf.spellLanguage, self.theProject.projDict)
self.theParent.statusBar.setLanguage(self.mainConf.spellLanguage) self.theParent.statusBar.setLanguage(self.theDict.spellLanguage)
return True return True
def setSpellCheck(self, theMode): def setSpellCheck(self, theMode):
"""This is the master spell check setting function, and this one
should call all other setSpellCheck functions in other classes.
If the spell check mode is not defined, then toggle the current
status saved in the class.
"""
if theMode is None:
theMode = not self.spellCheck
if self.theDict.spellLanguage is None:
theMode = False
self.spellCheck = theMode self.spellCheck = theMode
self.theParent.mainMenu.setSpellCheck(theMode)
self.theProject.setSpellCheck(theMode)
self.hLight.setSpellCheck(theMode) self.hLight.setSpellCheck(theMode)
self.hLight.rehighlight() self.hLight.rehighlight()
logger.verbose("Spell check is set to %s" % str(theMode))
return True return True
def updateSpellCheck(self): def updateSpellCheck(self):
"""Rerun the highlighter to update spell checking status of the
currently loaded text.
"""
if self.spellCheck: if self.spellCheck:
self.hLight.rehighlight() self.hLight.rehighlight()
return True return True
@@ -506,9 +530,12 @@ class GuiDocEditor(QTextEdit):
theCursor = self.cursorForPosition(thePos) theCursor = self.cursorForPosition(thePos)
theCursor.select(QTextCursor.WordUnderCursor) theCursor.select(QTextCursor.WordUnderCursor)
theWord = theCursor.selectedText().strip().strip(self.nonWord) theWord = theCursor.selectedText().strip().strip(self.nonWord)
if theWord == "": if theWord == "":
return return
logger.verbose("Looking up '%s' in the dictionary" % theWord)
if self.theDict.checkWord(theWord): if self.theDict.checkWord(theWord):
return return
+13 -12
View File
@@ -68,7 +68,6 @@ class GuiMainMenu(QMenuBar):
def updateMenu(self): def updateMenu(self):
self.updateRecentProjects() self.updateRecentProjects()
self.updateSpellCheck()
return return
def updateRecentProjects(self): def updateRecentProjects(self):
@@ -91,10 +90,12 @@ class GuiMainMenu(QMenuBar):
return return
def updateSpellCheck(self): def setSpellCheck(self, theMode):
if self.theParent.hasProject: """Set the spell check check box to theMode. This is controlled
self.aSpellCheck.setChecked(self.theProject.spellCheck) by the document editor class, which holds the master spell check
logger.verbose("Spell check is set to %s" % str(self.theProject.spellCheck)) flag.
"""
self.aSpellCheck.setChecked(theMode)
return return
## ##
@@ -106,12 +107,11 @@ class GuiMainMenu(QMenuBar):
return return
def _toggleSpellCheck(self): def _toggleSpellCheck(self):
if self.theParent.hasProject: """Toggle spell checking. The active status of the spell check
self.theProject.setSpellCheck(self.aSpellCheck.isChecked()) flag is handled by the document editor class, so we make no
self.theParent.docEditor.setSpellCheck(self.aSpellCheck.isChecked()) decision, just pass a None to the function and let it decide.
logger.verbose("Spell check is set to %s" % str(self.theProject.spellCheck)) """
else: self.theParent.docEditor.setSpellCheck(None)
self.aSpellCheck.setChecked(False)
return True return True
def _toggleViewComments(self): def _toggleViewComments(self):
@@ -609,7 +609,8 @@ class GuiMainMenu(QMenuBar):
self.aSpellCheck.setStatusTip("Toggle check spelling") self.aSpellCheck.setStatusTip("Toggle check spelling")
self.aSpellCheck.setCheckable(True) self.aSpellCheck.setCheckable(True)
self.aSpellCheck.setChecked(self.theProject.spellCheck) self.aSpellCheck.setChecked(self.theProject.spellCheck)
self.aSpellCheck.toggled.connect(self._toggleSpellCheck) # Here we must used triggered, not toggled, to avoid recursion
self.aSpellCheck.triggered.connect(self._toggleSpellCheck)
self.aSpellCheck.setShortcut("Ctrl+F7") self.aSpellCheck.setShortcut("Ctrl+F7")
self.toolsMenu.addAction(self.aSpellCheck) self.toolsMenu.addAction(self.aSpellCheck)
+4 -1
View File
@@ -116,7 +116,10 @@ class GuiMainStatus(QStatusBar):
return return
def setLanguage(self, theLanguage): def setLanguage(self, theLanguage):
self.langBox.setText(NWSpellCheck.expandLanguage(theLanguage)) if theLanguage is None:
self.langBox.setText("None")
else:
self.langBox.setText(NWSpellCheck.expandLanguage(theLanguage))
return return
def setProjectStatus(self, isChanged): def setProjectStatus(self, isChanged):
+11 -3
View File
@@ -18,6 +18,8 @@ from PyQt5.QtGui import (
QColor, QTextCharFormat, QFont, QSyntaxHighlighter, QBrush QColor, QTextCharFormat, QFont, QSyntaxHighlighter, QBrush
) )
from nw.constants import nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiDocHighlighter(QSyntaxHighlighter): class GuiDocHighlighter(QSyntaxHighlighter):
@@ -150,7 +152,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
# Non-breaking Space # Non-breaking Space
self.hRules.append(( self.hRules.append((
"[\u00a0]+", { "[%s]+" % nwUnicode.U_NBSP, {
0 : self.hStyles["nobreak"], 0 : self.hStyles["nobreak"],
} }
)) ))
@@ -201,13 +203,19 @@ class GuiDocHighlighter(QSyntaxHighlighter):
} }
)) ))
# Build a QRegExp for each pattern and for the spell checker # Build a QRegExp for each highlight pattern
self.rxRules = [] self.rxRules = []
for regEx, regRules in self.hRules: for regEx, regRules in self.hRules:
hReg = QRegularExpression(regEx) hReg = QRegularExpression(regEx)
hReg.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption) hReg.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption)
self.rxRules.append((hReg, regRules)) self.rxRules.append((hReg, regRules))
self.spellRx = QRegularExpression(r"\b[^\s]+\b")
# Build a QRegExp for spell checker
# Include additional characters that the highlighter should
# consider to be word separators
wordSep = "_+"
wordSep += nwUnicode.U_EMDASH
self.spellRx = QRegularExpression("\\b[^\\s%s]+\\b" % wordSep)
self.spellRx.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption) self.spellRx.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption)
return True return True
+8 -4
View File
@@ -13,6 +13,8 @@
import logging import logging
import nw import nw
from os import path
from nw.constants import isoLanguage from nw.constants import isoLanguage
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -29,6 +31,7 @@ class NWSpellCheck():
def __init__(self): def __init__(self):
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.projectDict = None self.projectDict = None
self.spellLanguage = None
return return
def setLanguage(self, theLang, projectDict=None): def setLanguage(self, theLang, projectDict=None):
@@ -45,11 +48,10 @@ class NWSpellCheck():
newWord = newWord.strip() newWord = newWord.strip()
self.PROJW.append(newWord) self.PROJW.append(newWord)
try: try:
with open(self.projectDict,mode="w+",encoding="utf-8") as outFile: with open(self.projectDict,mode="a+",encoding="utf-8") as outFile:
for pWord in self.PROJW: outFile.write("%s\n" % newWord)
outFile.write("%s\n" % pWord)
except Exception as e: except Exception as e:
logger.error("Failed to write to project word list at %s" % str(self.projectDict)) logger.error("Failed to add word to project word list %s" % str(self.projectDict))
logger.error(str(e)) logger.error(str(e))
return return
@@ -75,6 +77,8 @@ class NWSpellCheck():
self.PROJW = [] self.PROJW = []
if projectDict is not None: if projectDict is not None:
self.projectDict = projectDict self.projectDict = projectDict
if not path.isfile(projectDict):
return
try: try:
with open(projectDict,mode="r",encoding="utf-8") as wordsFile: with open(projectDict,mode="r",encoding="utf-8") as wordsFile:
for theLine in wordsFile: for theLine in wordsFile:
+2
View File
@@ -32,10 +32,12 @@ class NWSpellEnchant(NWSpellCheck):
""" """
try: try:
self.theDict = enchant.Dict(theLang) self.theDict = enchant.Dict(theLang)
self.spellLanguage = theLang
logger.debug("Enchant spell checking for language %s loaded" % theLang) logger.debug("Enchant spell checking for language %s loaded" % theLang)
except: except:
logger.error("Failed to load enchant spell checking for language %s" % theLang) logger.error("Failed to load enchant spell checking for language %s" % theLang)
self.theDict = NWSpellEnchantDummy() self.theDict = NWSpellEnchantDummy()
self.spellLanguage = None
self._readProjectDictionary(projectDict) self._readProjectDictionary(projectDict)
for pWord in self.PROJW: for pWord in self.PROJW:
+3 -1
View File
@@ -41,9 +41,11 @@ class NWSpellSimple(NWSpellCheck):
self.WORDS.append(theLine.strip().lower()) self.WORDS.append(theLine.strip().lower())
logger.debug("Spell check word list for language %s loaded" % theLang) logger.debug("Spell check word list for language %s loaded" % theLang)
logger.debug("Word list contains %d words" % len(self.WORDS)) logger.debug("Word list contains %d words" % len(self.WORDS))
self.spellLanguage = theLang
except Exception as e: except Exception as e:
logger.error("Failed to load spell check word list for language %s" % theLang) logger.error("Failed to load spell check word list for language %s" % theLang)
logger.error(str(e)) logger.error(str(e))
self.spellLanguage = None
self._readProjectDictionary(projectDict) self._readProjectDictionary(projectDict)
for pWord in self.PROJW: for pWord in self.PROJW:
@@ -104,7 +106,7 @@ class NWSpellSimple(NWSpellCheck):
if theBits[1] != ".dict": if theBits[1] != ".dict":
continue continue
spName = "%s [nternal]" % self.expandLanguage(theBits[0]) spName = "%s [Internal]" % self.expandLanguage(theBits[0])
retList.append((theBits[0], spName)) retList.append((theBits[0], spName))
return retList return retList
@@ -12,6 +12,8 @@ In addition, the editor supports automatic formatting of “quotes”, both doub
If you have the need for it, you can also add text that can be automatically replaced by other text when you generate a preview or export the project. Now, lets auto-replace this A with <A>, and this C with <C>. While <E> is just <E>. Press Ctrl+R to see what this looks like in the view pane. If you have the need for it, you can also add text that can be automatically replaced by other text when you generate a preview or export the project. Now, lets auto-replace this A with <A>, and this C with <C>. While <E> is just <E>. Press Ctrl+R to see what this looks like in the view pane.
The editor also supports non breaking spaces, and the spell checker accepts long dashes—like this—as valid word separators.
#### Some Section Here #### Some Section Here
If you need to split a scene file up into further pieces, you can do so with the level four heading, like above. This is referred to as a section. If you need to split a scene file up into further pieces, you can do so with the level four heading, like above. This is referred to as a section.
+8 -8
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.4.0" fileVersion="1.0" timeStamp="2019-11-07 22:03:42"> <novelWriterXML appVersion="0.4.1" fileVersion="1.0" timeStamp="2019-11-16 12:31:19">
<project> <project>
<name>Sample Project</name> <name>Sample Project</name>
<title>Sample Project</title> <title>Sample Project</title>
@@ -9,9 +9,9 @@
</project> </project>
<settings> <settings>
<spellCheck>True</spellCheck> <spellCheck>True</spellCheck>
<lastEdited>96b68994dfa3d</lastEdited> <lastEdited>636b6aa9b697b</lastEdited>
<lastViewed>b3e74dbc1f584</lastViewed> <lastViewed>b3e74dbc1f584</lastViewed>
<lastWordCount>855</lastWordCount> <lastWordCount>875</lastWordCount>
<autoReplace> <autoReplace>
<A>B</A> <A>B</A>
<B>E</B> <B>E</B>
@@ -79,10 +79,10 @@
<status>1st Draft</status> <status>1st Draft</status>
<expanded>False</expanded> <expanded>False</expanded>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>1076</charCount> <charCount>1199</charCount>
<wordCount>196</wordCount> <wordCount>216</wordCount>
<paraCount>6</paraCount> <paraCount>7</paraCount>
<cursorPos>59</cursorPos> <cursorPos>949</cursorPos>
</item> </item>
<item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a"> <item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a">
<name>Another Scene</name> <name>Another Scene</name>
@@ -118,7 +118,7 @@
<charCount>1692</charCount> <charCount>1692</charCount>
<wordCount>313</wordCount> <wordCount>313</wordCount>
<paraCount>6</paraCount> <paraCount>6</paraCount>
<cursorPos>216</cursorPos> <cursorPos>530</cursorPos>
</item> </item>
<item handle="88706ddc78b1b" order="5" parent="e7ded148d6e4a"> <item handle="88706ddc78b1b" order="5" parent="e7ded148d6e4a">
<name>Chapter Two</name> <name>Chapter Two</name>
+1 -1
View File
@@ -13,4 +13,4 @@ print("")
profMainWindows = pstats.Stats(path.join(profDir,"testMainWindows.prof")) profMainWindows = pstats.Stats(path.join(profDir,"testMainWindows.prof"))
profMainWindows.sort_stats("cumtime") profMainWindows.sort_stats("cumtime")
profMainWindows.print_stats("nw",50) profMainWindows.print_stats("nw/")