Merge pull request #3 from vkbo/spellcheck_updates

Spellcheck updates
This commit is contained in:
Veronica K. Berglyd Olsen
2019-05-12 16:20:46 +02:00
committed by GitHub
9 changed files with 195 additions and 72 deletions
+52
View File
@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
"""novelWriter Common Functions
novelWriter Common Functions
================================
Various functions used multiple places
File History:
Created: 2019-05-12 [0.1.0]
"""
import logging
import nw
logger = logging.getLogger(__name__)
def checkString(checkValue, defaultValue, allowNone=False):
if allowNone:
if checkValue == None: return None
if checkValue == "None": return None
if isinstance(checkValue,str): return str(checkValue)
return defaultValue
def checkInt(checkValue, defaultValue, allowNone=False):
if allowNone:
if checkValue == None: return None
if checkValue == "None": return None
try:
return int(checkValue)
except:
return defaultValue
def checkBool(checkValue, defaultValue, allowNone=False):
if allowNone:
if checkValue == None: return None
if checkValue == "None": return None
if isinstance(checkValue, str):
if checkValue == "True":
return True
elif checkValue == "False":
return False
else:
return defaultValue
elif isinstance(checkValue, int):
if checkValue == 1:
return True
elif checkValue == 0:
return False
else:
return defaultValue
return defaultValue
+23 -3
View File
@@ -38,6 +38,7 @@ class GuiDocEditor(QTextEdit):
self.theParent = theParent
self.docChanged = False
self.pwlFile = None
self.spellCheck = False
# Document Variables
self.charCount = 0
@@ -105,7 +106,7 @@ class GuiDocEditor(QTextEdit):
def setDocumentChanged(self, bValue):
self.docChanged = bValue
self.theParent.statusBar.setDocumentStatus(self.docChanged)
return
return self.docChanged
def setText(self, theText):
self.setPlainText(theText)
@@ -120,7 +121,18 @@ class GuiDocEditor(QTextEdit):
self.pwlFile = pwlFile
self.theDict = enchant.DictWithPWL(self.mainConf.spellLanguage,pwlFile)
self.hLight.setDict(self.theDict)
return
return True
def setSpellCheck(self, theMode):
self.spellCheck = theMode
self.hLight.setSpellCheck(theMode)
self.rehighlightDocument()
return True
def updateSpellCheck(self):
if self.spellCheck:
self.rehighlightDocument()
return True
def getText(self):
theText = self.toPlainText()
@@ -154,6 +166,11 @@ class GuiDocEditor(QTextEdit):
elif theAction == nwDocAction.SEL_PARA: self._makeSelection(QTextCursor.BlockUnderCursor)
else:
logger.error("Unknown or unsupported document action %s" % str(theAction))
return False
return True
def rehighlightDocument(self):
self.hLight.rehighlight()
return
##
@@ -181,6 +198,9 @@ class GuiDocEditor(QTextEdit):
def _openContextMenu(self, thePos):
if not self.spellCheck:
return
theCursor = self.cursorForPosition(thePos)
theCursor.select(QTextCursor.WordUnderCursor)
theWord = theCursor.selectedText()
@@ -237,7 +257,7 @@ class GuiDocEditor(QTextEdit):
self.wcTimer.start()
if self.mainConf.doReplace and not self.hasSelection:
self._docAutoReplace(self.theDoc.findBlock(thePos))
# logger.verbose("Doc change signal took %.3f µs" % ((time()-self.lastEdit)*1e6))
logger.verbose("Doc change signal took %.3f µs" % ((time()-self.lastEdit)*1e6))
return
def _docAutoReplace(self, theBlock):
+21 -16
View File
@@ -24,22 +24,23 @@ class GuiDocHighlighter(QSyntaxHighlighter):
QSyntaxHighlighter.__init__(self, theDoc)
logger.debug("Initialising DocHighlighter ...")
self.mainConf = nw.CONFIG
self.theDoc = theDoc
self.theDict = None
self.hRules = []
self.mainConf = nw.CONFIG
self.theDoc = theDoc
self.theDict = None
self.spellCheck = False
self.hRules = []
self.colHead = QColor( 0,155,200)
self.colHeadH = QColor( 0,105,135)
self.colEmph = QColor(200,120, 0)
self.colDialN = QColor(200, 46, 0)
self.colDialD = QColor(184,200, 0)
self.colDialS = QColor(136,200, 0)
self.colComm = QColor(150,150,150)
self.colKey = QColor(200, 46, 0)
self.colVal = QColor(184,200, 0)
self.colHead = QColor( 0,155,200)
self.colHeadH = QColor( 0,105,135)
self.colEmph = QColor(200,120, 0)
self.colDialN = QColor(200, 46, 0)
self.colDialD = QColor(184,200, 0)
self.colDialS = QColor(136,200, 0)
self.colComm = QColor(150,150,150)
self.colKey = QColor(200, 46, 0)
self.colVal = QColor(184,200, 0)
self.colSpell = QColor(200, 46, 0)
self.colSpell = QColor(200, 46, 0)
self.hStyles = {
"header1" : self._makeFormat(self.colHead, "bold",1.8),
@@ -153,7 +154,11 @@ class GuiDocHighlighter(QSyntaxHighlighter):
def setDict(self, theDict):
self.theDict = theDict
return
return True
def setSpellCheck(self, theMode):
self.spellCheck = theMode
return True
def _makeFormat(self, fmtCol=None, fmtStyle=None, fmtSize=None):
theFormat = QTextCharFormat()
@@ -189,7 +194,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.setCurrentBlockState(0)
if self.theDict is None:
if self.theDict is None or not self.spellCheck:
return
rxSpell = self.spellRx.globalMatch(theText.replace("_"," "), 0)
+38 -2
View File
@@ -61,6 +61,15 @@ class GuiMainMenu(QMenuBar):
)
return
##
# Update Menu on Settings Changed
##
def updateMenu(self):
self.updateRecentProjects()
self.updateSpellCheck()
return
def updateRecentProjects(self):
self.recentMenu.clear()
for n in range(len(self.mainConf.recentList)):
@@ -71,6 +80,11 @@ class GuiMainMenu(QMenuBar):
self.recentMenu.addAction(menuItem)
return
def updateSpellCheck(self):
self.toolsSpellCheck.setChecked(self.theProject.spellCheck)
logger.verbose("Spell check is set to %s" % str(self.theProject.spellCheck))
return
##
# Menu Action
##
@@ -80,6 +94,12 @@ class GuiMainMenu(QMenuBar):
qApp.quit()
return True
def _toggleSpellCheck(self):
self.theProject.setSpellCheck(self.toolsSpellCheck.isChecked())
self.theParent.docEditor.setSpellCheck(self.toolsSpellCheck.isChecked())
logger.verbose("Spell check is set to %s" % str(self.theProject.spellCheck))
return
def _showAbout(self):
msgBox = QMessageBox()
msgBox.about(self.theParent, "About %s" % nw.__package__, (
@@ -407,8 +427,24 @@ class GuiMainMenu(QMenuBar):
self.toolsMoveDown.triggered.connect(lambda : self._moveTreeItem(1))
self.toolsMenu.addAction(self.toolsMoveDown)
# # Tools > Separator
# self.toolsMenu.addSeparator()
# Tools > Separator
self.toolsMenu.addSeparator()
# Tools > Toggle Spell Check
self.toolsSpellCheck = QAction("Check Spelling", self)
self.toolsSpellCheck.setStatusTip("Toggle Check Spelling")
self.toolsSpellCheck.setCheckable(True)
self.toolsSpellCheck.setChecked(self.theProject.spellCheck)
self.toolsSpellCheck.toggled.connect(self._toggleSpellCheck)
self.toolsSpellCheck.setShortcut("Ctrl+F7")
self.toolsMenu.addAction(self.toolsSpellCheck)
# Tools > Update Spell Check
menuItem = QAction(QIcon.fromTheme("tools-check-spelling"), "Re-Run Spell Check", self)
menuItem.setStatusTip("Rus the Spell Checker on Current Document")
menuItem.setShortcut("F7")
menuItem.triggered.connect(self.theParent.docEditor.updateSpellCheck)
self.toolsMenu.addAction(menuItem)
# # Tools > Settings
# menuItem = QAction(QIcon.fromTheme("preferences-system"), "Preferences", self)
+2 -1
View File
@@ -172,10 +172,11 @@ class GuiMain(QMainWindow):
self.treeView.clearTree()
self.theProject.openProject(projFile)
self.treeView.buildTree()
self.mainMenu.updateRecentProjects()
self._setWindowTitle(self.theProject.projName)
self._makeStatusIcons()
self.docEditor.setPwl(path.join(self.theProject.projMeta,"wordlist.txt"))
self.docEditor.setSpellCheck(self.theProject.spellCheck)
self.mainMenu.updateMenu()
return True
def saveProject(self):
+9 -21
View File
@@ -13,11 +13,12 @@
import logging
import nw
from os import path, mkdir
from lxml import etree
from datetime import datetime
from os import path, mkdir
from lxml import etree
from datetime import datetime
from nw.enum import nwItemType, nwItemClass, nwItemLayout
from nw.enum import nwItemType, nwItemClass, nwItemLayout
from nw.common import checkInt
logger = logging.getLogger(__name__)
@@ -153,7 +154,7 @@ class NWItem():
return
def setStatus(self, theStatus):
theStatus = self._checkInt(theStatus,0)
theStatus = checkInt(theStatus,0)
self.itemStatus = theStatus
return
@@ -169,31 +170,18 @@ class NWItem():
##
def setCharCount(self, theCount):
theCount = self._checkInt(theCount,0)
theCount = checkInt(theCount,0)
self.charCount = theCount
return
def setWordCount(self, theCount):
theCount = self._checkInt(theCount,0)
theCount = checkInt(theCount,0)
self.wordCount = theCount
return
def setParaCount(self, theCount):
theCount = self._checkInt(theCount,0)
theCount = checkInt(theCount,0)
self.paraCount = theCount
return
##
# Internal Functions
##
def _checkInt(self,checkValue,defaultValue,allowNone=False):
if allowNone:
if checkValue == None: return None
if checkValue == "None": return None
try:
return int(checkValue)
except:
return defaultValue
# END Class NWItem
+44 -29
View File
@@ -20,6 +20,7 @@ from datetime import datetime
from time import time
from nw.enum import nwItemType, nwItemClass, nwItemLayout
from nw.common import checkString, checkBool
from nw.project.item import NWItem
logger = logging.getLogger(__name__)
@@ -36,7 +37,7 @@ class NWProject():
# Debug
self.handleSeed = None
# Project Settings
# Class Settings
self.projTree = None
self.treeOrder = None
self.treeRoots = None
@@ -45,11 +46,17 @@ class NWProject():
self.projMeta = None
self.projCache = None
self.projFile = None
self.statusCols = None
# Project Meta
self.projName = None
self.bookTitle = None
self.bookAuthors = None
self.statusCols = None
# Project Settings
self.spellCheck = False
# Set Defaults
self.clearProject()
return
@@ -130,6 +137,7 @@ class NWProject():
self.projName = ""
self.bookTitle = ""
self.bookAuthors = []
self.spellCheck = False
self.statusCols = [
("New", 100,100,100),
("Note", 200, 50, 0),
@@ -185,6 +193,12 @@ class NWProject():
elif xItem.tag == "author":
logger.verbose("Author: '%s'" % xItem.text)
self.bookAuthors.append(xItem.text)
elif xChild.tag == "settings":
logger.debug("Found project settings")
for xItem in xChild:
if xItem.text is None: continue
if xItem.tag == "spellCheck":
self.spellCheck = checkBool(xItem.text,False)
elif xChild.tag == "content":
logger.debug("Found project content")
for xItem in xChild:
@@ -233,15 +247,16 @@ class NWProject():
"appVersion" : str(nw.__version__),
"timeStamp" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
})
xProject = etree.SubElement(nwXML,"project")
xProjName = etree.SubElement(xProject,"name")
xProjName.text = self.projName
xBookTitle = etree.SubElement(xProject,"title")
xBookTitle.text = self.bookTitle
for bookAuthor in self.bookAuthors:
if bookAuthor == "": continue
xBookAuthor = etree.SubElement(xProject,"author")
xBookAuthor.text = bookAuthor
# Save Project Meta
xProject = etree.SubElement(nwXML,"project")
self._saveProjectValue(xProject,"name", self.projName, True)
self._saveProjectValue(xProject,"title", self.bookTitle, True)
self._saveProjectValue(xProject,"author",self.bookAuthors)
# Save Project Settings
xSettings = etree.SubElement(nwXML,"settings")
self._saveProjectValue(xSettings,"spellCheck",self.spellCheck)
# Save Tree Content
logger.debug("Writing project content")
@@ -298,6 +313,11 @@ class NWProject():
self.setProjectChanged(True)
return True
def setSpellCheck(self, theMode):
self.spellCheck = theMode
self.setProjectChanged(True)
return True
def setTreeOrder(self, newOrder):
if len(self.treeOrder) != len(newOrder):
logger.warning("Size of new and old tree order does not match")
@@ -351,6 +371,17 @@ class NWProject():
return False
return True
def _saveProjectValue(self, xParent, theName, theValue, allowNone=True):
if not isinstance(theValue, list):
theValue = [theValue]
for aValue in theValue:
if not isinstance(aValue, str):
aValue = str(aValue)
if aValue == "" and not allowNone: continue
xItem = etree.SubElement(xParent,theName)
xItem.text = aValue
return
def _scanProjectFolder(self):
if self.projPath is None:
@@ -402,8 +433,8 @@ class NWProject():
return
def _appendItem(self, tHandle, pHandle, nwItem):
tHandle = self._checkString(tHandle,self._makeHandle(),False)
pHandle = self._checkString(pHandle,None,True)
tHandle = checkString(tHandle,self._makeHandle(),False)
pHandle = checkString(pHandle,None,True)
logger.verbose("Adding entry %s with parent %s" % (str(tHandle),str(pHandle)))
nwItem.setHandle(tHandle)
@@ -441,20 +472,4 @@ class NWProject():
itemHandle = self._makeHandle(addSeed+"!")
return itemHandle
def _checkString(self,checkValue,defaultValue,allowNone=False):
if allowNone:
if checkValue == None: return None
if checkValue == "None": return None
if isinstance(checkValue,str): return str(checkValue)
return defaultValue
def _checkInt(self,checkValue,defaultValue,allowNone=False):
if allowNone:
if checkValue == None: return None
if checkValue == "None": return None
try:
return int(checkValue)
except:
return defaultValue
# END Class NWProject
+3
View File
@@ -4,6 +4,9 @@
<name></name>
<title></title>
</project>
<settings>
<spellCheck>False</spellCheck>
</settings>
<content count="6">
<item handle="73475cb40a568" order="None" parent="None">
<name>Novel</name>
+3
View File
@@ -4,6 +4,9 @@
<name></name>
<title></title>
</project>
<settings>
<spellCheck>False</spellCheck>
</settings>
<content count="10">
<item handle="73475cb40a568" order="None" parent="None">
<name>Novel</name>