From 64ae52e7aa48a742c01810d33aacc1919e94d2d3 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Thu, 7 May 2020 20:02:49 +0200 Subject: [PATCH] Moved NWItem and NWStatus into the project file as the classes are no longer called from elsewhere --- nw/project/__init__.py | 4 - nw/project/item.py | 232 --------------------------- nw/project/project.py | 345 ++++++++++++++++++++++++++++++++++++++++- nw/project/status.py | 170 -------------------- tests/test_item.py | 3 +- 5 files changed, 344 insertions(+), 410 deletions(-) delete mode 100644 nw/project/item.py delete mode 100644 nw/project/status.py diff --git a/nw/project/__init__.py b/nw/project/__init__.py index d7065c78..b36f5a5e 100644 --- a/nw/project/__init__.py +++ b/nw/project/__init__.py @@ -3,15 +3,11 @@ from nw.project.backup import NWBackup from nw.project.document import NWDoc from nw.project.index import NWIndex -from nw.project.item import NWItem from nw.project.project import NWProject -from nw.project.status import NWStatus __all__ = [ "NWBackup", "NWDoc", "NWIndex", - "NWItem", "NWProject", - "NWStatus", ] diff --git a/nw/project/item.py b/nw/project/item.py deleted file mode 100644 index f0462dbe..00000000 --- a/nw/project/item.py +++ /dev/null @@ -1,232 +0,0 @@ -# -*- coding: utf-8 -*- -"""novelWriter Project Item - - novelWriter – Project Item -============================ - Class holding a project item - - File History: - Created: 2018-10-27 [0.0.1] - - This file is a part of novelWriter - Copyright 2020, Veronica Berglyd Olsen - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" - -import logging -import nw - -from lxml import etree - -from nw.common import checkInt -from nw.constants import nwItemType, nwItemClass, nwItemLayout - -logger = logging.getLogger(__name__) - -class NWItem(): - - def __init__(self, theProject): - - self.theProject = theProject - - self.itemName = "" - self.itemHandle = None - self.parHandle = None - self.itemOrder = None - self.itemType = nwItemType.NO_TYPE - self.itemClass = nwItemClass.NO_CLASS - self.itemLayout = nwItemLayout.NO_LAYOUT - self.itemStatus = None - self.isExpanded = False - - # Document Meta Data - self.charCount = 0 - self.wordCount = 0 - self.paraCount = 0 - self.cursorPos = 0 - - return - - ## - # XML Pack - ## - - def packXML(self, xParent): - """Packs all the data in the class instance into an XML object. - """ - xPack = etree.SubElement(xParent,"item",attrib={ - "handle" : str(self.itemHandle), - "order" : str(self.itemOrder), - "parent" : str(self.parHandle), - }) - xSub = self._subPack(xPack,"name", text=str(self.itemName)) - xSub = self._subPack(xPack,"type", text=str(self.itemType.name)) - xSub = self._subPack(xPack,"class", text=str(self.itemClass.name)) - xSub = self._subPack(xPack,"status", text=str(self.itemStatus)) - xSub = self._subPack(xPack,"expanded", text=str(self.isExpanded)) - if self.itemType == nwItemType.FILE: - xSub = self._subPack(xPack,"layout", text=str(self.itemLayout.name)) - xSub = self._subPack(xPack,"charCount", text=str(self.charCount), none=False) - xSub = self._subPack(xPack,"wordCount", text=str(self.wordCount), none=False) - xSub = self._subPack(xPack,"paraCount", text=str(self.paraCount), none=False) - xSub = self._subPack(xPack,"cursorPos", text=str(self.cursorPos), none=False) - return - - def unpackXML(self, xItem): - """Sets the values from an XML entry of type 'item'. - """ - - if xItem.tag != "item": - logger.error("XML entry is not an NWItem") - return False - - if "handle" in xItem.attrib: - self.itemHandle = xItem.attrib["handle"] - else: - logger.error("XML item entry does not have a handle") - return False - - if "parent" in xItem.attrib: - self.parHandle = xItem.attrib["parent"] - - setMap = { - "name" : self.setName, - "order" : self.setOrder, - "type" : self.setType, - "class" : self.setClass, - "layout" : self.setLayout, - "status" : self.setStatus, - "expanded" : self.setExpanded, - "charCount" : self.setCharCount, - "wordCount" : self.setWordCount, - "paraCount" : self.setParaCount, - "cursorPos" : self.setCursorPos, - } - for xValue in xItem: - if xValue.tag in setMap: - setMap[xValue.tag](xValue.text) - else: - logger.error("Unknown tag '%s'" % xValue.tag) - - return True - - @staticmethod - def _subPack(xParent, name, attrib=None, text=None, none=True): - if not none and (text == None or text == "None"): - return None - xSub = etree.SubElement(xParent,name,attrib=attrib) - if text is not None: - xSub.text = text - return xSub - - ## - # Set Item Values - ## - - def setName(self, theName): - self.itemName = theName.strip() - return - - def setHandle(self, theHandle): - if isinstance(theHandle, str): - if len(theHandle) == 13: - self.itemHandle = theHandle - else: - self.itemHandle = None - else: - self.itemHandle = None - return - - def setParent(self, theParent): - if theParent is None: - self.parHandle = None - elif isinstance(theParent, str): - if len(theParent) == 13: - self.parHandle = theParent - else: - self.parHandle = None - else: - self.parHandle = None - return - - def setOrder(self, theOrder): - self.itemOrder = checkInt(theOrder, 0) - return - - def setType(self, theType): - if isinstance(theType, nwItemType): - self.itemType = theType - elif theType in nwItemType.__members__: - self.itemType = nwItemType[theType] - else: - logger.error("Unrecognised item type '%s'" % theType) - self.itemType = nwItemType.NO_TYPE - return - - def setClass(self, theClass): - if isinstance(theClass, nwItemClass): - self.itemClass = theClass - elif theClass in nwItemClass.__members__: - self.itemClass = nwItemClass[theClass] - else: - logger.error("Unrecognised item class '%s'" % theClass) - self.itemClass = nwItemClass.NO_CLASS - return - - def setLayout(self, theLayout): - if isinstance(theLayout, nwItemLayout): - self.itemLayout = theLayout - elif theLayout in nwItemLayout.__members__: - self.itemLayout = nwItemLayout[theLayout] - else: - logger.error("Unrecognised item layout '%s'" % theLayout) - self.itemLayout = nwItemLayout.NO_LAYOUT - return - - def setStatus(self, theStatus): - if self.itemClass == nwItemClass.NOVEL: - self.itemStatus = self.theProject.statusItems.checkEntry(theStatus) - else: - self.itemStatus = self.theProject.importItems.checkEntry(theStatus) - return - - def setExpanded(self, expState): - if isinstance(expState, str): - self.isExpanded = expState == str(True) - else: - self.isExpanded = expState == True - return - - ## - # Set Document Meta Data - ## - - def setCharCount(self, theCount): - self.charCount = checkInt(theCount,0) - return - - def setWordCount(self, theCount): - self.wordCount = checkInt(theCount,0) - return - - def setParaCount(self, theCount): - self.paraCount = checkInt(theCount,0) - return - - def setCursorPos(self, thePosition): - self.cursorPos = checkInt(thePosition,0) - return - -# END Class NWItem diff --git a/nw/project/project.py b/nw/project/project.py index 674cba92..9ee3844f 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -7,6 +7,8 @@ File History: Created: 2018-09-29 [0.0.1] + Merged: 2020-05-07 [0.4.5] Merged NWItem class into file + Merged: 2020-05-07 [0.4.5] Merged NWStatus class into file This file is a part of novelWriter Copyright 2020, Veronica Berglyd Olsen @@ -34,8 +36,6 @@ from hashlib import sha256 from datetime import datetime from time import time -from nw.project.status import NWStatus -from nw.project.item import NWItem from nw.tools import projectMaintenance, OptionState from nw.common import checkString, checkBool, checkInt from nw.constants import ( @@ -934,3 +934,344 @@ class NWProject(): return itemHandle # END Class NWProject + +# ================================================================================================ # +# NWItem +# Class holding the project items making up the NWProject +# ================================================================================================ # + +class NWItem(): + + def __init__(self, theProject): + + self.theProject = theProject + + self.itemName = "" + self.itemHandle = None + self.parHandle = None + self.itemOrder = None + self.itemType = nwItemType.NO_TYPE + self.itemClass = nwItemClass.NO_CLASS + self.itemLayout = nwItemLayout.NO_LAYOUT + self.itemStatus = None + self.isExpanded = False + + # Document Meta Data + self.charCount = 0 + self.wordCount = 0 + self.paraCount = 0 + self.cursorPos = 0 + + return + + ## + # XML Pack + ## + + def packXML(self, xParent): + """Packs all the data in the class instance into an XML object. + """ + xPack = etree.SubElement(xParent,"item",attrib={ + "handle" : str(self.itemHandle), + "order" : str(self.itemOrder), + "parent" : str(self.parHandle), + }) + xSub = self._subPack(xPack,"name", text=str(self.itemName)) + xSub = self._subPack(xPack,"type", text=str(self.itemType.name)) + xSub = self._subPack(xPack,"class", text=str(self.itemClass.name)) + xSub = self._subPack(xPack,"status", text=str(self.itemStatus)) + xSub = self._subPack(xPack,"expanded", text=str(self.isExpanded)) + if self.itemType == nwItemType.FILE: + xSub = self._subPack(xPack,"layout", text=str(self.itemLayout.name)) + xSub = self._subPack(xPack,"charCount", text=str(self.charCount), none=False) + xSub = self._subPack(xPack,"wordCount", text=str(self.wordCount), none=False) + xSub = self._subPack(xPack,"paraCount", text=str(self.paraCount), none=False) + xSub = self._subPack(xPack,"cursorPos", text=str(self.cursorPos), none=False) + return + + def unpackXML(self, xItem): + """Sets the values from an XML entry of type 'item'. + """ + + if xItem.tag != "item": + logger.error("XML entry is not an NWItem") + return False + + if "handle" in xItem.attrib: + self.itemHandle = xItem.attrib["handle"] + else: + logger.error("XML item entry does not have a handle") + return False + + if "parent" in xItem.attrib: + self.parHandle = xItem.attrib["parent"] + + setMap = { + "name" : self.setName, + "order" : self.setOrder, + "type" : self.setType, + "class" : self.setClass, + "layout" : self.setLayout, + "status" : self.setStatus, + "expanded" : self.setExpanded, + "charCount" : self.setCharCount, + "wordCount" : self.setWordCount, + "paraCount" : self.setParaCount, + "cursorPos" : self.setCursorPos, + } + for xValue in xItem: + if xValue.tag in setMap: + setMap[xValue.tag](xValue.text) + else: + logger.error("Unknown tag '%s'" % xValue.tag) + + return True + + @staticmethod + def _subPack(xParent, name, attrib=None, text=None, none=True): + if not none and (text == None or text == "None"): + return None + xSub = etree.SubElement(xParent,name,attrib=attrib) + if text is not None: + xSub.text = text + return xSub + + ## + # Set Item Values + ## + + def setName(self, theName): + self.itemName = theName.strip() + return + + def setHandle(self, theHandle): + if isinstance(theHandle, str): + if len(theHandle) == 13: + self.itemHandle = theHandle + else: + self.itemHandle = None + else: + self.itemHandle = None + return + + def setParent(self, theParent): + if theParent is None: + self.parHandle = None + elif isinstance(theParent, str): + if len(theParent) == 13: + self.parHandle = theParent + else: + self.parHandle = None + else: + self.parHandle = None + return + + def setOrder(self, theOrder): + self.itemOrder = checkInt(theOrder, 0) + return + + def setType(self, theType): + if isinstance(theType, nwItemType): + self.itemType = theType + elif theType in nwItemType.__members__: + self.itemType = nwItemType[theType] + else: + logger.error("Unrecognised item type '%s'" % theType) + self.itemType = nwItemType.NO_TYPE + return + + def setClass(self, theClass): + if isinstance(theClass, nwItemClass): + self.itemClass = theClass + elif theClass in nwItemClass.__members__: + self.itemClass = nwItemClass[theClass] + else: + logger.error("Unrecognised item class '%s'" % theClass) + self.itemClass = nwItemClass.NO_CLASS + return + + def setLayout(self, theLayout): + if isinstance(theLayout, nwItemLayout): + self.itemLayout = theLayout + elif theLayout in nwItemLayout.__members__: + self.itemLayout = nwItemLayout[theLayout] + else: + logger.error("Unrecognised item layout '%s'" % theLayout) + self.itemLayout = nwItemLayout.NO_LAYOUT + return + + def setStatus(self, theStatus): + if self.itemClass == nwItemClass.NOVEL: + self.itemStatus = self.theProject.statusItems.checkEntry(theStatus) + else: + self.itemStatus = self.theProject.importItems.checkEntry(theStatus) + return + + def setExpanded(self, expState): + if isinstance(expState, str): + self.isExpanded = expState == str(True) + else: + self.isExpanded = expState == True + return + + ## + # Set Document Meta Data + ## + + def setCharCount(self, theCount): + self.charCount = checkInt(theCount,0) + return + + def setWordCount(self, theCount): + self.wordCount = checkInt(theCount,0) + return + + def setParaCount(self, theCount): + self.paraCount = checkInt(theCount,0) + return + + def setCursorPos(self, thePosition): + self.cursorPos = checkInt(thePosition,0) + return + +# END Class NWItem + +# ================================================================================================ # +# NWStatus +# Class holding the item status values stored in the NWProject +# ================================================================================================ # + +class NWStatus(): + + def __init__(self): + self.theLabels = [] + self.theColours = [] + self.theCounts = [] + self.theMap = {} + self.theLength = 0 + self.theIndex = 0 + return + + def addEntry(self, theLabel, theColours): + theLabel = theLabel.strip() + if self.lookupEntry(theLabel) is None: + self.theLabels.append(theLabel) + self.theColours.append(theColours) + self.theCounts.append(0) + self.theMap[theLabel] = self.theLength + self.theLength += 1 + return True + + def lookupEntry(self, theLabel): + if theLabel is None: + return None + theLabel = theLabel.strip() + if theLabel in self.theMap.keys(): + return self.theMap[theLabel] + return None + + def checkEntry(self, theStatus): + if isinstance(theStatus, str): + theStatus = theStatus.strip() + if self.lookupEntry(theStatus) is not None: + return theStatus + theStatus = checkInt(theStatus, 0, False) + if theStatus >= 0 and theStatus < self.theLength: + return self.theLabels[theStatus] + + def setNewEntries(self, newList): + + replaceMap = {} + + if newList is not None: + + self.theLabels = [] + self.theColours = [] + self.theCounts = [] + self.theMap = {} + self.theLength = 0 + self.theIndex = 0 + + for nName, nR, nG, nB, oName in newList: + self.addEntry(nName, (nR, nG, nB)) + if nName != oName and oName is not None: + replaceMap[oName] = nName + + return replaceMap + + def resetCounts(self): + self.theCounts = [0]*self.theLength + return + + def countEntry(self, theLabel): + theIndex = self.lookupEntry(theLabel) + if theIndex is not None: + self.theCounts[theIndex] += 1 + return + + def packEntries(self, xParent): + for n in range(self.theLength): + xSub = etree.SubElement(xParent,"entry",attrib={ + "blue" : str(self.theColours[n][2]), + "green" : str(self.theColours[n][1]), + "red" : str(self.theColours[n][0]), + }) + xSub.text = self.theLabels[n] + return True + + def unpackEntries(self, xParent): + + theLabels = [] + theColours = [] + + for xChild in xParent: + theLabels.append(xChild.text) + if "red" in xChild.attrib: + cR = checkInt(xChild.attrib["red"],0,False) + else: + cR = 0 + if "green" in xChild.attrib: + cG = checkInt(xChild.attrib["green"],0,False) + else: + cG = 0 + if "blue" in xChild.attrib: + cB = checkInt(xChild.attrib["blue"],0,False) + else: + cB = 0 + theColours.append((cR,cG,cB)) + + if len(theLabels) > 0: + self.theLabels = [] + self.theColours = [] + self.theCounts = [] + self.theMap = {} + self.theLength = 0 + self.theIndex = 0 + + for n in range(len(theLabels)): + self.addEntry(theLabels[n], theColours[n]) + + return True + + ## + # Iterator Bits + ## + + def __getitem__(self, n): + if n >= 0 and n < self.theLength: + return self.theLabels[n], self.theColours[n], self.theCounts[n] + return None, None, None + + def __iter__(self): + self.theIndex = 0 + return self + + def __next__(self): + if self.theIndex < self.theLength: + theLabel, theColour, theCount = self.__getitem__(self.theIndex) + self.theIndex += 1 + return theLabel, theColour, theCount + else: + raise StopIteration + +# END Class NWStatus diff --git a/nw/project/status.py b/nw/project/status.py deleted file mode 100644 index c7771f3d..00000000 --- a/nw/project/status.py +++ /dev/null @@ -1,170 +0,0 @@ -# -*- coding: utf-8 -*- -"""novelWriter Item Status - - novelWriter – Item Status -=========================== - Class holding the project's item statuses - - File History: - Created: 2019-05-19 [0.1.3] - - This file is a part of novelWriter - Copyright 2020, Veronica Berglyd Olsen - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" - -import logging -import nw - -from lxml import etree - -from nw.common import checkInt - -logger = logging.getLogger(__name__) - -class NWStatus(): - - def __init__(self): - self.theLabels = [] - self.theColours = [] - self.theCounts = [] - self.theMap = {} - self.theLength = 0 - self.theIndex = 0 - return - - def addEntry(self, theLabel, theColours): - theLabel = theLabel.strip() - if self.lookupEntry(theLabel) is None: - self.theLabels.append(theLabel) - self.theColours.append(theColours) - self.theCounts.append(0) - self.theMap[theLabel] = self.theLength - self.theLength += 1 - return True - - def lookupEntry(self, theLabel): - if theLabel is None: - return None - theLabel = theLabel.strip() - if theLabel in self.theMap.keys(): - return self.theMap[theLabel] - return None - - def checkEntry(self, theStatus): - if isinstance(theStatus, str): - theStatus = theStatus.strip() - if self.lookupEntry(theStatus) is not None: - return theStatus - theStatus = checkInt(theStatus, 0, False) - if theStatus >= 0 and theStatus < self.theLength: - return self.theLabels[theStatus] - - def setNewEntries(self, newList): - - replaceMap = {} - - if newList is not None: - - self.theLabels = [] - self.theColours = [] - self.theCounts = [] - self.theMap = {} - self.theLength = 0 - self.theIndex = 0 - - for nName, nR, nG, nB, oName in newList: - self.addEntry(nName, (nR, nG, nB)) - if nName != oName and oName is not None: - replaceMap[oName] = nName - - return replaceMap - - def resetCounts(self): - self.theCounts = [0]*self.theLength - return - - def countEntry(self, theLabel): - theIndex = self.lookupEntry(theLabel) - if theIndex is not None: - self.theCounts[theIndex] += 1 - return - - def packEntries(self, xParent): - for n in range(self.theLength): - xSub = etree.SubElement(xParent,"entry",attrib={ - "blue" : str(self.theColours[n][2]), - "green" : str(self.theColours[n][1]), - "red" : str(self.theColours[n][0]), - }) - xSub.text = self.theLabels[n] - return True - - def unpackEntries(self, xParent): - - theLabels = [] - theColours = [] - - for xChild in xParent: - theLabels.append(xChild.text) - if "red" in xChild.attrib: - cR = checkInt(xChild.attrib["red"],0,False) - else: - cR = 0 - if "green" in xChild.attrib: - cG = checkInt(xChild.attrib["green"],0,False) - else: - cG = 0 - if "blue" in xChild.attrib: - cB = checkInt(xChild.attrib["blue"],0,False) - else: - cB = 0 - theColours.append((cR,cG,cB)) - - if len(theLabels) > 0: - self.theLabels = [] - self.theColours = [] - self.theCounts = [] - self.theMap = {} - self.theLength = 0 - self.theIndex = 0 - - for n in range(len(theLabels)): - self.addEntry(theLabels[n], theColours[n]) - - return True - - ## - # Iterator Bits - ## - - def __getitem__(self, n): - if n >= 0 and n < self.theLength: - return self.theLabels[n], self.theColours[n], self.theCounts[n] - return None, None, None - - def __iter__(self): - self.theIndex = 0 - return self - - def __next__(self): - if self.theIndex < self.theLength: - theLabel, theColour, theCount = self.__getitem__(self.theIndex) - self.theIndex += 1 - return theLabel, theColour, theCount - else: - raise StopIteration - -# END Class NWStatus diff --git a/tests/test_item.py b/tests/test_item.py index 101eda79..b58f1b7e 100644 --- a/tests/test_item.py +++ b/tests/test_item.py @@ -9,8 +9,7 @@ from lxml import etree from nwdummy import DummyMain from nw.config import Config -from nw.project.project import NWProject -from nw.project.item import NWItem +from nw.project.project import NWProject, NWItem from nw.constants import nwItemClass, nwItemType, nwItemLayout theConf = Config()