@@ -82,6 +82,18 @@ def checkBool(checkValue, defaultValue, allowNone=False):
|
|||||||
return defaultValue
|
return defaultValue
|
||||||
return defaultValue
|
return defaultValue
|
||||||
|
|
||||||
|
def checkHandle(checkValue, defaultValue, allowNone=False):
|
||||||
|
"""Check if a value is a handle.
|
||||||
|
"""
|
||||||
|
if allowNone:
|
||||||
|
if checkValue is None:
|
||||||
|
return None
|
||||||
|
if checkValue == "None":
|
||||||
|
return None
|
||||||
|
if isHandle(checkValue):
|
||||||
|
return str(checkValue)
|
||||||
|
return defaultValue
|
||||||
|
|
||||||
def isHandle(theString):
|
def isHandle(theString):
|
||||||
"""Check if a string is a valid novelWriter handle.
|
"""Check if a string is a valid novelWriter handle.
|
||||||
Note: This is case sensitive. Must be lower case!
|
Note: This is case sensitive. Must be lower case!
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from nw.core.document import NWDoc
|
|||||||
from nw.core.index import NWIndex
|
from nw.core.index import NWIndex
|
||||||
from nw.core.project import NWProject
|
from nw.core.project import NWProject
|
||||||
from nw.core.spellcheck import NWSpellCheck, NWSpellEnchant, NWSpellSimple
|
from nw.core.spellcheck import NWSpellCheck, NWSpellEnchant, NWSpellSimple
|
||||||
from nw.core.tokenizer import Tokenizer
|
|
||||||
from nw.core.tohtml import ToHtml
|
from nw.core.tohtml import ToHtml
|
||||||
from nw.core.tools import countWords, numberToRoman, numberToWord
|
from nw.core.tools import countWords, numberToRoman, numberToWord
|
||||||
|
|
||||||
@@ -15,7 +14,6 @@ __all__ = [
|
|||||||
"NWSpellCheck",
|
"NWSpellCheck",
|
||||||
"NWSpellEnchant",
|
"NWSpellEnchant",
|
||||||
"NWSpellSimple",
|
"NWSpellSimple",
|
||||||
"Tokenizer",
|
|
||||||
"ToHtml",
|
"ToHtml",
|
||||||
"countWords",
|
"countWords",
|
||||||
"numberToRoman",
|
"numberToRoman",
|
||||||
|
|||||||
+41
-33
@@ -26,11 +26,9 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import nw
|
|
||||||
|
|
||||||
from os import path, rename, unlink
|
from os import path, rename, unlink
|
||||||
|
|
||||||
from nw.core.item import NWItem
|
|
||||||
from nw.constants import nwAlert
|
from nw.constants import nwAlert
|
||||||
from nw.common import isHandle
|
from nw.common import isHandle
|
||||||
from nw.constants import nwItemLayout, nwItemClass, nwConst
|
from nw.constants import nwItemLayout, nwItemClass, nwConst
|
||||||
@@ -41,14 +39,14 @@ class NWDoc():
|
|||||||
|
|
||||||
def __init__(self, theProject, theParent):
|
def __init__(self, theProject, theParent):
|
||||||
|
|
||||||
self.mainConf = nw.CONFIG
|
|
||||||
self.theProject = theProject
|
self.theProject = theProject
|
||||||
self.theParent = theParent
|
self.theParent = theParent
|
||||||
|
|
||||||
self.theItem = None
|
# Internal Variables
|
||||||
self.docHandle = None
|
self._theItem = None # The currently open item
|
||||||
self.fileLoc = None
|
self._docHandle = None # The handle of the currently open item
|
||||||
self.docMeta = ""
|
self._fileLoc = None # The file location of the currently open item
|
||||||
|
self._docMeta = "" # The meta string of the currently open item
|
||||||
|
|
||||||
# Internal Mapping
|
# Internal Mapping
|
||||||
self.makeAlert = self.theParent.makeAlert
|
self.makeAlert = self.theParent.makeAlert
|
||||||
@@ -62,10 +60,10 @@ class NWDoc():
|
|||||||
def clearDocument(self):
|
def clearDocument(self):
|
||||||
"""Clear the document contents.
|
"""Clear the document contents.
|
||||||
"""
|
"""
|
||||||
self.theItem = None
|
self._theItem = None
|
||||||
self.docHandle = None
|
self._docHandle = None
|
||||||
self.fileLoc = None
|
self._fileLoc = None
|
||||||
self.docMeta = ""
|
self._docMeta = ""
|
||||||
return
|
return
|
||||||
|
|
||||||
def openDocument(self, tHandle, showStatus=True, isOrphan=False):
|
def openDocument(self, tHandle, showStatus=True, isOrphan=False):
|
||||||
@@ -78,31 +76,31 @@ class NWDoc():
|
|||||||
# Always clear first, since the object will often be reused.
|
# Always clear first, since the object will often be reused.
|
||||||
self.clearDocument()
|
self.clearDocument()
|
||||||
|
|
||||||
self.docHandle = tHandle
|
self._docHandle = tHandle
|
||||||
if not isOrphan:
|
if not isOrphan:
|
||||||
self.theItem = self.theProject.projTree[tHandle]
|
self._theItem = self.theProject.projTree[tHandle]
|
||||||
else:
|
else:
|
||||||
self.theItem = None
|
self._theItem = None
|
||||||
|
|
||||||
if self.theItem is None and not isOrphan:
|
if self._theItem is None and not isOrphan:
|
||||||
self.clearDocument()
|
self.clearDocument()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
docFile = self.docHandle+".nwd"
|
docFile = self._docHandle+".nwd"
|
||||||
logger.debug("Opening document %s" % docFile)
|
logger.debug("Opening document %s" % docFile)
|
||||||
|
|
||||||
docPath = path.join(self.theProject.projContent, docFile)
|
docPath = path.join(self.theProject.projContent, docFile)
|
||||||
self.fileLoc = docPath
|
self._fileLoc = docPath
|
||||||
|
|
||||||
theText = ""
|
theText = ""
|
||||||
self.docMeta = ""
|
self._docMeta = ""
|
||||||
if path.isfile(docPath):
|
if path.isfile(docPath):
|
||||||
try:
|
try:
|
||||||
with open(docPath, mode="r", encoding="utf8") as inFile:
|
with open(docPath, mode="r", encoding="utf8") as inFile:
|
||||||
fstLine = inFile.readline()
|
fstLine = inFile.readline()
|
||||||
if fstLine.startswith("%%~ "):
|
if fstLine.startswith("%%~ "):
|
||||||
# This is the meta line
|
# This is the meta line
|
||||||
self.docMeta = fstLine[4:].strip()
|
self._docMeta = fstLine[4:].strip()
|
||||||
else:
|
else:
|
||||||
theText = fstLine
|
theText = fstLine
|
||||||
theText += inFile.read()
|
theText += inFile.read()
|
||||||
@@ -120,10 +118,10 @@ class NWDoc():
|
|||||||
logger.debug("The requested document does not exist.")
|
logger.debug("The requested document does not exist.")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
logger.verbose("DocMeta: '%s'" % self.docMeta)
|
logger.verbose("DocMeta: '%s'" % self._docMeta)
|
||||||
|
|
||||||
if showStatus and not isOrphan:
|
if showStatus and not isOrphan:
|
||||||
self.theParent.statusBar.setStatus("Opened Document: %s" % self.theItem.itemName)
|
self.theParent.statusBar.setStatus("Opened Document: %s" % self._theItem.itemName)
|
||||||
|
|
||||||
return theText
|
return theText
|
||||||
|
|
||||||
@@ -131,29 +129,29 @@ class NWDoc():
|
|||||||
"""Save the document via temp file in case of save failure, and
|
"""Save the document via temp file in case of save failure, and
|
||||||
in any case keep a backup of the file.
|
in any case keep a backup of the file.
|
||||||
"""
|
"""
|
||||||
if self.docHandle is None:
|
if self._docHandle is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.theProject.ensureFolderStructure()
|
self.theProject.ensureFolderStructure()
|
||||||
|
|
||||||
docFile = self.docHandle+".nwd"
|
docFile = self._docHandle+".nwd"
|
||||||
logger.debug("Saving document %s" % docFile)
|
logger.debug("Saving document %s" % docFile)
|
||||||
|
|
||||||
docPath = path.join(self.theProject.projContent, docFile)
|
docPath = path.join(self.theProject.projContent, docFile)
|
||||||
docTemp = path.join(self.theProject.projContent, docFile+"~")
|
docTemp = path.join(self.theProject.projContent, docFile+"~")
|
||||||
|
|
||||||
if isinstance(self.theItem, NWItem):
|
if self._theItem is None:
|
||||||
itemPath = self.theProject.projTree.getItemPath(self.docHandle)
|
docMeta = ""
|
||||||
|
else:
|
||||||
|
itemPath = self.theProject.projTree.getItemPath(self._docHandle)
|
||||||
docMeta = (
|
docMeta = (
|
||||||
"%%~ {handlepath:s}:{itemclass:s}:{itemlayout:s}:{itemname:s}\n"
|
"%%~ {handlepath:s}:{itemclass:s}:{itemlayout:s}:{itemname:s}\n"
|
||||||
).format(
|
).format(
|
||||||
handlepath = ":".join(itemPath),
|
handlepath = ":".join(itemPath),
|
||||||
itemclass = self.theItem.itemClass.name,
|
itemclass = self._theItem.itemClass.name,
|
||||||
itemlayout = self.theItem.itemLayout.name,
|
itemlayout = self._theItem.itemLayout.name,
|
||||||
itemname = self.theItem.itemName,
|
itemname = self._theItem.itemName,
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
docMeta = ""
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(docTemp, mode="w", encoding="utf8") as outFile:
|
with open(docTemp, mode="w", encoding="utf8") as outFile:
|
||||||
@@ -169,7 +167,7 @@ class NWDoc():
|
|||||||
unlink(docPath)
|
unlink(docPath)
|
||||||
rename(docTemp, docPath)
|
rename(docTemp, docPath)
|
||||||
|
|
||||||
self.theParent.statusBar.setStatus("Saved Document: %s" % self.theItem.itemName)
|
self.theParent.statusBar.setStatus("Saved Document: %s" % self._theItem.itemName)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -201,15 +199,25 @@ class NWDoc():
|
|||||||
# Getters
|
# Getters
|
||||||
##
|
##
|
||||||
|
|
||||||
|
def getFileLocation(self):
|
||||||
|
"""Return the file location of the current file.
|
||||||
|
"""
|
||||||
|
return self._fileLoc
|
||||||
|
|
||||||
|
def getCurrentItem(self):
|
||||||
|
"""Return a pointer to the currently open item.
|
||||||
|
"""
|
||||||
|
return self._theItem
|
||||||
|
|
||||||
def getMeta(self):
|
def getMeta(self):
|
||||||
"""Parses the document meta tag and returns the path and name as
|
"""Parses the document meta tag and returns the path and name as
|
||||||
a list and a string.
|
a list and a string.
|
||||||
"""
|
"""
|
||||||
if len(self.docMeta) < 14:
|
if len(self._docMeta) < 14:
|
||||||
# Not enough information
|
# Not enough information
|
||||||
return "", [], None, None
|
return "", [], None, None
|
||||||
|
|
||||||
theMeta = self.docMeta
|
theMeta = self._docMeta
|
||||||
|
|
||||||
# Scan for handles
|
# Scan for handles
|
||||||
thePath = []
|
thePath = []
|
||||||
|
|||||||
+2
-1
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
import nw
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
from time import time
|
from time import time
|
||||||
@@ -66,9 +67,9 @@ class NWIndex():
|
|||||||
def __init__(self, theProject, theParent):
|
def __init__(self, theProject, theParent):
|
||||||
|
|
||||||
# Internal
|
# Internal
|
||||||
|
self.mainConf = nw.CONFIG
|
||||||
self.theProject = theProject
|
self.theProject = theProject
|
||||||
self.theParent = theParent
|
self.theParent = theParent
|
||||||
self.mainConf = self.theParent.mainConf
|
|
||||||
self.indexBroken = False
|
self.indexBroken = False
|
||||||
|
|
||||||
# Indices
|
# Indices
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import nw
|
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
@@ -40,9 +39,7 @@ class OptionState():
|
|||||||
|
|
||||||
def __init__(self, theProject):
|
def __init__(self, theProject):
|
||||||
|
|
||||||
self.mainConf = nw.CONFIG
|
|
||||||
self.theProject = theProject
|
self.theProject = theProject
|
||||||
|
|
||||||
self.theState = {}
|
self.theState = {}
|
||||||
self.validMap = {
|
self.validMap = {
|
||||||
"GuiWritingStats": {
|
"GuiWritingStats": {
|
||||||
|
|||||||
+27
-25
@@ -481,7 +481,7 @@ class NWProject():
|
|||||||
|
|
||||||
# Changes:
|
# Changes:
|
||||||
# 1.0 : Original file format.
|
# 1.0 : Original file format.
|
||||||
# 1.1 : Changes the way documents are structure in the project
|
# 1.1 : Changes the way documents are structured in the project
|
||||||
# folder from data_X, where X is the first hex value of
|
# folder from data_X, where X is the first hex value of
|
||||||
# the handle, to a single content folder.
|
# the handle, to a single content folder.
|
||||||
# 1.2 : Changes the way autoReplace entries are stored. The 1.1
|
# 1.2 : Changes the way autoReplace entries are stored. The 1.1
|
||||||
@@ -518,15 +518,16 @@ class NWProject():
|
|||||||
msgRes = msgBox.question(self.theParent, "Version Conflict", (
|
msgRes = msgBox.question(self.theParent, "Version Conflict", (
|
||||||
"This project was saved by a newer version of novelWriter, version %s. "
|
"This project was saved by a newer version of novelWriter, version %s. "
|
||||||
"This is version %s. If you continue to open the project, some attributes "
|
"This is version %s. If you continue to open the project, some attributes "
|
||||||
"and settings may not be preserved. Continue opening the project?"
|
"and settings may not be preserved, but the overall project should be fine. "
|
||||||
|
"Continue opening the project?"
|
||||||
) % (
|
) % (
|
||||||
appVersion, nw.__version__
|
appVersion, nw.__version__
|
||||||
))
|
))
|
||||||
if msgRes != QMessageBox.Yes:
|
if msgRes != QMessageBox.Yes:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Start Parsing XML
|
# Start Parsing the XML
|
||||||
# =================
|
# =====================
|
||||||
|
|
||||||
for xChild in xRoot:
|
for xChild in xRoot:
|
||||||
if xChild.tag == "project":
|
if xChild.tag == "project":
|
||||||
@@ -578,9 +579,9 @@ class NWProject():
|
|||||||
elif xItem.tag == "notesWordCount":
|
elif xItem.tag == "notesWordCount":
|
||||||
self.notesWCount = checkInt(xItem.text, 0, False)
|
self.notesWCount = checkInt(xItem.text, 0, False)
|
||||||
elif xItem.tag == "status":
|
elif xItem.tag == "status":
|
||||||
self.statusItems.unpackEntries(xItem)
|
self.statusItems.unpackXML(xItem)
|
||||||
elif xItem.tag == "importance":
|
elif xItem.tag == "importance":
|
||||||
self.importItems.unpackEntries(xItem)
|
self.importItems.unpackXML(xItem)
|
||||||
elif xItem.tag == "autoReplace":
|
elif xItem.tag == "autoReplace":
|
||||||
for xEntry in xItem:
|
for xEntry in xItem:
|
||||||
if xEntry.tag == "entry":
|
if xEntry.tag == "entry":
|
||||||
@@ -684,9 +685,9 @@ class NWProject():
|
|||||||
self._packProjectValue(xTitleFmt, aKey, aValue)
|
self._packProjectValue(xTitleFmt, aKey, aValue)
|
||||||
|
|
||||||
xStatus = etree.SubElement(xSettings, "status")
|
xStatus = etree.SubElement(xSettings, "status")
|
||||||
self.statusItems.packEntries(xStatus)
|
self.statusItems.packXML(xStatus)
|
||||||
xStatus = etree.SubElement(xSettings, "importance")
|
xStatus = etree.SubElement(xSettings, "importance")
|
||||||
self.importItems.packEntries(xStatus)
|
self.importItems.packXML(xStatus)
|
||||||
|
|
||||||
# Save Tree Content
|
# Save Tree Content
|
||||||
logger.debug("Writing project content")
|
logger.debug("Writing project content")
|
||||||
@@ -1440,23 +1441,24 @@ class NWProject():
|
|||||||
def _deprecatedFiles(self):
|
def _deprecatedFiles(self):
|
||||||
"""Delete files that are no longer used by novelWriter.
|
"""Delete files that are no longer used by novelWriter.
|
||||||
"""
|
"""
|
||||||
rmList = []
|
rmList = [
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.0"))
|
path.join(self.projCache, "nwProject.nwx.0"),
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.1"))
|
path.join(self.projCache, "nwProject.nwx.1"),
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.2"))
|
path.join(self.projCache, "nwProject.nwx.2"),
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.3"))
|
path.join(self.projCache, "nwProject.nwx.3"),
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.4"))
|
path.join(self.projCache, "nwProject.nwx.4"),
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.5"))
|
path.join(self.projCache, "nwProject.nwx.5"),
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.6"))
|
path.join(self.projCache, "nwProject.nwx.6"),
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.7"))
|
path.join(self.projCache, "nwProject.nwx.7"),
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.8"))
|
path.join(self.projCache, "nwProject.nwx.8"),
|
||||||
rmList.append(path.join(self.projCache, "nwProject.nwx.9"))
|
path.join(self.projCache, "nwProject.nwx.9"),
|
||||||
rmList.append(path.join(self.projMeta, "mainOptions.json"))
|
path.join(self.projMeta, "mainOptions.json"),
|
||||||
rmList.append(path.join(self.projMeta, "exportOptions.json"))
|
path.join(self.projMeta, "exportOptions.json"),
|
||||||
rmList.append(path.join(self.projMeta, "outlineOptions.json"))
|
path.join(self.projMeta, "outlineOptions.json"),
|
||||||
rmList.append(path.join(self.projMeta, "timelineOptions.json"))
|
path.join(self.projMeta, "timelineOptions.json"),
|
||||||
rmList.append(path.join(self.projMeta, "docMergeOptions.json"))
|
path.join(self.projMeta, "docMergeOptions.json"),
|
||||||
rmList.append(path.join(self.projMeta, "sessionLogOptions.json"))
|
path.join(self.projMeta, "sessionLogOptions.json"),
|
||||||
|
]
|
||||||
|
|
||||||
for rmFile in rmList:
|
for rmFile in rmList:
|
||||||
if path.isfile(rmFile):
|
if path.isfile(rmFile):
|
||||||
|
|||||||
@@ -89,13 +89,10 @@ class NWSpellCheck():
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def expandLanguage(spTag):
|
def expandLanguage(spTag):
|
||||||
"""Translate a language tag to something more suer friendly.
|
"""Translate a language tag to something more user friendly.
|
||||||
"""
|
"""
|
||||||
spBits = spTag.split("_")
|
spBits = spTag.split("_")
|
||||||
if spBits[0] in isoLanguage.ISO_639_1:
|
spLang = isoLanguage.ISO_639_1.get(spBits[0], spBits[0])
|
||||||
spLang = isoLanguage.ISO_639_1[spBits[0]]
|
|
||||||
else:
|
|
||||||
spLang = spBits[0]
|
|
||||||
if len(spBits) > 1:
|
if len(spBits) > 1:
|
||||||
spLang += " (%s)" % spBits[1]
|
spLang += " (%s)" % spBits[1]
|
||||||
return spLang
|
return spLang
|
||||||
|
|||||||
+42
-42
@@ -36,12 +36,12 @@ logger = logging.getLogger(__name__)
|
|||||||
class NWStatus():
|
class NWStatus():
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.theLabels = []
|
self._theLabels = []
|
||||||
self.theColours = []
|
self._theColours = []
|
||||||
self.theCounts = []
|
self._theCounts = []
|
||||||
self.theMap = {}
|
self._theMap = {}
|
||||||
self.theLength = 0
|
self._theLength = 0
|
||||||
self.theIndex = 0
|
self._theIndex = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
def addEntry(self, theLabel, theColours):
|
def addEntry(self, theLabel, theColours):
|
||||||
@@ -50,11 +50,11 @@ class NWStatus():
|
|||||||
"""
|
"""
|
||||||
theLabel = theLabel.strip()
|
theLabel = theLabel.strip()
|
||||||
if self.lookupEntry(theLabel) is None:
|
if self.lookupEntry(theLabel) is None:
|
||||||
self.theLabels.append(theLabel)
|
self._theLabels.append(theLabel)
|
||||||
self.theColours.append(theColours)
|
self._theColours.append(theColours)
|
||||||
self.theCounts.append(0)
|
self._theCounts.append(0)
|
||||||
self.theMap[theLabel] = self.theLength
|
self._theMap[theLabel] = self._theLength
|
||||||
self.theLength += 1
|
self._theLength += 1
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def lookupEntry(self, theLabel):
|
def lookupEntry(self, theLabel):
|
||||||
@@ -64,8 +64,8 @@ class NWStatus():
|
|||||||
if theLabel is None:
|
if theLabel is None:
|
||||||
return None
|
return None
|
||||||
theLabel = theLabel.strip()
|
theLabel = theLabel.strip()
|
||||||
if theLabel in self.theMap.keys():
|
if theLabel in self._theMap.keys():
|
||||||
return self.theMap[theLabel]
|
return self._theMap[theLabel]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def checkEntry(self, theStatus):
|
def checkEntry(self, theStatus):
|
||||||
@@ -77,8 +77,8 @@ class NWStatus():
|
|||||||
if self.lookupEntry(theStatus) is not None:
|
if self.lookupEntry(theStatus) is not None:
|
||||||
return theStatus
|
return theStatus
|
||||||
theStatus = checkInt(theStatus, 0, False)
|
theStatus = checkInt(theStatus, 0, False)
|
||||||
if theStatus >= 0 and theStatus < self.theLength:
|
if theStatus >= 0 and theStatus < self._theLength:
|
||||||
return self.theLabels[theStatus]
|
return self._theLabels[theStatus]
|
||||||
|
|
||||||
def setNewEntries(self, newList):
|
def setNewEntries(self, newList):
|
||||||
"""Update the list of entries after they have been modified by
|
"""Update the list of entries after they have been modified by
|
||||||
@@ -87,12 +87,12 @@ class NWStatus():
|
|||||||
replaceMap = {}
|
replaceMap = {}
|
||||||
|
|
||||||
if newList is not None:
|
if newList is not None:
|
||||||
self.theLabels = []
|
self._theLabels = []
|
||||||
self.theColours = []
|
self._theColours = []
|
||||||
self.theCounts = []
|
self._theCounts = []
|
||||||
self.theMap = {}
|
self._theMap = {}
|
||||||
self.theLength = 0
|
self._theLength = 0
|
||||||
self.theIndex = 0
|
self._theIndex = 0
|
||||||
|
|
||||||
for nName, nR, nG, nB, oName in newList:
|
for nName, nR, nG, nB, oName in newList:
|
||||||
self.addEntry(nName, (nR, nG, nB))
|
self.addEntry(nName, (nR, nG, nB))
|
||||||
@@ -104,7 +104,7 @@ class NWStatus():
|
|||||||
def resetCounts(self):
|
def resetCounts(self):
|
||||||
"""Clear the counts of references to the status entries.
|
"""Clear the counts of references to the status entries.
|
||||||
"""
|
"""
|
||||||
self.theCounts = [0]*self.theLength
|
self._theCounts = [0]*self._theLength
|
||||||
return
|
return
|
||||||
|
|
||||||
def countEntry(self, theLabel):
|
def countEntry(self, theLabel):
|
||||||
@@ -112,23 +112,23 @@ class NWStatus():
|
|||||||
"""
|
"""
|
||||||
theIndex = self.lookupEntry(theLabel)
|
theIndex = self.lookupEntry(theLabel)
|
||||||
if theIndex is not None:
|
if theIndex is not None:
|
||||||
self.theCounts[theIndex] += 1
|
self._theCounts[theIndex] += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
def packEntries(self, xParent):
|
def packXML(self, xParent):
|
||||||
"""Pack the status entries into an XML object for saving to the
|
"""Pack the status entries into an XML object for saving to the
|
||||||
main project file.
|
main project file.
|
||||||
"""
|
"""
|
||||||
for n in range(self.theLength):
|
for n in range(self._theLength):
|
||||||
xSub = etree.SubElement(xParent, "entry", attrib={
|
xSub = etree.SubElement(xParent, "entry", attrib={
|
||||||
"blue" : str(self.theColours[n][2]),
|
"blue" : str(self._theColours[n][2]),
|
||||||
"green" : str(self.theColours[n][1]),
|
"green" : str(self._theColours[n][1]),
|
||||||
"red" : str(self.theColours[n][0]),
|
"red" : str(self._theColours[n][0]),
|
||||||
})
|
})
|
||||||
xSub.text = self.theLabels[n]
|
xSub.text = self._theLabels[n]
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def unpackEntries(self, xParent):
|
def unpackXML(self, xParent):
|
||||||
"""Unpack an XML tree and set the class values.
|
"""Unpack an XML tree and set the class values.
|
||||||
"""
|
"""
|
||||||
theLabels = []
|
theLabels = []
|
||||||
@@ -151,12 +151,12 @@ class NWStatus():
|
|||||||
theColours.append((cR, cG, cB))
|
theColours.append((cR, cG, cB))
|
||||||
|
|
||||||
if len(theLabels) > 0:
|
if len(theLabels) > 0:
|
||||||
self.theLabels = []
|
self._theLabels = []
|
||||||
self.theColours = []
|
self._theColours = []
|
||||||
self.theCounts = []
|
self._theCounts = []
|
||||||
self.theMap = {}
|
self._theMap = {}
|
||||||
self.theLength = 0
|
self._theLength = 0
|
||||||
self.theIndex = 0
|
self._theIndex = 0
|
||||||
|
|
||||||
for n in range(len(theLabels)):
|
for n in range(len(theLabels)):
|
||||||
self.addEntry(theLabels[n], theColours[n])
|
self.addEntry(theLabels[n], theColours[n])
|
||||||
@@ -170,22 +170,22 @@ class NWStatus():
|
|||||||
def __getitem__(self, n):
|
def __getitem__(self, n):
|
||||||
"""Return an entry by its index.
|
"""Return an entry by its index.
|
||||||
"""
|
"""
|
||||||
if n >= 0 and n < self.theLength:
|
if n >= 0 and n < self._theLength:
|
||||||
return self.theLabels[n], self.theColours[n], self.theCounts[n]
|
return self._theLabels[n], self._theColours[n], self._theCounts[n]
|
||||||
return None, None, None
|
return None, None, None
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"""Initialise the iterator.
|
"""Initialise the iterator.
|
||||||
"""
|
"""
|
||||||
self.theIndex = 0
|
self._theIndex = 0
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __next__(self):
|
def __next__(self):
|
||||||
"""Return the next entry for the iterator.
|
"""Return the next entry for the iterator.
|
||||||
"""
|
"""
|
||||||
if self.theIndex < self.theLength:
|
if self._theIndex < self._theLength:
|
||||||
theLabel, theColour, theCount = self.__getitem__(self.theIndex)
|
theLabel, theColour, theCount = self.__getitem__(self._theIndex)
|
||||||
self.theIndex += 1
|
self._theIndex += 1
|
||||||
return theLabel, theColour, theCount
|
return theLabel, theColour, theCount
|
||||||
else:
|
else:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|||||||
+1
-2
@@ -309,8 +309,7 @@ class ToHtml(Tokenizer):
|
|||||||
def _formatKeywords(self, tText):
|
def _formatKeywords(self, tText):
|
||||||
"""Apply HTML formatting to keywords.
|
"""Apply HTML formatting to keywords.
|
||||||
"""
|
"""
|
||||||
tText = "@"+tText
|
isValid, theBits, thePos = self.theParent.theIndex.scanThis("@"+tText)
|
||||||
isValid, theBits, thePos = self.theParent.theIndex.scanThis(tText)
|
|
||||||
if not isValid or not theBits:
|
if not isValid or not theBits:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import nw
|
|
||||||
|
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from PyQt5.QtCore import QRegularExpression
|
from PyQt5.QtCore import QRegularExpression
|
||||||
@@ -74,9 +73,8 @@ class Tokenizer():
|
|||||||
|
|
||||||
def __init__(self, theProject, theParent):
|
def __init__(self, theProject, theParent):
|
||||||
|
|
||||||
self.mainConf = nw.CONFIG
|
self.theProject = theProject
|
||||||
self.theProject = theProject
|
self.theParent = theParent
|
||||||
self.theParent = theParent
|
|
||||||
|
|
||||||
# Data Variables
|
# Data Variables
|
||||||
self.theText = None # The raw text to be tokenized
|
self.theText = None # The raw text to be tokenized
|
||||||
|
|||||||
+24
-25
@@ -34,7 +34,7 @@ from hashlib import sha256
|
|||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from nw.core.item import NWItem
|
from nw.core.item import NWItem
|
||||||
from nw.common import checkString
|
from nw.common import checkHandle
|
||||||
from nw.constants import nwFiles, nwItemType, nwItemClass, nwItemLayout, nwConst
|
from nw.constants import nwFiles, nwItemType, nwItemClass, nwItemLayout, nwConst
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -49,7 +49,6 @@ class NWTree():
|
|||||||
self._treeOrder = [] # The order of the tree items on the tree view
|
self._treeOrder = [] # The order of the tree items on the tree view
|
||||||
self._treeRoots = [] # The root items of the tree
|
self._treeRoots = [] # The root items of the tree
|
||||||
self._trashRoot = None # The handle of the trash root folder
|
self._trashRoot = None # The handle of the trash root folder
|
||||||
self._theLength = 0 # Always the length of _treeOrder
|
|
||||||
self._theIndex = 0 # The current iterator index
|
self._theIndex = 0 # The current iterator index
|
||||||
self._treeChanged = False # True if tree structure has changed
|
self._treeChanged = False # True if tree structure has changed
|
||||||
self._handleSeed = None # Used for generating handles for testing
|
self._handleSeed = None # Used for generating handles for testing
|
||||||
@@ -68,7 +67,6 @@ class NWTree():
|
|||||||
self._treeRoots = []
|
self._treeRoots = []
|
||||||
self._trashRoot = None
|
self._trashRoot = None
|
||||||
self._archRoot = None
|
self._archRoot = None
|
||||||
self._theLength = 0
|
|
||||||
self._theIndex = 0
|
self._theIndex = 0
|
||||||
self._treeChanged = False
|
self._treeChanged = False
|
||||||
return
|
return
|
||||||
@@ -81,12 +79,12 @@ class NWTree():
|
|||||||
def append(self, tHandle, pHandle, nwItem):
|
def append(self, tHandle, pHandle, nwItem):
|
||||||
"""Add a new item to the end of the tree.
|
"""Add a new item to the end of the tree.
|
||||||
"""
|
"""
|
||||||
tHandle = checkString(tHandle, None, True)
|
tHandle = checkHandle(tHandle, None, True)
|
||||||
pHandle = checkString(pHandle, None, True)
|
pHandle = checkHandle(pHandle, None, True)
|
||||||
if tHandle is None:
|
if tHandle is None:
|
||||||
tHandle = self._makeHandle()
|
tHandle = self._makeHandle()
|
||||||
|
|
||||||
logger.verbose("Adding entry %s with parent %s" % (str(tHandle), str(pHandle)))
|
logger.verbose("Adding item %s with parent %s" % (str(tHandle), str(pHandle)))
|
||||||
|
|
||||||
nwItem.setHandle(tHandle)
|
nwItem.setHandle(tHandle)
|
||||||
nwItem.setParent(pHandle)
|
nwItem.setParent(pHandle)
|
||||||
@@ -95,29 +93,29 @@ class NWTree():
|
|||||||
self._treeOrder.append(tHandle)
|
self._treeOrder.append(tHandle)
|
||||||
|
|
||||||
if nwItem.itemType == nwItemType.ROOT:
|
if nwItem.itemType == nwItemType.ROOT:
|
||||||
logger.verbose("Entry %s is a root item" % str(tHandle))
|
logger.verbose("Item %s is a root item" % str(tHandle))
|
||||||
self._treeRoots.append(tHandle)
|
self._treeRoots.append(tHandle)
|
||||||
if nwItem.itemClass == nwItemClass.ARCHIVE:
|
if nwItem.itemClass == nwItemClass.ARCHIVE:
|
||||||
logger.verbose("Entry %s is the archive folder" % str(tHandle))
|
logger.verbose("Item %s is the archive folder" % str(tHandle))
|
||||||
self._archRoot = tHandle
|
self._archRoot = tHandle
|
||||||
|
|
||||||
if nwItem.itemType == nwItemType.TRASH:
|
if nwItem.itemType == nwItemType.TRASH:
|
||||||
if self._trashRoot is None:
|
if self._trashRoot is None:
|
||||||
logger.verbose("Entry %s is the trash folder" % str(tHandle))
|
logger.verbose("Item %s is the trash folder" % str(tHandle))
|
||||||
self._trashRoot = tHandle
|
self._trashRoot = tHandle
|
||||||
else:
|
else:
|
||||||
logger.error("Only one trash folder allowed")
|
logger.error("Only one trash folder allowed")
|
||||||
|
|
||||||
self._theLength = len(self._treeOrder)
|
|
||||||
self._setTreeChanged(True)
|
self._setTreeChanged(True)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def packXML(self, xParent):
|
def packXML(self, xParent):
|
||||||
"""Pack the content of the tree into an XML object.
|
"""Pack the content of the tree into the provided XML object. In
|
||||||
|
the order defined by the _treeOrder list.
|
||||||
"""
|
"""
|
||||||
xContent = etree.SubElement(xParent, "content", attrib={
|
xContent = etree.SubElement(xParent, "content", attrib={
|
||||||
"count": str(self._theLength)}
|
"count": str(len(self._treeOrder))}
|
||||||
)
|
)
|
||||||
for tHandle in self._treeOrder:
|
for tHandle in self._treeOrder:
|
||||||
tItem = self.__getitem__(tHandle)
|
tItem = self.__getitem__(tHandle)
|
||||||
@@ -309,7 +307,6 @@ class NWTree():
|
|||||||
|
|
||||||
# Save the temp list
|
# Save the temp list
|
||||||
self._treeOrder = tmpOrder
|
self._treeOrder = tmpOrder
|
||||||
self._theLength = len(self._treeOrder)
|
|
||||||
self._setTreeChanged(True)
|
self._setTreeChanged(True)
|
||||||
logger.verbose("Project tree order updated")
|
logger.verbose("Project tree order updated")
|
||||||
|
|
||||||
@@ -330,7 +327,7 @@ class NWTree():
|
|||||||
if tItem is None:
|
if tItem is None:
|
||||||
return False
|
return False
|
||||||
if tItem.itemType != nwItemType.FILE:
|
if tItem.itemType != nwItemType.FILE:
|
||||||
logger.error("Item '%s' is not a file" % tHandle)
|
logger.error("Item %s is not a file" % tHandle)
|
||||||
return False
|
return False
|
||||||
if not isinstance(itemLayout, nwItemLayout):
|
if not isinstance(itemLayout, nwItemLayout):
|
||||||
return False
|
return False
|
||||||
@@ -370,12 +367,12 @@ class NWTree():
|
|||||||
def __len__(self):
|
def __len__(self):
|
||||||
"""Return the length counter. Does not check that it is correct!
|
"""Return the length counter. Does not check that it is correct!
|
||||||
"""
|
"""
|
||||||
return self._theLength
|
return len(self._treeOrder)
|
||||||
|
|
||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
"""Returns True if the tree has any entries.
|
"""Returns True if the tree has any entries.
|
||||||
"""
|
"""
|
||||||
return self._theLength > 0
|
return len(self._treeOrder) > 0
|
||||||
|
|
||||||
##
|
##
|
||||||
# Item Access Methods
|
# Item Access Methods
|
||||||
@@ -391,19 +388,21 @@ class NWTree():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def __delitem__(self, tHandle):
|
def __delitem__(self, tHandle):
|
||||||
"""This only removes the item from the order list, but not from
|
"""Remove an item from the internal lists and dictionaries.
|
||||||
the project tree.
|
|
||||||
"""
|
"""
|
||||||
if tHandle not in self._treeOrder:
|
if tHandle in self._treeOrder and tHandle in self._projTree:
|
||||||
logger.warning(
|
self._treeOrder.remove(tHandle)
|
||||||
"Could not remove item %s from project tree as it does not exist" % tHandle
|
del self._projTree[tHandle]
|
||||||
)
|
else:
|
||||||
|
logger.warning("Failed to delete item %s: item not found" % tHandle)
|
||||||
return False
|
return False
|
||||||
self._treeOrder.remove(tHandle)
|
|
||||||
self._theLength = len(self._treeOrder)
|
|
||||||
|
|
||||||
if tHandle in self._treeRoots:
|
if tHandle in self._treeRoots:
|
||||||
self._treeRoots.remove(tHandle)
|
self._treeRoots.remove(tHandle)
|
||||||
|
if tHandle == self._trashRoot:
|
||||||
|
self._trashRoot = None
|
||||||
|
if tHandle == self._archRoot:
|
||||||
|
self._archRoot = None
|
||||||
|
|
||||||
self._setTreeChanged(True)
|
self._setTreeChanged(True)
|
||||||
|
|
||||||
@@ -427,7 +426,7 @@ class NWTree():
|
|||||||
def __next__(self):
|
def __next__(self):
|
||||||
"""Returns the item from the next entry in the _treeOrder list.
|
"""Returns the item from the next entry in the _treeOrder list.
|
||||||
"""
|
"""
|
||||||
if self._theIndex < self._theLength:
|
if self._theIndex < len(self._treeOrder):
|
||||||
theItem = self.__getitem__(self._treeOrder[self._theIndex])
|
theItem = self.__getitem__(self._treeOrder[self._theIndex])
|
||||||
self._theIndex += 1
|
self._theIndex += 1
|
||||||
return theItem
|
return theItem
|
||||||
|
|||||||
+17
-15
@@ -270,10 +270,12 @@ class GuiDocEditor(QTextEdit):
|
|||||||
afTime = time()
|
afTime = time()
|
||||||
logger.debug("Document highlighted in %.3f milliseconds" % (1000*(afTime-bfTime)))
|
logger.debug("Document highlighted in %.3f milliseconds" % (1000*(afTime-bfTime)))
|
||||||
|
|
||||||
if tLine is None:
|
theItem = self.nwDocument.getCurrentItem()
|
||||||
self.setCursorPosition(self.nwDocument.theItem.cursorPos)
|
if tLine is None and theItem is not None:
|
||||||
|
self.setCursorPosition(theItem.cursorPos)
|
||||||
else:
|
else:
|
||||||
self.setCursorLine(tLine)
|
self.setCursorLine(tLine)
|
||||||
|
|
||||||
self.lastEdit = time()
|
self.lastEdit = time()
|
||||||
self._runCounter()
|
self._runCounter()
|
||||||
self.wcTimer.start()
|
self.wcTimer.start()
|
||||||
@@ -308,21 +310,20 @@ class GuiDocEditor(QTextEdit):
|
|||||||
"""Save the text currently in the editor to the NWDoc object,
|
"""Save the text currently in the editor to the NWDoc object,
|
||||||
and update the NWItem meta data.
|
and update the NWItem meta data.
|
||||||
"""
|
"""
|
||||||
if self.nwDocument.theItem is None:
|
theItem = self.nwDocument.getCurrentItem()
|
||||||
|
if theItem is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
docText = self.getText()
|
docText = self.getText()
|
||||||
cursPos = self.getCursorPosition()
|
cursPos = self.getCursorPosition()
|
||||||
self.nwDocument.theItem.setCharCount(self.charCount)
|
theItem.setCharCount(self.charCount)
|
||||||
self.nwDocument.theItem.setWordCount(self.wordCount)
|
theItem.setWordCount(self.wordCount)
|
||||||
self.nwDocument.theItem.setParaCount(self.paraCount)
|
theItem.setParaCount(self.paraCount)
|
||||||
self.nwDocument.theItem.setCursorPos(cursPos)
|
theItem.setCursorPos(cursPos)
|
||||||
self.nwDocument.saveDocument(docText)
|
self.nwDocument.saveDocument(docText)
|
||||||
self.setDocumentChanged(False)
|
self.setDocumentChanged(False)
|
||||||
|
|
||||||
self.theParent.theIndex.scanText(
|
self.theParent.theIndex.scanText(theItem.itemHandle, docText)
|
||||||
self.nwDocument.theItem.itemHandle, docText
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -598,7 +599,7 @@ class GuiDocEditor(QTextEdit):
|
|||||||
"Location: {fileLoc:s}"
|
"Location: {fileLoc:s}"
|
||||||
).format(
|
).format(
|
||||||
handle = self.theHandle,
|
handle = self.theHandle,
|
||||||
fileLoc = str(self.nwDocument.fileLoc)
|
fileLoc = str(self.nwDocument.getFileLocation())
|
||||||
))
|
))
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -873,7 +874,8 @@ class GuiDocEditor(QTextEdit):
|
|||||||
def _updateCounts(self):
|
def _updateCounts(self):
|
||||||
"""Slot for the word counter's finished signal
|
"""Slot for the word counter's finished signal
|
||||||
"""
|
"""
|
||||||
if self.theHandle is None or self.nwDocument.theItem is None:
|
theItem = self.nwDocument.getCurrentItem()
|
||||||
|
if self.theHandle is None or theItem is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.verbose("Updating word count")
|
logger.verbose("Updating word count")
|
||||||
@@ -881,9 +883,9 @@ class GuiDocEditor(QTextEdit):
|
|||||||
self.charCount = self.wCounter.charCount
|
self.charCount = self.wCounter.charCount
|
||||||
self.wordCount = self.wCounter.wordCount
|
self.wordCount = self.wCounter.wordCount
|
||||||
self.paraCount = self.wCounter.paraCount
|
self.paraCount = self.wCounter.paraCount
|
||||||
self.nwDocument.theItem.setCharCount(self.charCount)
|
theItem.setCharCount(self.charCount)
|
||||||
self.nwDocument.theItem.setWordCount(self.wordCount)
|
theItem.setWordCount(self.wordCount)
|
||||||
self.nwDocument.theItem.setParaCount(self.paraCount)
|
theItem.setParaCount(self.paraCount)
|
||||||
|
|
||||||
self.theParent.treeView.propagateCount(self.theHandle, self.wordCount)
|
self.theParent.treeView.propagateCount(self.theHandle, self.wordCount)
|
||||||
self.theParent.treeView.projectWordCount()
|
self.theParent.treeView.projectWordCount()
|
||||||
|
|||||||
+7
-4
@@ -639,7 +639,8 @@ class GuiDocViewHistory():
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _truncateHistory(self, atPos):
|
def _truncateHistory(self, atPos):
|
||||||
"""Truncate the navigation history to the given position.
|
"""Truncate the navigation history to the given position. Also
|
||||||
|
enforces a maximum length of the navigation history to 20.
|
||||||
"""
|
"""
|
||||||
nSkip = 1 if atPos > 19 else 0
|
nSkip = 1 if atPos > 19 else 0
|
||||||
|
|
||||||
@@ -652,13 +653,15 @@ class GuiDocViewHistory():
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _dumpHistory(self):
|
def _dumpHistory(self):
|
||||||
"""Debug function to dump history. Since it is a for loop, it is
|
"""Debug function to dump history to the logger. Since it is a
|
||||||
skipped entirely if log level isn't VERBOSE.
|
for loop, it is skipped entirely if log level isn't VERBOSE.
|
||||||
"""
|
"""
|
||||||
if logger.getEffectiveLevel() < logging.DEBUG:
|
if logger.getEffectiveLevel() < logging.DEBUG:
|
||||||
for i, (h, p) in enumerate(zip(self._navHistory, self._posHistory)):
|
for i, (h, p) in enumerate(zip(self._navHistory, self._posHistory)):
|
||||||
logger.verbose(
|
logger.verbose(
|
||||||
"History: %s %2d %13s %5d" % (">" if i == self._currPos else " ", i, h, p)
|
"History %02d: %s %13s [x:%d]" % (
|
||||||
|
i + 1, ">" if i == self._currPos else " ", h, p
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -378,11 +378,11 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def deleteItem(self, tHandle=None, alreadyAsked=False, askForTrash=False):
|
def deleteItem(self, tHandle=None, alreadyAsked=False, askForTrash=False):
|
||||||
"""Delete items from the tree. Note that this does not delete
|
"""Delete an item from the project tree. As a first step, files are
|
||||||
the item from the item tree in the project object. However,
|
moved to the Trash folder. Permanent deletion is a second step. This
|
||||||
since this is only meta data, there isn't really a need to do
|
second step also deletes the item from the project object as well as
|
||||||
that to save memory. Items not in the tree are not saved to the
|
delete the files on disk. Folders are deleted if they're empty only,
|
||||||
project file, so a loaded project will be clean anyway.
|
and the deletion is always permanent.
|
||||||
"""
|
"""
|
||||||
if tHandle is None:
|
if tHandle is None:
|
||||||
tHandle = self.getSelectedHandle()
|
tHandle = self.getSelectedHandle()
|
||||||
@@ -584,7 +584,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
always make sure items with a parent have had their parent item
|
always make sure items with a parent have had their parent item
|
||||||
sent first.
|
sent first.
|
||||||
"""
|
"""
|
||||||
logger.debug("Building project tree ...")
|
logger.debug("Building the project tree ...")
|
||||||
self.clear()
|
self.clear()
|
||||||
iCount = 0
|
iCount = 0
|
||||||
|
|
||||||
@@ -592,7 +592,7 @@ class GuiProjectTree(QTreeWidget):
|
|||||||
iCount += 1
|
iCount += 1
|
||||||
self._addTreeItem(nwItem)
|
self._addTreeItem(nwItem)
|
||||||
|
|
||||||
logger.debug("%d items added to project tree" % iCount)
|
logger.debug("%d items added to the project tree" % iCount)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getSelectedHandle(self):
|
def getSelectedHandle(self):
|
||||||
|
|||||||
+10
-1
@@ -5,7 +5,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from nw.common import (
|
from nw.common import (
|
||||||
checkString, checkBool, checkInt, colRange, formatInt, transferCase,
|
checkString, checkBool, checkInt, colRange, formatInt, transferCase,
|
||||||
fuzzyTime
|
fuzzyTime, checkHandle
|
||||||
)
|
)
|
||||||
from nwtools import cmpList
|
from nwtools import cmpList
|
||||||
|
|
||||||
@@ -42,6 +42,15 @@ def testCheckBool():
|
|||||||
assert checkBool(1.0, None, False) is None
|
assert checkBool(1.0, None, False) is None
|
||||||
assert checkBool(2.0, None, False) is None
|
assert checkBool(2.0, None, False) is None
|
||||||
|
|
||||||
|
@pytest.mark.core
|
||||||
|
def testCheckHandle():
|
||||||
|
assert checkHandle("None", 1, True) is None
|
||||||
|
assert checkHandle("None", 1, False) == 1
|
||||||
|
assert checkHandle(None, 1, True) is None
|
||||||
|
assert checkHandle(None, 1, False) == 1
|
||||||
|
assert checkHandle("47666c91c7ccf", None, False) == "47666c91c7ccf"
|
||||||
|
assert checkHandle("h7666c91c7ccf", None, False) is None
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testColRange():
|
def testColRange():
|
||||||
assert colRange([0, 0], [0, 0], 0) is None
|
assert colRange([0, 0], [0, 0], 0) is None
|
||||||
|
|||||||
+61
-2
@@ -12,7 +12,7 @@ from nw.core.project import NWProject
|
|||||||
from nw.core.document import NWDoc
|
from nw.core.document import NWDoc
|
||||||
from nw.core.index import NWIndex
|
from nw.core.index import NWIndex
|
||||||
from nw.core.spellcheck import NWSpellEnchant, NWSpellSimple
|
from nw.core.spellcheck import NWSpellEnchant, NWSpellSimple
|
||||||
from nw.constants import nwItemClass, nwItemLayout
|
from nw.constants import nwItemClass, nwItemLayout, nwFiles
|
||||||
|
|
||||||
@pytest.mark.project
|
@pytest.mark.project
|
||||||
def testProjectNewOpenSave(nwFuncTemp, nwTempProj, nwRef, nwTemp, nwDummy):
|
def testProjectNewOpenSave(nwFuncTemp, nwTempProj, nwRef, nwTemp, nwDummy):
|
||||||
@@ -316,7 +316,7 @@ def testDocMeta(nwDummy, nwLipsum):
|
|||||||
assert theClass == nwItemClass.NOVEL
|
assert theClass == nwItemClass.NOVEL
|
||||||
assert theLayout == nwItemLayout.SCENE
|
assert theLayout == nwItemLayout.SCENE
|
||||||
|
|
||||||
aDoc.docMeta = "too_short"
|
aDoc._docMeta = "too_short"
|
||||||
theMeta, thePath, theClass, theLayout = aDoc.getMeta()
|
theMeta, thePath, theClass, theLayout = aDoc.getMeta()
|
||||||
assert theMeta == ""
|
assert theMeta == ""
|
||||||
assert thePath == []
|
assert thePath == []
|
||||||
@@ -372,3 +372,62 @@ def testSpellSimple(nwTemp, nwConf):
|
|||||||
|
|
||||||
dList = spChk.listDictionaries()
|
dList = spChk.listDictionaries()
|
||||||
assert len(dList) > 0
|
assert len(dList) > 0
|
||||||
|
|
||||||
|
@pytest.mark.project
|
||||||
|
def testProjectOptions(nwDummy, nwLipsum):
|
||||||
|
theProject = NWProject(nwDummy)
|
||||||
|
assert theProject.projMeta is None
|
||||||
|
|
||||||
|
theOpts = theProject.optState
|
||||||
|
assert not theOpts.loadSettings()
|
||||||
|
assert not theOpts.saveSettings()
|
||||||
|
|
||||||
|
# No Settings
|
||||||
|
assert theProject.openProject(nwLipsum)
|
||||||
|
assert theOpts.loadSettings()
|
||||||
|
assert theOpts.saveSettings()
|
||||||
|
assert str(theOpts.theState) == r"{}"
|
||||||
|
|
||||||
|
# Read Invalid Settings and Filter
|
||||||
|
stateFile = path.join(theProject.projMeta, nwFiles.OPTS_FILE)
|
||||||
|
with open(stateFile, mode="w", encoding="utf8") as outFile:
|
||||||
|
outFile.write(
|
||||||
|
r'{"GuiProjectSettings": {"winWidth": 100, "winHeight": 50}, "NoGroup": {"NoName": 0}}'
|
||||||
|
)
|
||||||
|
assert theOpts.loadSettings()
|
||||||
|
assert str(theOpts.theState) == r"{'GuiProjectSettings': {'winWidth': 100, 'winHeight': 50}}"
|
||||||
|
|
||||||
|
# Set New Settings
|
||||||
|
assert not theOpts.setValue("NoGroup", "NoName", None)
|
||||||
|
assert not theOpts.setValue("GuiProjectSettings", "NoName", None)
|
||||||
|
assert theOpts.setValue("GuiProjectSettings", "winWidth", 200)
|
||||||
|
assert theOpts.setValue("GuiProjectSettings", "winHeight", 80)
|
||||||
|
assert str(theOpts.theState) == r"{'GuiProjectSettings': {'winWidth': 200, 'winHeight': 80}}"
|
||||||
|
|
||||||
|
# Check Read/Write Types
|
||||||
|
|
||||||
|
## String
|
||||||
|
assert theOpts.setValue("GuiWritingStats", "winWidth", "123")
|
||||||
|
assert isinstance(theOpts.getString("GuiWritingStats", "winWidth", "456"), str)
|
||||||
|
assert theOpts.getString("GuiWritingStats", "NoName", "456") == "456"
|
||||||
|
|
||||||
|
## Int
|
||||||
|
assert theOpts.setValue("GuiWritingStats", "winWidth", "123")
|
||||||
|
assert isinstance(theOpts.getInt("GuiWritingStats", "winWidth", 456), int)
|
||||||
|
assert theOpts.getInt("GuiWritingStats", "NoName", 456) == 456
|
||||||
|
assert theOpts.setValue("GuiWritingStats", "winWidth", "True")
|
||||||
|
assert theOpts.getInt("GuiWritingStats", "NoName", 456) == 456
|
||||||
|
|
||||||
|
## Float
|
||||||
|
assert theOpts.setValue("GuiWritingStats", "winWidth", "123")
|
||||||
|
assert isinstance(theOpts.getFloat("GuiWritingStats", "winWidth", 456.0), float)
|
||||||
|
assert theOpts.getFloat("GuiWritingStats", "NoName", 456.0) == 456.0
|
||||||
|
assert theOpts.setValue("GuiWritingStats", "winWidth", "True")
|
||||||
|
assert theOpts.getFloat("GuiWritingStats", "winWidth", 456.0) == 456.0
|
||||||
|
|
||||||
|
## Bool
|
||||||
|
assert theOpts.setValue("GuiWritingStats", "winWidth", True)
|
||||||
|
assert isinstance(theOpts.getBool("GuiWritingStats", "winWidth", False), bool)
|
||||||
|
assert theOpts.getFloat("GuiWritingStats", "NoName", False) is False
|
||||||
|
assert theOpts.setValue("GuiWritingStats", "winWidth", "True")
|
||||||
|
assert theOpts.getFloat("GuiWritingStats", "winWidth", False) is False
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""novelWriter Tools Tester
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from nw.core.tools import countWords, numberToRoman, numberToWord
|
||||||
|
|
||||||
|
@pytest.mark.core
|
||||||
|
def testCountWords():
|
||||||
|
testText = (
|
||||||
|
"# Heading One\n"
|
||||||
|
"## Heading Two\n"
|
||||||
|
"### Heading Three\n"
|
||||||
|
"#### Heading Four\n"
|
||||||
|
"\n"
|
||||||
|
"@tag: value\n"
|
||||||
|
"\n"
|
||||||
|
"% A comment that should n ot be counted.\n"
|
||||||
|
"\n"
|
||||||
|
"The first paragraph.\n"
|
||||||
|
"\n"
|
||||||
|
"The second paragraph.\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"The third paragraph.\n"
|
||||||
|
)
|
||||||
|
cC, wC, pC = countWords(testText)
|
||||||
|
|
||||||
|
assert cC == 108
|
||||||
|
assert wC == 17
|
||||||
|
assert pC == 3
|
||||||
|
|
||||||
|
@pytest.mark.core
|
||||||
|
def testNumberWords():
|
||||||
|
assert numberToWord(0, "en") == "Zero"
|
||||||
|
assert numberToWord(1, "en") == "One"
|
||||||
|
assert numberToWord(2, "en") == "Two"
|
||||||
|
assert numberToWord(3, "en") == "Three"
|
||||||
|
assert numberToWord(4, "en") == "Four"
|
||||||
|
assert numberToWord(5, "en") == "Five"
|
||||||
|
assert numberToWord(6, "en") == "Six"
|
||||||
|
assert numberToWord(7, "en") == "Seven"
|
||||||
|
assert numberToWord(8, "en") == "Eight"
|
||||||
|
assert numberToWord(9, "en") == "Nine"
|
||||||
|
assert numberToWord(10, "en") == "Ten"
|
||||||
|
assert numberToWord(11, "en") == "Eleven"
|
||||||
|
assert numberToWord(12, "en") == "Twelve"
|
||||||
|
assert numberToWord(13, "en") == "Thirteen"
|
||||||
|
assert numberToWord(14, "en") == "Fourteen"
|
||||||
|
assert numberToWord(15, "en") == "Fifteen"
|
||||||
|
assert numberToWord(16, "en") == "Sixteen"
|
||||||
|
assert numberToWord(17, "en") == "Seventeen"
|
||||||
|
assert numberToWord(18, "en") == "Eighteen"
|
||||||
|
assert numberToWord(19, "en") == "Nineteen"
|
||||||
|
assert numberToWord(20, "en") == "Twenty"
|
||||||
|
assert numberToWord(21, "en") == "Twenty-One"
|
||||||
|
assert numberToWord(29, "en") == "Twenty-Nine"
|
||||||
|
assert numberToWord(42, "en") == "Forty-Two"
|
||||||
|
assert numberToWord(142, "en") == "One Hundred Forty-Two"
|
||||||
|
assert numberToWord(999, "en") == "Nine Hundred Ninety-Nine"
|
||||||
|
|
||||||
|
@pytest.mark.core
|
||||||
|
def testRomanNumbers():
|
||||||
|
assert numberToRoman(None, False) == "NAN"
|
||||||
|
assert numberToRoman(0, False) == "OOR"
|
||||||
|
assert numberToRoman(1, False) == "I"
|
||||||
|
assert numberToRoman(2, False) == "II"
|
||||||
|
assert numberToRoman(3, False) == "III"
|
||||||
|
assert numberToRoman(4, False) == "IV"
|
||||||
|
assert numberToRoman(5, False) == "V"
|
||||||
|
assert numberToRoman(6, False) == "VI"
|
||||||
|
assert numberToRoman(7, False) == "VII"
|
||||||
|
assert numberToRoman(8, False) == "VIII"
|
||||||
|
assert numberToRoman(9, False) == "IX"
|
||||||
|
assert numberToRoman(10, False) == "X"
|
||||||
|
assert numberToRoman(14, False) == "XIV"
|
||||||
|
assert numberToRoman(42, False) == "XLII"
|
||||||
|
assert numberToRoman(99, False) == "XCIX"
|
||||||
|
assert numberToRoman(142, False) == "CXLII"
|
||||||
|
assert numberToRoman(542, False) == "DXLII"
|
||||||
|
assert numberToRoman(999, False) == "CMXCIX"
|
||||||
|
assert numberToRoman(2010, False) == "MMX"
|
||||||
|
assert numberToRoman(999, True) == "cmxcix"
|
||||||
Reference in New Issue
Block a user