Merge pull request #145 from vkbo/language_status
Language on Status Bar
This commit is contained in:
@@ -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
@@ -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
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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, let’s 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, let’s 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.
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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/")
|
||||||
|
|||||||
Reference in New Issue
Block a user