Merge pull request #196 from vkbo/project_structure

Project Class Restructure
Merging into `dev` for further testing and code restructuring before we merge to master.
This commit is contained in:
Veronica K. Berglyd Olsen
2020-05-08 10:22:20 +02:00
committed by GitHub
29 changed files with 1017 additions and 670 deletions
+2 -2
View File
@@ -164,12 +164,12 @@ class TextFile():
* Items that appear in the TRASH folder * Items that appear in the TRASH folder
""" """
theItem = self.theProject.getItem(tHandle) theItem = self.theProject.projTree[tHandle]
isNone = theItem.itemType != nwItemType.FILE isNone = theItem.itemType != nwItemType.FILE
isNone |= theItem.itemLayout == nwItemLayout.NO_LAYOUT isNone |= theItem.itemLayout == nwItemLayout.NO_LAYOUT
isNone |= theItem.itemClass == nwItemClass.NO_CLASS isNone |= theItem.itemClass == nwItemClass.NO_CLASS
isNone |= theItem.itemClass == nwItemClass.TRASH isNone |= theItem.itemClass == nwItemClass.TRASH
isNone |= theItem.parHandle == self.theProject.trashRoot isNone |= theItem.parHandle == self.theProject.projTree.trashRoot()
isNote = theItem.itemLayout == nwItemLayout.NOTE isNote = theItem.itemLayout == nwItemLayout.NOTE
isNovel = not isNone and not isNote isNovel = not isNone and not isNote
+1 -1
View File
@@ -142,7 +142,7 @@ class Tokenizer():
def setText(self, theHandle, theText=None): def setText(self, theHandle, theText=None):
self.theHandle = theHandle self.theHandle = theHandle
self.theItem = self.theProject.getItem(theHandle) self.theItem = self.theProject.projTree[theHandle]
if theText is not None: if theText is not None:
# If the text is set, just use that # If the text is set, just use that
+3 -3
View File
@@ -115,7 +115,7 @@ class GuiDocMerge(QDialog):
), nwAlert.ERROR) ), nwAlert.ERROR)
return return
srcItem = self.theProject.getItem(self.sourceItem) srcItem = self.theProject.projTree[self.sourceItem]
nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.parHandle) nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.parHandle)
self.theParent.treeView.revealTreeItem(nHandle) self.theParent.treeView.revealTreeItem(nHandle)
theDoc.openDocument(nHandle, False) theDoc.openDocument(nHandle, False)
@@ -149,7 +149,7 @@ class GuiDocMerge(QDialog):
if tHandle is None: if tHandle is None:
return return
nwItem = self.theProject.getItem(tHandle) nwItem = self.theProject.projTree[tHandle]
if nwItem is None: if nwItem is None:
return return
if nwItem.itemType is not nwItemType.FOLDER: if nwItem.itemType is not nwItemType.FOLDER:
@@ -160,7 +160,7 @@ class GuiDocMerge(QDialog):
for sHandle in self.theParent.treeView.getTreeFromHandle(tHandle): for sHandle in self.theParent.treeView.getTreeFromHandle(tHandle):
newItem = QListWidgetItem() newItem = QListWidgetItem()
nwItem = self.theProject.getItem(sHandle) nwItem = self.theProject.projTree[sHandle]
if nwItem.itemType is not nwItemType.FILE: if nwItem.itemType is not nwItemType.FILE:
continue continue
newItem.setText(nwItem.itemName) newItem.setText(nwItem.itemName)
+3 -3
View File
@@ -120,7 +120,7 @@ class GuiDocSplit(QDialog):
), nwAlert.ERROR) ), nwAlert.ERROR)
return return
srcItem = self.theProject.getItem(self.sourceItem) srcItem = self.theProject.projTree[self.sourceItem]
if srcItem is None: if srcItem is None:
self.theParent.makeAlert(( self.theParent.makeAlert((
"Could not parse source document." "Could not parse source document."
@@ -172,7 +172,7 @@ class GuiDocSplit(QDialog):
wTitle = wTitle.strip() wTitle = wTitle.strip()
nHandle = self.theProject.newFile(wTitle, srcItem.itemClass, fHandle) nHandle = self.theProject.newFile(wTitle, srcItem.itemClass, fHandle)
newItem = self.theProject.getItem(nHandle) newItem = self.theProject.projTree[nHandle]
newItem.setLayout(itemLayout) newItem.setLayout(itemLayout)
logger.verbose( logger.verbose(
"Creating new document %s with text from line %d to %d" % (nHandle, iStart, iEnd-1) "Creating new document %s with text from line %d to %d" % (nHandle, iStart, iEnd-1)
@@ -213,7 +213,7 @@ class GuiDocSplit(QDialog):
if self.sourceItem is None: if self.sourceItem is None:
return return
nwItem = self.theProject.getItem(self.sourceItem) nwItem = self.theProject.projTree[self.sourceItem]
if nwItem is None: if nwItem is None:
return return
if nwItem.itemType is not nwItemType.FILE: if nwItem.itemType is not nwItemType.FILE:
+3 -5
View File
@@ -134,7 +134,7 @@ class GuiExport(QDialog):
self.exportStatus.setText("Export failed ...") self.exportStatus.setText("Export failed ...")
return False return False
nItems = len(self.theProject.treeOrder) nItems = len(self.theProject.projTree)
if eFormat == GuiExportMain.FMT_PDOC: if eFormat == GuiExportMain.FMT_PDOC:
nItems += int(0.2*nItems) nItems += int(0.2*nItems)
self.exportProgress.setMinimum(0) self.exportProgress.setMinimum(0)
@@ -182,16 +182,14 @@ class GuiExport(QDialog):
time.sleep(0.5) time.sleep(0.5)
nDone = 0 nDone = 0
for tHandle in self.theProject.treeOrder: for tItem in self.theProject.projTree:
self.exportProgress.setValue(nDone) self.exportProgress.setValue(nDone)
tItem = self.theProject.getItem(tHandle)
self.exportStatus.setText("Exporting: %s" % tItem.itemName) self.exportStatus.setText("Exporting: %s" % tItem.itemName)
logger.verbose("Exporting: %s" % tItem.itemName) logger.verbose("Exporting: %s" % tItem.itemName)
if tItem is not None and tItem.itemType == nwItemType.FILE: if tItem is not None and tItem.itemType == nwItemType.FILE:
outFile.addText(tHandle) outFile.addText(tItem.itemHandle)
nDone += 1 nDone += 1
+1 -1
View File
@@ -48,7 +48,7 @@ class GuiItemEditor(QDialog):
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theProject = theProject self.theProject = theProject
self.theParent = theParent self.theParent = theParent
self.theItem = self.theProject.getItem(tHandle) self.theItem = self.theProject.projTree[tHandle]
self.outerBox = QHBoxLayout() self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout() self.innerBox = QVBoxLayout()
+1 -1
View File
@@ -83,7 +83,7 @@ class GuiDocDetails(QFrame):
def buildViewBox(self, tHandle): def buildViewBox(self, tHandle):
nwItem = self.theProject.getItem(tHandle) nwItem = self.theProject.projTree[tHandle]
if nwItem is None: if nwItem is None:
colTwo = [""]*4 colTwo = [""]*4
+3 -3
View File
@@ -87,15 +87,15 @@ class GuiDocTitleBar(QLabel):
if self.mainConf.showFullPath: if self.mainConf.showFullPath:
tTitle = [] tTitle = []
tTree = self.theProject.getItemPath(tHandle) tTree = self.theProject.projTree.getItemPath(tHandle)
for aHandle in reversed(tTree): for aHandle in reversed(tTree):
nwItem = self.theProject.getItem(aHandle) nwItem = self.theProject.projTree[aHandle]
if nwItem is not None: if nwItem is not None:
tTitle.append(nwItem.itemName) tTitle.append(nwItem.itemName)
sSep = " %s " % nwUnicode.U_RSAQUO sSep = " %s " % nwUnicode.U_RSAQUO
self.setText(sSep.join(tTitle)) self.setText(sSep.join(tTitle))
else: else:
nwItem = self.theProject.getItem(tHandle) nwItem = self.theProject.projTree[tHandle]
if nwItem is None: if nwItem is None:
return False return False
+29 -26
View File
@@ -34,7 +34,7 @@ from PyQt5.QtWidgets import (
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QApplication, QMessageBox QTreeWidget, QTreeWidgetItem, QAbstractItemView, QApplication, QMessageBox
) )
from nw.project import NWItem, NWDoc from nw.project import NWDoc
from nw.constants import ( from nw.constants import (
nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert nwLabels, nwItemType, nwItemClass, nwItemLayout, nwAlert
) )
@@ -118,7 +118,7 @@ class GuiDocTree(QTreeWidget):
return False return False
if itemClass is None and pHandle is not None: if itemClass is None and pHandle is not None:
pItem = self.theProject.getItem(pHandle) pItem = self.theProject.projTree[pHandle]
if pItem is not None: if pItem is not None:
itemClass = pItem.itemClass itemClass = pItem.itemClass
@@ -150,7 +150,7 @@ class GuiDocTree(QTreeWidget):
# If no parent has been selected, make the new file under # If no parent has been selected, make the new file under
# the root NOVEL item. # the root NOVEL item.
if pHandle is None: if pHandle is None:
pHandle = self.theProject.findRootItem(nwItemClass.NOVEL) pHandle = self.theProject.projTree.findRoot(nwItemClass.NOVEL)
# If still nothing, give up # If still nothing, give up
if pHandle is None: if pHandle is None:
@@ -159,7 +159,7 @@ class GuiDocTree(QTreeWidget):
# Now check if the selected item is a file, in which case # Now check if the selected item is a file, in which case
# the new file will be a sibling # the new file will be a sibling
pItem = self.theProject.getItem(pHandle) pItem = self.theProject.projTree[pHandle]
if pItem.itemType == nwItemType.FILE: if pItem.itemType == nwItemType.FILE:
pHandle = pItem.parHandle pHandle = pItem.parHandle
@@ -170,7 +170,7 @@ class GuiDocTree(QTreeWidget):
) )
return False return False
if pHandle == self.theProject.trashRoot: if pHandle == self.theProject.projTree.trashRoot():
self.makeAlert( self.makeAlert(
"Cannot add new files or folders to the trash folder.", nwAlert.ERROR "Cannot add new files or folders to the trash folder.", nwAlert.ERROR
) )
@@ -194,7 +194,7 @@ class GuiDocTree(QTreeWidget):
def revealTreeItem(self, tHandle): def revealTreeItem(self, tHandle):
"""Reveal a newly added project item in the project tree. """Reveal a newly added project item in the project tree.
""" """
nwItem = self.theProject.getItem(tHandle) nwItem = self.theProject.projTree[tHandle]
trItem = self._addTreeItem(nwItem) trItem = self._addTreeItem(nwItem)
pHandle = nwItem.parHandle pHandle = nwItem.parHandle
if pHandle is not None and pHandle in self.theMap.keys(): if pHandle is not None and pHandle in self.theMap.keys():
@@ -267,14 +267,16 @@ class GuiDocTree(QTreeWidget):
deleteItem function for each document in the Trash folder. deleteItem function for each document in the Trash folder.
""" """
trashHandle = self.theProject.projTree.trashRoot()
logger.debug("Emptying Trash folder") logger.debug("Emptying Trash folder")
if self.theProject.trashRoot is None: if trashHandle is None:
self.makeAlert("There is no Trash folder.", nwAlert.INFO) self.makeAlert("There is no Trash folder.", nwAlert.INFO)
return False return False
theTrash = self.getTreeFromHandle(self.theProject.trashRoot) theTrash = self.getTreeFromHandle(trashHandle)
if self.theProject.trashRoot in theTrash: if trashHandle in theTrash:
theTrash.remove(self.theProject.trashRoot) theTrash.remove(trashHandle)
nTrash = len(theTrash) nTrash = len(theTrash)
if nTrash == 0: if nTrash == 0:
@@ -291,8 +293,8 @@ class GuiDocTree(QTreeWidget):
return False return False
logger.verbose("Deleting %d files from Trash" % nTrash) logger.verbose("Deleting %d files from Trash" % nTrash)
for tHandle in self.getTreeFromHandle(self.theProject.trashRoot): for tHandle in self.getTreeFromHandle(trashHandle):
if tHandle == self.theProject.trashRoot: if tHandle == trashHandle:
continue continue
self.deleteItem(tHandle, True) self.deleteItem(tHandle, True)
@@ -313,7 +315,7 @@ class GuiDocTree(QTreeWidget):
return False return False
trItemS = self._getTreeItem(tHandle) trItemS = self._getTreeItem(tHandle)
nwItemS = self.theProject.getItem(tHandle) nwItemS = self.theProject.projTree[tHandle]
if nwItemS is None: if nwItemS is None:
return False return False
@@ -327,7 +329,7 @@ class GuiDocTree(QTreeWidget):
return False return False
pHandle = nwItemS.parHandle pHandle = nwItemS.parHandle
if pHandle is not None and pHandle == self.theProject.trashRoot: if pHandle is not None and pHandle == self.theProject.projTree.trashRoot():
# If the file is in the trash folder already, as the # If the file is in the trash folder already, as the
# user if they want to permanently delete the file. # user if they want to permanently delete the file.
@@ -353,7 +355,7 @@ class GuiDocTree(QTreeWidget):
theDoc = NWDoc(self.theProject, self.theParent) theDoc = NWDoc(self.theProject, self.theParent)
theDoc.deleteDocument(tHandle) theDoc.deleteDocument(tHandle)
self.theProject.deleteItem(tHandle) del self.theProject.projTree[tHandle]
self.theParent.theIndex.deleteHandle(tHandle) self.theParent.theIndex.deleteHandle(tHandle)
else: else:
@@ -366,7 +368,7 @@ class GuiDocTree(QTreeWidget):
tIndex = trItemP.indexOfChild(trItemS) tIndex = trItemP.indexOfChild(trItemS)
trItemC = trItemP.takeChild(tIndex) trItemC = trItemP.takeChild(tIndex)
trItemT.addChild(trItemC) trItemT.addChild(trItemC)
nwItemS.setParent(self.theProject.trashRoot) nwItemS.setParent(self.theProject.projTree.trashRoot())
self.theProject.setProjectChanged(True) self.theProject.setProjectChanged(True)
self.theParent.theIndex.deleteHandle(tHandle) self.theParent.theIndex.deleteHandle(tHandle)
@@ -380,7 +382,7 @@ class GuiDocTree(QTreeWidget):
tIndex = trItemP.indexOfChild(trItemS) tIndex = trItemP.indexOfChild(trItemS)
if trItemS.childCount() == 0: if trItemS.childCount() == 0:
trItemP.takeChild(tIndex) trItemP.takeChild(tIndex)
self.theProject.deleteItem(tHandle) del self.theProject.projTree[tHandle]
else: else:
self.makeAlert(["Cannot delete folder.","It is not empty."], nwAlert.ERROR) self.makeAlert(["Cannot delete folder.","It is not empty."], nwAlert.ERROR)
return False return False
@@ -401,7 +403,7 @@ class GuiDocTree(QTreeWidget):
def setTreeItemValues(self, tHandle): def setTreeItemValues(self, tHandle):
trItem = self._getTreeItem(tHandle) trItem = self._getTreeItem(tHandle)
nwItem = self.theProject.getItem(tHandle) nwItem = self.theProject.projTree[tHandle]
tName = nwItem.itemName tName = nwItem.itemName
tClass = nwItem.itemClass tClass = nwItem.itemClass
tHandle = nwItem.itemHandle tHandle = nwItem.itemHandle
@@ -552,14 +554,15 @@ class GuiDocTree(QTreeWidget):
"""Adds the trash root folder if it doesn't already exist in the """Adds the trash root folder if it doesn't already exist in the
project tree. project tree.
""" """
if self.theProject.trashRoot is None: trashHandle = self.theProject.projTree.trashRoot()
if trashHandle is None:
self.theProject.addTrash() self.theProject.addTrash()
trItem = self._addTreeItem( trItem = self._addTreeItem(
self.theProject.getItem(self.theProject.trashRoot) self.theProject.projTree[trashHandle]
) )
trItem.setExpanded(True) trItem.setExpanded(True)
else: else:
trItem = self._getTreeItem(self.theProject.trashRoot) trItem = self._getTreeItem(trashHandle)
return trItem return trItem
def _addOrphanedRoot(self): def _addOrphanedRoot(self):
@@ -589,7 +592,7 @@ class GuiDocTree(QTreeWidget):
""" """
trItemS = self._getTreeItem(tHandle) trItemS = self._getTreeItem(tHandle)
nwItemS = self.theProject.getItem(tHandle) nwItemS = self.theProject.projTree[tHandle]
trItemP = trItemS.parent() trItemP = trItemS.parent()
if trItemP is None: if trItemP is None:
logger.error("Failed to find new parent item of %s" % tHandle) logger.error("Failed to find new parent item of %s" % tHandle)
@@ -609,8 +612,8 @@ class GuiDocTree(QTreeWidget):
def _moveOrphanedItem(self, tHandle, dHandle): def _moveOrphanedItem(self, tHandle, dHandle):
trItemS = self._getTreeItem(tHandle) trItemS = self._getTreeItem(tHandle)
nwItemS = self.theProject.getItem(tHandle) nwItemS = self.theProject.projTree[tHandle]
nwItemD = self.theProject.getItem(dHandle) nwItemD = self.theProject.projTree[dHandle]
trItemP = trItemS.parent() trItemP = trItemS.parent()
nwItemS.setClass(nwItemD.itemClass) nwItemS.setClass(nwItemD.itemClass)
if trItemP is None: if trItemP is None:
@@ -652,8 +655,8 @@ class GuiDocTree(QTreeWidget):
dItem = self.itemFromIndex(dIndex) dItem = self.itemFromIndex(dIndex)
dHandle = dItem.text(self.C_HANDLE) dHandle = dItem.text(self.C_HANDLE)
snItem = self.theProject.getItem(sHandle) snItem = self.theProject.projTree[sHandle]
dnItem = self.theProject.getItem(dHandle) dnItem = self.theProject.projTree[dHandle]
if dnItem is None: if dnItem is None:
self.makeAlert("The item cannot be moved to that location.", nwAlert.ERROR) self.makeAlert("The item cannot be moved to that location.", nwAlert.ERROR)
return return
+1 -1
View File
@@ -123,7 +123,7 @@ class GuiDocViewer(QTextBrowser):
"""Load text into the viewer from an item handle. """Load text into the viewer from an item handle.
""" """
tItem = self.theProject.getItem(tHandle) tItem = self.theProject.projTree[tHandle]
if tItem is None: if tItem is None:
logger.warning("Item not found") logger.warning("Item not found")
return False return False
+1 -1
View File
@@ -405,7 +405,7 @@ class GuiProjectOutline(QTreeWidget):
"""Populate a tree item with all the column values. """Populate a tree item with all the column values.
""" """
nwItem = self.theProject.getItem(tHandle) nwItem = self.theProject.projTree[tHandle]
novIdx = self.theIndex.novelIndex[tHandle][sTitle] novIdx = self.theIndex.novelIndex[tHandle][sTitle]
newItem = QTreeWidgetItem() newItem = QTreeWidgetItem()
+1 -1
View File
@@ -103,7 +103,7 @@ class GuiDocViewDetails(QWidget):
theRefs = self.theParent.theIndex.getBackReferenceList(tHandle) theRefs = self.theParent.theIndex.getBackReferenceList(tHandle)
theList = [] theList = []
for tHandle in theRefs: for tHandle in theRefs:
tItem = self.theProject.getItem(tHandle) tItem = self.theProject.projTree[tHandle]
if tItem is not None: if tItem is not None:
theList.append("<a href='#tag=%s'>%s</a>" % (tHandle,tItem.itemName)) theList.append("<a href='#tag=%s'>%s</a>" % (tHandle,tItem.itemName))
+1 -1
View File
@@ -68,7 +68,7 @@ class GuiMainMenu(QMenuBar):
if itemClass == nwItemClass.NO_CLASS: continue if itemClass == nwItemClass.NO_CLASS: continue
if itemClass == nwItemClass.TRASH: continue if itemClass == nwItemClass.TRASH: continue
self.rootItems[itemClass].setEnabled( self.rootItems[itemClass].setEnabled(
self.theProject.checkRootUnique(itemClass) self.theProject.projTree.checkRootUnique(itemClass)
) )
return return
+1 -1
View File
@@ -228,7 +228,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
return return
if theText.startswith("@"): # Keywords and commands if theText.startswith("@"): # Keywords and commands
tItem = self.theParent.theProject.getItem(self.theHandle) tItem = self.theParent.theProject.projTree[self.theHandle]
isValid, theBits, thePos = self.theIndex.scanThis(theText) isValid, theBits, thePos = self.theIndex.scanThis(theText)
isGood = self.theIndex.checkThese(theBits, tItem) isGood = self.theIndex.checkThese(theBits, tItem)
if isValid: if isValid:
+14 -14
View File
@@ -45,7 +45,7 @@ from nw.gui import (
GuiConfigEditor, GuiProjectEditor, GuiItemEditor, GuiProjectOutline, GuiConfigEditor, GuiProjectEditor, GuiItemEditor, GuiProjectOutline,
GuiSessionLogView, GuiDocMerge, GuiDocSplit, GuiProjectLoad GuiSessionLogView, GuiDocMerge, GuiDocSplit, GuiProjectLoad
) )
from nw.project import NWProject, NWDoc, NWItem, NWIndex, NWBackup from nw.project import NWProject, NWDoc, NWIndex, NWBackup
from nw.tools import countWords from nw.tools import countWords
from nw.constants import nwFiles, nwItemType, nwAlert from nw.constants import nwFiles, nwItemType, nwAlert
@@ -617,7 +617,7 @@ class GuiMain(QMainWindow):
return False return False
logger.verbose("Opening item %s" % tHandle) logger.verbose("Opening item %s" % tHandle)
nwItem = self.theProject.getItem(tHandle) nwItem = self.theProject.projTree[tHandle]
if nwItem.itemType == nwItemType.FILE: if nwItem.itemType == nwItemType.FILE:
logger.verbose("Requested item %s is a file" % tHandle) logger.verbose("Requested item %s is a file" % tHandle)
self.openDocument(tHandle) self.openDocument(tHandle)
@@ -656,7 +656,7 @@ class GuiMain(QMainWindow):
self.treeView.saveTreeOrder() self.treeView.saveTreeOrder()
self.theIndex.clearIndex() self.theIndex.clearIndex()
nItems = len(self.theProject.treeOrder) nItems = len(self.theProject.projTree)
dlgProg = QProgressDialog("Scanning files ...", "Cancel", 0, nItems, self) dlgProg = QProgressDialog("Scanning files ...", "Cancel", 0, nItems, self)
dlgProg.setWindowModality(Qt.WindowModal) dlgProg.setWindowModality(Qt.WindowModal)
@@ -668,27 +668,27 @@ class GuiMain(QMainWindow):
time.sleep(0.5) time.sleep(0.5)
nDone = 0 nDone = 0
for tHandle in self.theProject.treeOrder: for tItem in self.theProject.projTree:
tItem = self.theProject.getItem(tHandle)
dlgProg.setValue(nDone) dlgProg.setValue(nDone)
dlgProg.setLabelText("Scanning: %s" % tItem.itemName)
logger.verbose("Scanning: %s" % tItem.itemName)
if tItem is not None and tItem.itemType == nwItemType.FILE: if tItem is not None and tItem.itemType == nwItemType.FILE:
dlgProg.setLabelText("Scanning: %s" % tItem.itemName)
logger.verbose("Scanning: %s" % tItem.itemName)
theDoc = NWDoc(self.theProject, self) theDoc = NWDoc(self.theProject, self)
theText = theDoc.openDocument(tHandle, False) theText = theDoc.openDocument(tItem.itemHandle, False)
# Build tag index # Build tag index
self.theIndex.scanText(tHandle, theText) self.theIndex.scanText(tItem.itemHandle, theText)
# Get Word Counts # Get Word Counts
cC, wC, pC = self.theIndex.getCounts(tHandle) cC, wC, pC = self.theIndex.getCounts(tItem.itemHandle)
tItem.setCharCount(cC) tItem.setCharCount(cC)
tItem.setWordCount(wC) tItem.setWordCount(wC)
tItem.setParaCount(pC) tItem.setParaCount(pC)
self.treeView.propagateCount(tHandle, wC) self.treeView.propagateCount(tItem.itemHandle, wC)
self.treeView.projectWordCount() self.treeView.projectWordCount()
nDone += 1 nDone += 1
@@ -1020,7 +1020,7 @@ class GuiMain(QMainWindow):
def _treeDoubleClick(self, tItem, colNo): def _treeDoubleClick(self, tItem, colNo):
tHandle = tItem.text(3) tHandle = tItem.text(3)
logger.verbose("User double clicked tree item with handle %s" % tHandle) logger.verbose("User double clicked tree item with handle %s" % tHandle)
nwItem = self.theProject.getItem(tHandle) nwItem = self.theProject.projTree[tHandle]
if nwItem.itemType == nwItemType.FILE: if nwItem.itemType == nwItemType.FILE:
logger.verbose("Requested item %s is a file" % tHandle) logger.verbose("Requested item %s is a file" % tHandle)
self.openDocument(tHandle) self.openDocument(tHandle)
@@ -1031,7 +1031,7 @@ class GuiMain(QMainWindow):
def _treeKeyPressReturn(self): def _treeKeyPressReturn(self):
tHandle = self.treeView.getSelectedHandle() tHandle = self.treeView.getSelectedHandle()
logger.verbose("User pressed return on tree item with handle %s" % tHandle) logger.verbose("User pressed return on tree item with handle %s" % tHandle)
nwItem = self.theProject.getItem(tHandle) nwItem = self.theProject.projTree[tHandle]
if nwItem.itemType == nwItemType.FILE: if nwItem.itemType == nwItemType.FILE:
logger.verbose("Requested item %s is a file" % tHandle) logger.verbose("Requested item %s is a file" % tHandle)
self.openDocument(tHandle) self.openDocument(tHandle)
-4
View File
@@ -3,15 +3,11 @@
from nw.project.backup import NWBackup from nw.project.backup import NWBackup
from nw.project.document import NWDoc from nw.project.document import NWDoc
from nw.project.index import NWIndex from nw.project.index import NWIndex
from nw.project.item import NWItem
from nw.project.project import NWProject from nw.project.project import NWProject
from nw.project.status import NWStatus
__all__ = [ __all__ = [
"NWBackup", "NWBackup",
"NWDoc", "NWDoc",
"NWIndex", "NWIndex",
"NWItem",
"NWProject", "NWProject",
"NWStatus",
] ]
+2 -2
View File
@@ -62,7 +62,7 @@ class NWDoc():
def openDocument(self, tHandle, showStatus=True): def openDocument(self, tHandle, showStatus=True):
self.docHandle = tHandle self.docHandle = tHandle
self.theItem = self.theProject.getItem(tHandle) self.theItem = self.theProject.projTree[tHandle]
if self.theItem is None: if self.theItem is None:
self.clearDocument() self.clearDocument()
@@ -71,7 +71,7 @@ class NWDoc():
# By default, the document is editable. # By default, the document is editable.
# Except for files in the trash folder. # Except for files in the trash folder.
self.docEditable = True self.docEditable = True
if self.theItem.parHandle == self.theProject.trashRoot: if self.theItem.parHandle == self.theProject.projTree.trashRoot():
self.docEditable = False self.docEditable = False
docDir, docFile = self.assemblePath(self.docHandle, self.FILE_MN) docDir, docFile = self.assemblePath(self.docHandle, self.FILE_MN)
+4 -4
View File
@@ -249,12 +249,12 @@ class NWIndex():
files before we save them, unless we're rebuilding the index. files before we save them, unless we're rebuilding the index.
""" """
theItem = self.theProject.getItem(tHandle) theItem = self.theProject.projTree[tHandle]
if theItem is None: if theItem is None:
return False return False
if theItem.itemType != nwItemType.FILE: if theItem.itemType != nwItemType.FILE:
return False return False
if theItem.parHandle == self.theProject.trashRoot: if theItem.parHandle == self.theProject.projTree.trashRoot():
return False return False
if theItem.itemLayout == nwItemLayout.NO_LAYOUT: if theItem.itemLayout == nwItemLayout.NO_LAYOUT:
return False return False
@@ -539,7 +539,7 @@ class NWIndex():
""" """
theStructure = [] theStructure = []
for tHandle in self.theProject.treeOrder: for tHandle in self.theProject.projTree.handles():
if tHandle not in self.novelIndex: if tHandle not in self.novelIndex:
continue continue
for sTitle in sorted(self.novelIndex[tHandle].keys()): for sTitle in sorted(self.novelIndex[tHandle].keys()):
@@ -605,7 +605,7 @@ class NWIndex():
theRefs = {} theRefs = {}
tItem = self.theProject.getItem(tHandle) tItem = self.theProject.projTree[tHandle]
if tHandle is None: if tHandle is None:
return theRefs return theRefs
-222
View File
@@ -1,222 +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 <https://www.gnu.org/licenses/>.
"""
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):
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 xPack
def _subPack(self, 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
##
# Settings Wrapper
##
def setFromTag(self, tagName, tagValue):
logger.verbose("Setting tag '%s' to value '%s'" % (tagName, str(tagValue)))
if tagName == "name":
self.setName(tagValue)
elif tagName == "order":
self.setOrder(tagValue)
elif tagName == "type":
self.setType(tagValue)
elif tagName == "class":
self.setClass(tagValue)
elif tagName == "layout":
self.setLayout(tagValue)
elif tagName == "status":
self.setStatus(tagValue)
elif tagName == "expanded":
self.setExpanded(tagValue)
elif tagName == "charCount":
self.setCharCount(tagValue)
elif tagName == "wordCount":
self.setWordCount(tagValue)
elif tagName == "paraCount":
self.setParaCount(tagValue)
elif tagName == "cursorPos":
self.setCursorPos(tagValue)
else:
logger.error("Unknown tag '%s'" % tagName)
return
##
# Set Item Values
##
def setName(self, theName):
self.itemName = theName.strip()
return
def setHandle(self, theHandle):
self.itemHandle = theHandle
return
def setParent(self, theParent):
self.parHandle = theParent
return
def setOrder(self, theOrder):
self.itemOrder = theOrder
return
def setType(self, theType):
if isinstance(theType, nwItemType):
self.itemType = theType
return
else:
for itemType in nwItemType:
if theType == itemType.name:
self.itemType = itemType
return
logger.error("Unrecognised item type '%s'" % theType)
self.itemType = nwItemType.NO_TYPE
return
def setClass(self, theClass):
if isinstance(theClass, nwItemClass):
self.itemClass = theClass
return
else:
for itemClass in nwItemClass:
if theClass == itemClass.name:
self.itemClass = itemClass
return
logger.error("Unrecognised item class '%s'" % theClass)
self.itemClass = nwItemClass.NO_CLASS
return
def setLayout(self, theLayout):
if isinstance(theLayout, nwItemLayout):
self.itemLayout = theLayout
return
else:
for itemLayout in nwItemLayout:
if theLayout == itemLayout.name:
self.itemLayout = itemLayout
return
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
return
##
# Set Document Meta Data
##
def setCharCount(self, theCount):
theCount = checkInt(theCount,0)
self.charCount = theCount
return
def setWordCount(self, theCount):
theCount = checkInt(theCount,0)
self.wordCount = theCount
return
def setParaCount(self, theCount):
theCount = checkInt(theCount,0)
self.paraCount = theCount
return
def setCursorPos(self, thePosition):
thePosition = checkInt(thePosition,0)
self.cursorPos = thePosition
return
# END Class NWItem
+699 -174
View File
File diff suppressed because it is too large Load Diff
-170
View File
@@ -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 <https://www.gnu.org/licenses/>.
"""
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
+4 -4
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.1.5" fileVersion="1.0" timeStamp="2019-06-27 20:31:37"> <novelWriterXML appVersion="0.4.5" fileVersion="1.0" saveCount="4" autoCount="0" timeStamp="2020-05-07 22:03:17">
<project> <project>
<name></name> <name></name>
<title></title> <title></title>
@@ -59,7 +59,7 @@
<status>New</status> <status>New</status>
<expanded>True</expanded> <expanded>True</expanded>
</item> </item>
<item handle="2fca346db6561" order="0" parent="44cb730c42048"> <item handle="98010bd9270f9" order="0" parent="44cb730c42048">
<name>New File</name> <name>New File</name>
<type>FILE</type> <type>FILE</type>
<class>CHARACTER</class> <class>CHARACTER</class>
@@ -78,7 +78,7 @@
<status>New</status> <status>New</status>
<expanded>True</expanded> <expanded>True</expanded>
</item> </item>
<item handle="02d20bbd7e394" order="0" parent="71ee45a3c0db9"> <item handle="0e17daca5f3e1" order="0" parent="71ee45a3c0db9">
<name>New File</name> <name>New File</name>
<type>FILE</type> <type>FILE</type>
<class>PLOT</class> <class>PLOT</class>
@@ -97,7 +97,7 @@
<status>New</status> <status>New</status>
<expanded>True</expanded> <expanded>True</expanded>
</item> </item>
<item handle="7688b6ef52555" order="0" parent="811786ad1ae74"> <item handle="1a6562590ef19" order="0" parent="811786ad1ae74">
<name>New File</name> <name>New File</name>
<type>FILE</type> <type>FILE</type>
<class>WORLD</class> <class>WORLD</class>
+5 -5
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.4.5" fileVersion="1.0" timeStamp="2020-02-26 22:05:41"> <novelWriterXML appVersion="0.4.5" fileVersion="1.0" saveCount="4" autoCount="0" timeStamp="2020-05-07 22:52:18">
<project> <project>
<name></name> <name></name>
<title></title> <title></title>
@@ -73,28 +73,28 @@
<paraCount>0</paraCount> <paraCount>0</paraCount>
<cursorPos>0</cursorPos> <cursorPos>0</cursorPos>
</item> </item>
<item handle="8722616204217" order="None" parent="None"> <item handle="98010bd9270f9" order="None" parent="None">
<name>Timeline</name> <name>Timeline</name>
<type>ROOT</type> <type>ROOT</type>
<class>TIMELINE</class> <class>TIMELINE</class>
<status>New</status> <status>New</status>
<expanded>False</expanded> <expanded>False</expanded>
</item> </item>
<item handle="96061e92f58e4" order="None" parent="None"> <item handle="0e17daca5f3e1" order="None" parent="None">
<name>Object</name> <name>Object</name>
<type>ROOT</type> <type>ROOT</type>
<class>OBJECT</class> <class>OBJECT</class>
<status>New</status> <status>New</status>
<expanded>False</expanded> <expanded>False</expanded>
</item> </item>
<item handle="eb624dbe56eb6" order="None" parent="None"> <item handle="1a6562590ef19" order="None" parent="None">
<name>Custom1</name> <name>Custom1</name>
<type>ROOT</type> <type>ROOT</type>
<class>CUSTOM</class> <class>CUSTOM</class>
<status>New</status> <status>New</status>
<expanded>False</expanded> <expanded>False</expanded>
</item> </item>
<item handle="f369cb89fc627" order="None" parent="None"> <item handle="031b4af5197ec" order="None" parent="None">
<name>Custom2</name> <name>Custom2</name>
<type>ROOT</type> <type>ROOT</type>
<class>CUSTOM</class> <class>CUSTOM</class>
+15 -15
View File
@@ -25,15 +25,15 @@ def testMainWindows(qtbot, nwTempGUI, nwRef, nwTemp):
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
# Create new, save, close project # Create new, save, close project
nwGUI.theProject.handleSeed = 42 nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.newProject(nwTempGUI, True) assert nwGUI.newProject(nwTempGUI, True)
assert nwGUI.saveProject() assert nwGUI.saveProject()
assert nwGUI.closeProject() assert nwGUI.closeProject()
assert len(nwGUI.theProject.projTree) == 0 assert len(nwGUI.theProject.projTree) == 0
assert len(nwGUI.theProject.treeOrder) == 0 assert len(nwGUI.theProject.projTree._treeOrder) == 0
assert len(nwGUI.theProject.treeRoots) == 0 assert len(nwGUI.theProject.projTree._treeRoots) == 0
assert nwGUI.theProject.trashRoot is None assert nwGUI.theProject.projTree.trashRoot() is None
assert nwGUI.theProject.projPath is None assert nwGUI.theProject.projPath is None
assert nwGUI.theProject.projMeta is None assert nwGUI.theProject.projMeta is None
assert nwGUI.theProject.projFile == "nwProject.nwx" assert nwGUI.theProject.projFile == "nwProject.nwx"
@@ -55,9 +55,9 @@ def testMainWindows(qtbot, nwTempGUI, nwRef, nwTemp):
# Check that we loaded the data # Check that we loaded the data
assert len(nwGUI.theProject.projTree) == 6 assert len(nwGUI.theProject.projTree) == 6
assert len(nwGUI.theProject.treeOrder) == 6 assert len(nwGUI.theProject.projTree._treeOrder) == 6
assert len(nwGUI.theProject.treeRoots) == 4 assert len(nwGUI.theProject.projTree._treeRoots) == 4
assert nwGUI.theProject.trashRoot is None assert nwGUI.theProject.projTree.trashRoot() is None
assert nwGUI.theProject.projPath == nwTempGUI assert nwGUI.theProject.projPath == nwTempGUI
assert nwGUI.theProject.projMeta == path.join(nwTempGUI,"meta") assert nwGUI.theProject.projMeta == path.join(nwTempGUI,"meta")
assert nwGUI.theProject.projFile == "nwProject.nwx" assert nwGUI.theProject.projFile == "nwProject.nwx"
@@ -237,14 +237,14 @@ def testMainWindows(qtbot, nwTempGUI, nwRef, nwTemp):
# Check the files # Check the files
refFile = path.join(nwTempGUI,"nwProject.nwx") refFile = path.join(nwTempGUI,"nwProject.nwx")
assert cmpFiles(refFile, path.join(nwRef,"gui","1_nwProject.nwx"), [2]) assert cmpFiles(refFile, path.join(nwRef,"gui","1_nwProject.nwx"), [2])
refFile = path.join(nwTempGUI,"data_0","2d20bbd7e394_main.nwd") refFile = path.join(nwTempGUI,"data_0","e17daca5f3e1_main.nwd")
assert cmpFiles(refFile, path.join(nwRef,"gui","1_2d20bbd7e394_main.nwd")) assert cmpFiles(refFile, path.join(nwRef,"gui","1_e17daca5f3e1_main.nwd"))
refFile = path.join(nwTempGUI,"data_2","fca346db6561_main.nwd") refFile = path.join(nwTempGUI,"data_9","8010bd9270f9_main.nwd")
assert cmpFiles(refFile, path.join(nwRef,"gui","1_fca346db6561_main.nwd")) assert cmpFiles(refFile, path.join(nwRef,"gui","1_8010bd9270f9_main.nwd"))
refFile = path.join(nwTempGUI,"data_3","1489056e0916_main.nwd") refFile = path.join(nwTempGUI,"data_3","1489056e0916_main.nwd")
assert cmpFiles(refFile, path.join(nwRef,"gui","1_1489056e0916_main.nwd")) assert cmpFiles(refFile, path.join(nwRef,"gui","1_1489056e0916_main.nwd"))
refFile = path.join(nwTempGUI,"data_7","688b6ef52555_main.nwd") refFile = path.join(nwTempGUI,"data_1","a6562590ef19_main.nwd")
assert cmpFiles(refFile, path.join(nwRef,"gui","1_688b6ef52555_main.nwd")) assert cmpFiles(refFile, path.join(nwRef,"gui","1_a6562590ef19_main.nwd"))
nwGUI.closeMain() nwGUI.closeMain()
# qtbot.stopForInteraction() # qtbot.stopForInteraction()
@@ -258,7 +258,7 @@ def testProjectEditor(qtbot, nwTempGUI, nwRef, nwTemp):
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
# Create new, save, open project # Create new, save, open project
nwGUI.theProject.handleSeed = 42 nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.newProject(nwTempGUI, True) assert nwGUI.newProject(nwTempGUI, True)
nwGUI.mainConf.backupPath = nwTempGUI nwGUI.mainConf.backupPath = nwTempGUI
@@ -345,7 +345,7 @@ def testItemEditor(qtbot, nwTempGUI, nwRef, nwTemp):
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
# Create new, save, open project # Create new, save, open project
nwGUI.theProject.handleSeed = 42 nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.newProject(nwTempGUI, True) assert nwGUI.newProject(nwTempGUI, True)
itemEdit = GuiItemEditor(nwGUI, nwGUI.theProject, "31489056e0916") itemEdit = GuiItemEditor(nwGUI, nwGUI.theProject, "31489056e0916")
+217
View File
@@ -0,0 +1,217 @@
# -*- coding: utf-8 -*-
"""novelWriter NWItem Class Tester
"""
import nw
import pytest
from lxml import etree
from nwdummy import DummyMain
from nw.config import Config
from nw.project.project import NWProject, NWItem
from nw.constants import nwItemClass, nwItemType, nwItemLayout
theConf = Config()
theMain = DummyMain()
theMain.mainConf = theConf
theProject = NWProject(theMain)
theItem = NWItem(theProject)
nwXML = etree.Element("novelWriterXML")
@pytest.mark.project
def testItemSettersSimple():
# Name
theItem.setName("A Name")
assert theItem.itemName == "A Name"
theItem.setName("\t A Name ")
assert theItem.itemName == "A Name"
# Handle
theItem.setHandle(123)
assert theItem.itemHandle is None
theItem.setHandle("0123456789abcdef")
assert theItem.itemHandle is None
theItem.setHandle("0123456789abc")
assert theItem.itemHandle == "0123456789abc"
# Parent
theItem.setParent(None)
assert theItem.parHandle is None
theItem.setParent(123)
assert theItem.parHandle is None
theItem.setParent("0123456789abcdef")
assert theItem.parHandle is None
theItem.setParent("0123456789abc")
assert theItem.parHandle == "0123456789abc"
# Order
theItem.setOrder(None)
assert theItem.itemOrder == 0
theItem.setOrder("1")
assert theItem.itemOrder == 1
theItem.setOrder(1)
assert theItem.itemOrder == 1
# Status
theItem.setStatus("Nonsense")
assert theItem.itemStatus == "New"
theItem.setStatus("New")
assert theItem.itemStatus == "New"
theItem.setStatus("Minor")
assert theItem.itemStatus == "Minor"
theItem.setStatus("Major")
assert theItem.itemStatus == "Major"
theItem.setStatus("Main")
assert theItem.itemStatus == "Main"
# Expanded
theItem.setExpanded(8)
assert not theItem.isExpanded
theItem.setExpanded(None)
assert not theItem.isExpanded
theItem.setExpanded("None")
assert not theItem.isExpanded
theItem.setExpanded("What?")
assert not theItem.isExpanded
theItem.setExpanded("True")
assert theItem.isExpanded
theItem.setExpanded(True)
assert theItem.isExpanded
# CharCount
theItem.setCharCount(None)
assert theItem.charCount == 0
theItem.setCharCount("1")
assert theItem.charCount == 1
theItem.setCharCount(1)
assert theItem.charCount == 1
# WordCount
theItem.setWordCount(None)
assert theItem.wordCount == 0
theItem.setWordCount("1")
assert theItem.wordCount == 1
theItem.setWordCount(1)
assert theItem.wordCount == 1
# ParaCount
theItem.setParaCount(None)
assert theItem.paraCount == 0
theItem.setParaCount("1")
assert theItem.paraCount == 1
theItem.setParaCount(1)
assert theItem.paraCount == 1
# CursorPos
theItem.setCursorPos(None)
assert theItem.cursorPos == 0
theItem.setCursorPos("1")
assert theItem.cursorPos == 1
theItem.setCursorPos(1)
assert theItem.cursorPos == 1
@pytest.mark.project
def testItemClassSetter():
# Class
theItem.setClass(None)
assert theItem.itemClass == nwItemClass.NO_CLASS
theItem.setClass("NONSENSE")
assert theItem.itemClass == nwItemClass.NO_CLASS
theItem.setClass("NO_CLASS")
assert theItem.itemClass == nwItemClass.NO_CLASS
theItem.setClass("NOVEL")
assert theItem.itemClass == nwItemClass.NOVEL
theItem.setClass("PLOT")
assert theItem.itemClass == nwItemClass.PLOT
theItem.setClass("CHARACTER")
assert theItem.itemClass == nwItemClass.CHARACTER
theItem.setClass("WORLD")
assert theItem.itemClass == nwItemClass.WORLD
theItem.setClass("TIMELINE")
assert theItem.itemClass == nwItemClass.TIMELINE
theItem.setClass("OBJECT")
assert theItem.itemClass == nwItemClass.OBJECT
theItem.setClass("ENTITY")
assert theItem.itemClass == nwItemClass.ENTITY
theItem.setClass("CUSTOM")
assert theItem.itemClass == nwItemClass.CUSTOM
theItem.setClass("TRASH")
assert theItem.itemClass == nwItemClass.TRASH
@pytest.mark.project
def testItemTypeSetter():
# Class
theItem.setType(None)
assert theItem.itemType == nwItemType.NO_TYPE
theItem.setType("NONSENSE")
assert theItem.itemType == nwItemType.NO_TYPE
theItem.setType("NO_TYPE")
assert theItem.itemType == nwItemType.NO_TYPE
theItem.setType("ROOT")
assert theItem.itemType == nwItemType.ROOT
theItem.setType("FOLDER")
assert theItem.itemType == nwItemType.FOLDER
theItem.setType("FILE")
assert theItem.itemType == nwItemType.FILE
theItem.setType("TRASH")
assert theItem.itemType == nwItemType.TRASH
@pytest.mark.project
def testItemLayoutSetter():
# Class
theItem.setLayout(None)
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
theItem.setLayout("NONSENSE")
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
theItem.setLayout("NO_LAYOUT")
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
theItem.setLayout("TITLE")
assert theItem.itemLayout == nwItemLayout.TITLE
theItem.setLayout("BOOK")
assert theItem.itemLayout == nwItemLayout.BOOK
theItem.setLayout("PAGE")
assert theItem.itemLayout == nwItemLayout.PAGE
theItem.setLayout("PARTITION")
assert theItem.itemLayout == nwItemLayout.PARTITION
theItem.setLayout("UNNUMBERED")
assert theItem.itemLayout == nwItemLayout.UNNUMBERED
theItem.setLayout("CHAPTER")
assert theItem.itemLayout == nwItemLayout.CHAPTER
theItem.setLayout("SCENE")
assert theItem.itemLayout == nwItemLayout.SCENE
theItem.setLayout("NOTE")
assert theItem.itemLayout == nwItemLayout.NOTE
@pytest.mark.project
def testItemXMLPackUnpack():
# Pack
xContent = etree.SubElement(nwXML, "content")
theItem.packXML(xContent)
assert etree.tostring(xContent, pretty_print=False, encoding="utf-8") == (
b"<content>"
b"<item handle=\"0123456789abc\" order=\"1\" parent=\"0123456789abc\">"
b"<name>A Name</name><type>TRASH</type><class>TRASH</class><status>Main</status><expanded>True</expanded>"
b"</item>"
b"</content>"
)
# Unpack
assert theItem.unpackXML(xContent[0])
assert theItem.itemHandle == "0123456789abc"
assert theItem.parHandle == "0123456789abc"
assert theItem.itemOrder == 1
assert theItem.isExpanded
assert theItem.charCount == 1
assert theItem.wordCount == 1
assert theItem.paraCount == 1
assert theItem.cursorPos == 1
assert theItem.itemClass == nwItemClass.TRASH
assert theItem.itemType == nwItemType.TRASH
assert theItem.itemLayout == nwItemLayout.NOTE
+6 -6
View File
@@ -2,24 +2,24 @@
"""novelWriter Project Class Tester """novelWriter Project Class Tester
""" """
import nw, pytest, types import nw
import pytest
from os import path from os import path
from nwtools import * from nwtools import *
from nwdummy import DummyMain from nwdummy import DummyMain
from nw.config import Config from nw.config import Config
from nw.project.project import NWProject from nw.project.project import NWProject
from nw.project.item import NWItem from nw.project.index import NWIndex
from nw.project.index import NWIndex from nw.constants import nwItemClass
from nw.constants import nwItemClass
theConf = Config() theConf = Config()
theMain = DummyMain() theMain = DummyMain()
theMain.mainConf = theConf theMain.mainConf = theConf
theProject = NWProject(theMain) theProject = NWProject(theMain)
theProject.handleSeed = 42 theProject.projTree.setSeed(42)
@pytest.mark.project @pytest.mark.project
def testProjectNew(nwTempProj,nwRef,nwTemp): def testProjectNew(nwTempProj,nwRef,nwTemp):