diff --git a/novelwriter/core/item.py b/novelwriter/core/item.py
index 73dfdd6b..8b04a0d3 100644
--- a/novelwriter/core/item.py
+++ b/novelwriter/core/item.py
@@ -51,6 +51,7 @@ class NWItem():
self._class = nwItemClass.NO_CLASS
self._layout = nwItemLayout.NO_LAYOUT
self._status = None
+ self._import = None
self._expanded = False
self._exported = True
@@ -109,6 +110,10 @@ class NWItem():
def itemStatus(self):
return self._status
+ @property
+ def itemImport(self):
+ return self._import
+
@property
def isExpanded(self):
return self._expanded
@@ -165,12 +170,13 @@ class NWItem():
nameAttrib = {}
nameAttrib["status"] = str(self._status)
+ nameAttrib["import"] = str(self._import)
if self._type == nwItemType.FILE:
nameAttrib["exported"] = str(self._exported)
xPack = etree.SubElement(xParent, "item", attrib=itemAttrib)
- self._subPack(xPack, "meta", attrib=metaAttrib)
- self._subPack(xPack, "name", text=str(self._name), attrib=nameAttrib)
+ self._subPack(xPack, "meta", attrib=metaAttrib)
+ self._subPack(xPack, "name", text=str(self._name), attrib=nameAttrib)
return
@@ -204,11 +210,12 @@ class NWItem():
elif xValue.tag == "name":
self.setName(xValue.text)
self.setStatus(xValue.attrib.get("status", None))
+ self.setImport(xValue.attrib.get("import", None))
self.setExported(xValue.attrib.get("exported", True))
# Legacy Format (1.3 and earlier)
elif xValue.tag == "status":
- self.setStatus(xValue.text)
+ self.setImportStatus(xValue.text)
elif xValue.tag == "type":
self.setType(xValue.text)
elif xValue.tag == "class":
@@ -275,6 +282,28 @@ class NWItem():
return trConst(nwLabels.ITEM_DESCRIPTION.get(descKey, ""))
+ def getImportStatus(self):
+ """Return the relevant importance or status label and icon for
+ the current item based on its class.
+ """
+ if self._class in nwLists.CLS_NOVEL:
+ stName = self.theProject.statusItems.checkEntry(self._status)
+ stIcon = self.theProject.statusItems.getIcon(stName)
+ else:
+ stName = self.theProject.importItems.checkEntry(self._import)
+ stIcon = self.theProject.importItems.getIcon(stName)
+ return stName, stIcon
+
+ def setImportStatus(self, theLabel):
+ """Update the importance or status value based on class. This is
+ a wrapper setter for setStatus and setImport.
+ """
+ if self._class in nwLists.CLS_NOVEL:
+ self.setStatus(theLabel)
+ else:
+ self.setImport(theLabel)
+ return
+
##
# Set Item Values
##
@@ -372,10 +401,14 @@ class NWItem():
"""Set the item status by looking it up in the valid status
items of the current project.
"""
- if self._class in nwLists.CLS_NOVEL:
- self._status = self.theProject.statusItems.checkEntry(theStatus)
- else:
- self._status = self.theProject.importItems.checkEntry(theStatus)
+ self._status = self.theProject.statusItems.checkEntry(theStatus)
+ return
+
+ def setImport(self, theImport):
+ """Set the item importance by looking it up in the valid import
+ items of the current project.
+ """
+ self._import = self.theProject.importItems.checkEntry(theImport)
return
def setExpanded(self, expState):
diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py
index 913e159a..3e10dcd7 100644
--- a/novelwriter/core/project.py
+++ b/novelwriter/core/project.py
@@ -46,7 +46,7 @@ from novelwriter.common import (
checkString, checkBool, checkInt, isHandle, formatTimeStamp,
makeFileNameSafe, hexToInt
)
-from novelwriter.constants import trConst, nwFiles, nwLabels
+from novelwriter.constants import nwLists, trConst, nwFiles, nwLabels
logger = logging.getLogger(__name__)
@@ -1077,7 +1077,7 @@ class NWProject():
"""
replaceMap = self.statusItems.setNewEntries(newCols)
for nwItem in self.projTree:
- if nwItem.itemClass == nwItemClass.NOVEL:
+ if nwItem.itemClass in nwLists.CLS_NOVEL:
if nwItem.itemStatus in replaceMap:
nwItem.setStatus(replaceMap[nwItem.itemStatus])
self.setProjectChanged(True)
@@ -1089,9 +1089,9 @@ class NWProject():
"""
replaceMap = self.importItems.setNewEntries(newCols)
for nwItem in self.projTree:
- if nwItem.itemClass != nwItemClass.NOVEL:
- if nwItem.itemStatus in replaceMap:
- nwItem.setStatus(replaceMap[nwItem.itemStatus])
+ if nwItem.itemClass not in nwLists.CLS_NOVEL:
+ if nwItem.itemImport in replaceMap:
+ nwItem.setImport(replaceMap[nwItem.itemImport])
self.setProjectChanged(True)
return True
@@ -1212,10 +1212,10 @@ class NWProject():
self.statusItems.resetCounts()
self.importItems.resetCounts()
for nwItem in self.projTree:
- if nwItem.itemClass == nwItemClass.NOVEL:
+ if nwItem.itemClass in nwLists.CLS_NOVEL:
self.statusItems.countEntry(nwItem.itemStatus)
else:
- self.importItems.countEntry(nwItem.itemStatus)
+ self.importItems.countEntry(nwItem.itemImport)
return
def localLookup(self, theWord):
diff --git a/novelwriter/core/status.py b/novelwriter/core/status.py
index 4318344f..2ca8ed53 100644
--- a/novelwriter/core/status.py
+++ b/novelwriter/core/status.py
@@ -24,9 +24,12 @@ along with this program. If not, see .
"""
import logging
+import novelwriter
from lxml import etree
+from PyQt5.QtGui import QIcon, QPixmap, QColor
+
from novelwriter.common import checkInt
logger = logging.getLogger(__name__)
@@ -39,9 +42,11 @@ class NWStatus():
self._theLabels = []
self._theColours = []
self._theCounts = []
+ self._theIcons = []
self._theMap = {}
self._theLength = 0
self._theIndex = 0
+ self._iconSize = novelwriter.CONFIG.pxInt(32)
return
@@ -50,38 +55,35 @@ class NWStatus():
a duplicate.
"""
theLabel = theLabel.strip()
- if self.lookupEntry(theLabel) is None:
+ if self._getIndex(theLabel) is None:
+ theIcon = QPixmap(self._iconSize, self._iconSize)
+ theIcon.fill(QColor(*theColours))
+ self._theIcons.append(QIcon(theIcon))
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):
- """Look up a status entry in the object lists, and return it if
- it exists.
- """
- if theLabel is None:
- return None
- theLabel = theLabel.strip()
- if theLabel in self._theMap.keys():
- return self._theMap[theLabel]
- return None
+ return True
def checkEntry(self, theStatus):
"""Check if a status value is valid, and returns the safe
reference to be used internally.
"""
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]
+ if self._getIndex(theStatus) is not None:
+ return theStatus.strip()
return self._theLabels[0]
+ def getIcon(self, theLabel):
+ """Return the icon for the given status item.
+ """
+ theIndex = self._getIndex(theLabel)
+ if theIndex is not None:
+ return self._theIcons[theIndex]
+ return QIcon()
+
def setNewEntries(self, newList):
"""Update the list of entries after they have been modified by
the GUI tool.
@@ -92,6 +94,7 @@ class NWStatus():
self._theLabels = []
self._theColours = []
self._theCounts = []
+ self._theIcons = []
self._theMap = {}
self._theLength = 0
self._theIndex = 0
@@ -113,7 +116,7 @@ class NWStatus():
"""Increment the counter for a given label. This should be used
together with resetCounts in a loop over project items.
"""
- theIndex = self.lookupEntry(theLabel)
+ theIndex = self._getIndex(theLabel)
if theIndex is not None:
self._theCounts[theIndex] += 1
return
@@ -124,9 +127,9 @@ class NWStatus():
"""
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]),
+ "green": str(self._theColours[n][1]),
+ "blue": str(self._theColours[n][2]),
})
xSub.text = self._theLabels[n]
return True
@@ -145,18 +148,31 @@ class NWStatus():
theColours.append((cR, cG, cB))
if len(theLabels) > 0:
- self._theLabels = []
+ self._theLabels = []
self._theColours = []
- self._theCounts = []
- self._theMap = {}
- self._theLength = 0
- self._theIndex = 0
+ self._theCounts = []
+ self._theIcons = []
+ self._theMap = {}
+ self._theLength = 0
+ self._theIndex = 0
for n in range(len(theLabels)):
self.addEntry(theLabels[n], theColours[n])
return True
+ ##
+ # Internal Functions
+ ##
+
+ def _getIndex(self, theLabel):
+ """Look up a status entry in the object lists, and return it if
+ it exists.
+ """
+ if theLabel is None:
+ return None
+ return self._theMap.get(theLabel.strip(), None)
+
##
# Iterator Bits
##
@@ -165,8 +181,8 @@ class NWStatus():
"""Return an entry by its index.
"""
if n >= 0 and n < self._theLength:
- return self._theLabels[n], self._theColours[n], self._theCounts[n]
- return None, None, None
+ return self._theLabels[n], self._theColours[n], self._theCounts[n], self._theIcons[n]
+ return None, None, None, QIcon()
def __iter__(self):
"""Initialise the iterator.
@@ -178,9 +194,9 @@ class NWStatus():
"""Return the next entry for the iterator.
"""
if self._theIndex < self._theLength:
- theLabel, theColour, theCount = self.__getitem__(self._theIndex)
+ theLabel, theColour, theCount, theIcon = self.__getitem__(self._theIndex)
self._theIndex += 1
- return theLabel, theColour, theCount
+ return theLabel, theColour, theCount, theIcon
else:
raise StopIteration
diff --git a/novelwriter/dialogs/docmerge.py b/novelwriter/dialogs/docmerge.py
index f9ee01af..f7695b9a 100644
--- a/novelwriter/dialogs/docmerge.py
+++ b/novelwriter/dialogs/docmerge.py
@@ -133,6 +133,7 @@ class GuiDocMerge(QDialog):
nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemClass, srcItem.itemParent)
newItem = self.theProject.projTree[nHandle]
newItem.setStatus(srcItem.itemStatus)
+ newItem.setImport(srcItem.itemImport)
outDoc = NWDoc(self.theProject, nHandle)
if not outDoc.writeDocument(theText):
diff --git a/novelwriter/dialogs/docsplit.py b/novelwriter/dialogs/docsplit.py
index 1138ec58..cdf0757a 100644
--- a/novelwriter/dialogs/docsplit.py
+++ b/novelwriter/dialogs/docsplit.py
@@ -203,6 +203,7 @@ class GuiDocSplit(QDialog):
newItem = self.theProject.projTree[nHandle]
newItem.setLayout(itemLayout)
newItem.setStatus(srcItem.itemStatus)
+ newItem.setImport(srcItem.itemImport)
logger.verbose(
"Creating new document '%s' with text from line %d to %d",
nHandle, iStart+1, iEnd
diff --git a/novelwriter/dialogs/itemeditor.py b/novelwriter/dialogs/itemeditor.py
index 9ab1e4ac..a39d93f4 100644
--- a/novelwriter/dialogs/itemeditor.py
+++ b/novelwriter/dialogs/itemeditor.py
@@ -75,15 +75,11 @@ class GuiItemEditor(QDialog):
self.editStatus = QComboBox()
self.editStatus.setMinimumWidth(mVd)
if self.theItem.itemClass in nwLists.CLS_NOVEL:
- for sLabel, _, _ in self.theProject.statusItems:
- self.editStatus.addItem(
- self.theParent.statusIcons[sLabel], sLabel, sLabel
- )
+ for sLabel, _, _, sIcon in self.theProject.statusItems:
+ self.editStatus.addItem(sIcon, sLabel, sLabel)
else:
- for sLabel, _, _ in self.theProject.importItems:
- self.editStatus.addItem(
- self.theParent.importIcons[sLabel], sLabel, sLabel
- )
+ for sLabel, _, _, sIcon in self.theProject.importItems:
+ self.editStatus.addItem(sIcon, sLabel, sLabel)
# Item Layout
self.editLayout = QComboBox()
@@ -120,7 +116,8 @@ class GuiItemEditor(QDialog):
self.editName.setText(self.theItem.itemName)
self.editName.selectAll()
- statusIdx = self.editStatus.findData(self.theItem.itemStatus)
+ currStatus, _ = self.theItem.getImportStatus()
+ statusIdx = self.editStatus.findData(currStatus)
if statusIdx != -1:
self.editStatus.setCurrentIndex(statusIdx)
@@ -180,7 +177,7 @@ class GuiItemEditor(QDialog):
isExported = self.editExport.isChecked()
self.theItem.setName(itemName)
- self.theItem.setStatus(itemStatus)
+ self.theItem.setImportStatus(itemStatus)
self.theItem.setLayout(itemLayout)
self.theItem.setExported(isExported)
diff --git a/novelwriter/dialogs/projsettings.py b/novelwriter/dialogs/projsettings.py
index 3989f7eb..f6e4b611 100644
--- a/novelwriter/dialogs/projsettings.py
+++ b/novelwriter/dialogs/projsettings.py
@@ -285,7 +285,7 @@ class GuiProjectEditStatus(QWidget):
self.listBox.setColumnWidth(self.COL_LABEL, wCol0)
self.listBox.setIndentation(0)
- for iName, iCol, nUse in self.theStatus:
+ for iName, iCol, nUse, _ in self.theStatus:
self._addItem(iName, iCol, iName, nUse)
# List Controls
diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py
index 4d35c978..64c2b73d 100644
--- a/novelwriter/gui/doceditor.py
+++ b/novelwriter/gui/doceditor.py
@@ -50,7 +50,7 @@ from PyQt5.QtWidgets import (
)
from novelwriter.core import NWDoc, NWSpellEnchant, countWords
-from novelwriter.enum import nwAlert, nwDocAction, nwDocInsert, nwItemClass
+from novelwriter.enum import nwAlert, nwDocAction, nwDocInsert
from novelwriter.common import transferCase
from novelwriter.constants import nwConst, nwKeyWords, nwUnicode
from novelwriter.gui.dochighlight import GuiDocHighlighter
@@ -2940,17 +2940,10 @@ class GuiDocEditFooter(QWidget):
sIcon = QPixmap()
sText = ""
else:
- iStatus = self._theItem.itemStatus
- if self._theItem.itemClass == nwItemClass.NOVEL:
- iStatus = self.theProject.statusItems.checkEntry(iStatus)
- theIcon = self.theParent.statusIcons[iStatus]
- else:
- iStatus = self.theProject.importItems.checkEntry(iStatus)
- theIcon = self.theParent.importIcons[iStatus]
-
+ theStatus, theIcon = self._theItem.getImportStatus()
sIcon = theIcon.pixmap(self.sPx, self.sPx)
hLevel = self.theParent.theIndex.getHandleHeaderLevel(self._docHandle)
- sText = f"{self._theItem.itemStatus} / {self._theItem.describeMe(hLevel)}"
+ sText = f"{theStatus} / {self._theItem.describeMe(hLevel)}"
self.statusIcon.setPixmap(sIcon)
self.statusText.setText(sText)
diff --git a/novelwriter/gui/itemdetails.py b/novelwriter/gui/itemdetails.py
index 0596f7a8..21df9b80 100644
--- a/novelwriter/gui/itemdetails.py
+++ b/novelwriter/gui/itemdetails.py
@@ -30,7 +30,7 @@ from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5.QtGui import QFont, QPixmap
from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel
-from novelwriter.enum import nwItemClass, nwItemType
+from novelwriter.enum import nwItemType
from novelwriter.constants import trConst, nwLabels
logger = logging.getLogger(__name__)
@@ -249,16 +249,9 @@ class GuiItemDetails(QWidget):
# Status
# ======
- itStatus = nwItem.itemStatus
- if nwItem.itemClass == nwItemClass.NOVEL:
- itStatus = self.theProject.statusItems.checkEntry(itStatus) # Make sure it's valid
- flagIcon = self.theParent.statusIcons[itStatus]
- else:
- itStatus = self.theProject.importItems.checkEntry(itStatus) # Make sure it's valid
- flagIcon = self.theParent.importIcons[itStatus]
-
- self.statusIcon.setPixmap(flagIcon.pixmap(iPx, iPx))
- self.statusData.setText(nwItem.itemStatus)
+ theStatus, theIcon = nwItem.getImportStatus()
+ self.statusIcon.setPixmap(theIcon.pixmap(iPx, iPx))
+ self.statusData.setText(theStatus)
# Class
# =====
diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py
index 18b2b9f5..01a8f707 100644
--- a/novelwriter/gui/projtree.py
+++ b/novelwriter/gui/projtree.py
@@ -609,14 +609,7 @@ class GuiProjectTree(QTreeWidget):
else:
expIcon = self.theTheme.getIcon("cross")
- iStatus = nwItem.itemStatus
- if nwItem.itemClass == nwItemClass.NOVEL:
- iStatus = self.theProject.statusItems.checkEntry(iStatus) # Make sure it's valid
- statIcon = self.theParent.statusIcons[iStatus]
- else:
- iStatus = self.theProject.importItems.checkEntry(iStatus) # Make sure it's valid
- statIcon = self.theParent.importIcons[iStatus]
-
+ itempStatus, statusIcon = nwItem.getImportStatus()
hLevel = self.theIndex.getHandleHeaderLevel(tHandle)
itemIcon = self.theTheme.getItemIcon(
nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel
@@ -625,8 +618,8 @@ class GuiProjectTree(QTreeWidget):
trItem.setIcon(self.C_NAME, itemIcon)
trItem.setText(self.C_NAME, nwItem.itemName)
trItem.setIcon(self.C_EXPORT, expIcon)
- trItem.setIcon(self.C_STATUS, statIcon)
- trItem.setToolTip(self.C_STATUS, nwItem.itemStatus)
+ trItem.setIcon(self.C_STATUS, statusIcon)
+ trItem.setToolTip(self.C_STATUS, itempStatus)
if self.mainConf.emphLabels and nwItem.itemLayout == nwItemLayout.DOCUMENT:
trFont = trItem.font(self.C_NAME)
diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py
index 2eaea912..9db27659 100644
--- a/novelwriter/guimain.py
+++ b/novelwriter/guimain.py
@@ -31,7 +31,7 @@ from time import time
from datetime import datetime
from PyQt5.QtCore import Qt, QTimer, QSize, QThreadPool, pyqtSlot
-from PyQt5.QtGui import QIcon, QPixmap, QColor, QKeySequence, QCursor
+from PyQt5.QtGui import QIcon, QKeySequence, QCursor
from PyQt5.QtWidgets import (
qApp, QMainWindow, QVBoxLayout, QWidget, QSplitter, QFileDialog, QShortcut,
QMessageBox, QDialog, QTabWidget, QToolBar, QAction
@@ -129,10 +129,6 @@ class GuiMain(QMainWindow):
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
- # Minor GUI Elements
- self.statusIcons = []
- self.importIcons = []
-
# Project Tree Tabs
self.projTabs = QTabWidget()
self.projTabs.setTabPosition(QTabWidget.South)
@@ -869,8 +865,6 @@ class GuiMain(QMainWindow):
def rebuildTrees(self):
"""Rebuild the project tree.
"""
- self._makeStatusIcons()
- self._makeImportIcons()
self.treeView.buildTree()
self.novelView.refreshTree()
return
@@ -1462,29 +1456,6 @@ class GuiMain(QMainWindow):
self.saveDocument()
return
- def _makeStatusIcons(self):
- """Generate all the item status icons based on project settings.
- """
- self.statusIcons = {}
- iPx = self.mainConf.pxInt(32)
- for sLabel, sCol, _ in self.theProject.statusItems:
- theIcon = QPixmap(iPx, iPx)
- theIcon.fill(QColor(*sCol))
- self.statusIcons[sLabel] = QIcon(theIcon)
- return
-
- def _makeImportIcons(self):
- """Generate all the item importance icons based on project
- settings.
- """
- self.importIcons = {}
- iPx = self.mainConf.pxInt(32)
- for sLabel, sCol, _ in self.theProject.importItems:
- theIcon = QPixmap(iPx, iPx)
- theIcon.fill(QColor(*sCol))
- self.importIcons[sLabel] = QIcon(theIcon)
- return
-
def _assembleProjectWizardData(self, newProj):
"""Extract the user choices from the New Project Wizard and
store them in a dictionary.
diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx
index bf40e1ee..68265de5 100644
--- a/sample/nwProject.nwx
+++ b/sample/nwProject.nwx
@@ -1,5 +1,5 @@
-
+
Sample Project
Sample Project
@@ -7,7 +7,7 @@
Jay Doh
1303
199
- 64457
+ 65005
False
@@ -33,121 +33,121 @@
- New
- Notes
- Started
- 1st Draft
- 2nd Draft
- 3rd Draft
- Finished
+ New
+ Notes
+ Started
+ 1st Draft
+ 2nd Draft
+ 3rd Draft
+ Finished
- None
- Minor
- Major
- Main
+ None
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Title Page
+ Title Page
-
- Page
+ Page
-
- Part One
+ Part One
-
- A Folder
+ A Folder
-
- Chapter One
+ Chapter One
-
- Making a Scene
+ Making a Scene
-
- Another Scene
+ Another Scene
-
- Interlude
+ Interlude
-
- A Note on Structure
+ A Note on Structure
-
- Chapter Two
+ Chapter Two
-
- We Found John!
+ We Found John!
-
- Characters
+ Characters
-
- Main Characters
+ Main Characters
-
- John Smith
+ John Smith
-
- Jane Smith
+ Jane Smith
-
- Locations
+ Locations
-
- Earth
+ Earth
-
- Space
+ Space
-
- Mars
+ Mars
-
- Archive
+ Archive
-
- Scenes
+ Scenes
-
- Old File
+ Old File
-
- Trash
+ Trash
-
- Delete Me!
+ Delete Me!
diff --git a/tests/conftest.py b/tests/conftest.py
index cf348870..4d8d7183 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -36,6 +36,13 @@ from PyQt5.QtWidgets import QMessageBox # noqa: E402
from novelwriter.config import Config # noqa: E402
+@pytest.fixture(autouse=True)
+def initQt(qtbot):
+ """Ensures that the qt main thread is always available in all tests.
+ """
+ return
+
+
##
# Core Test Folders
##
diff --git a/tests/lipsum/nwProject.nwx b/tests/lipsum/nwProject.nwx
index 457d8672..05069e2c 100644
--- a/tests/lipsum/nwProject.nwx
+++ b/tests/lipsum/nwProject.nwx
@@ -1,12 +1,12 @@
-
+
Lorem Ipsum
Lorem Ipsum
lipsum.com
23
24
- 1857
+ 1854
False
@@ -31,102 +31,102 @@
- New
- Note
- Draft
- Finished
+ New
+ Note
+ Draft
+ Finished
- New
- Minor
- Major
- Main
+ New
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Lorem Ipsum
+ Lorem Ipsum
-
- Front Matter
+ Front Matter
-
- Prologue
+ Prologue
-
- Act One
+ Act One
-
- Chapter One
+ Chapter One
-
- Chapter One
+ Chapter One
-
- Scene One
+ Scene One
-
- Scene Two
+ Scene Two
-
- Interlude
+ Interlude
-
- Chapter Two
+ Chapter Two
-
- Chapter Two
+ Chapter Two
-
- Scene Three
+ Scene Three
-
- Scene Four
+ Scene Four
-
- Scene Five
+ Scene Five
-
- Characters
+ Characters
-
- Mr. Nobody
+ Mr. Nobody
-
- Plot
+ Plot
-
- Main
+ Main
-
- World
+ World
-
- Ancient Europe
+ Ancient Europe
diff --git a/tests/minimal/nwProject.nwx b/tests/minimal/nwProject.nwx
index 708d449f..82fa1ed1 100644
--- a/tests/minimal/nwProject.nwx
+++ b/tests/minimal/nwProject.nwx
@@ -1,13 +1,13 @@
-
+
Test Minimal
Minimal
Jane Doe
John Doh
- 13
+ 14
2
- 134
+ 135
True
@@ -29,50 +29,50 @@
- New
- Note
- Draft
- Finished
+ New
+ Note
+ Draft
+ Finished
- New
- Minor
- Major
- Main
+ New
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Title Page
+ Title Page
-
- New Chapter
+ New Chapter
-
- New Chapter
+ New Chapter
-
- New Scene
+ New Scene
-
- Plot
+ Plot
-
- Characters
+ Characters
-
- World
+ World
diff --git a/tests/reference/coreProject_NewCustomA_nwProject.nwx b/tests/reference/coreProject_NewCustomA_nwProject.nwx
index 92517d59..92bbcf0e 100644
--- a/tests/reference/coreProject_NewCustomA_nwProject.nwx
+++ b/tests/reference/coreProject_NewCustomA_nwProject.nwx
@@ -1,5 +1,5 @@
-
+
Test Custom
Test Novel
@@ -29,110 +29,110 @@
- New
- Note
- Draft
- Finished
+ New
+ Note
+ Draft
+ Finished
- New
- Minor
- Major
- Main
+ New
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Plot
+ Plot
-
- Characters
+ Characters
-
- Locations
+ Locations
-
- Timeline
+ Timeline
-
- Objects
+ Objects
-
- Entities
+ Entities
-
- Title Page
+ Title Page
-
- Chapter 1
+ Chapter 1
-
- Chapter 1
+ Chapter 1
-
- Scene 1.1
+ Scene 1.1
-
- Scene 1.2
+ Scene 1.2
-
- Scene 1.3
+ Scene 1.3
-
- Chapter 2
+ Chapter 2
-
- Chapter 2
+ Chapter 2
-
- Scene 2.1
+ Scene 2.1
-
- Scene 2.2
+ Scene 2.2
-
- Scene 2.3
+ Scene 2.3
-
- Chapter 3
+ Chapter 3
-
- Chapter 3
+ Chapter 3
-
- Scene 3.1
+ Scene 3.1
-
- Scene 3.2
+ Scene 3.2
-
- Scene 3.3
+ Scene 3.3
diff --git a/tests/reference/coreProject_NewCustomB_nwProject.nwx b/tests/reference/coreProject_NewCustomB_nwProject.nwx
index 2614990c..e9ed7a7f 100644
--- a/tests/reference/coreProject_NewCustomB_nwProject.nwx
+++ b/tests/reference/coreProject_NewCustomB_nwProject.nwx
@@ -1,5 +1,5 @@
-
+
Test Custom
Test Novel
@@ -29,74 +29,74 @@
- New
- Note
- Draft
- Finished
+ New
+ Note
+ Draft
+ Finished
- New
- Minor
- Major
- Main
+ New
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Plot
+ Plot
-
- Characters
+ Characters
-
- Locations
+ Locations
-
- Timeline
+ Timeline
-
- Objects
+ Objects
-
- Entities
+ Entities
-
- Title Page
+ Title Page
-
- Scene 1
+ Scene 1
-
- Scene 2
+ Scene 2
-
- Scene 3
+ Scene 3
-
- Scene 4
+ Scene 4
-
- Scene 5
+ Scene 5
-
- Scene 6
+ Scene 6
diff --git a/tests/reference/coreProject_NewFile_nwProject.nwx b/tests/reference/coreProject_NewFile_nwProject.nwx
index a0c16221..4cd389ba 100644
--- a/tests/reference/coreProject_NewFile_nwProject.nwx
+++ b/tests/reference/coreProject_NewFile_nwProject.nwx
@@ -1,5 +1,5 @@
-
+
New Project
@@ -27,58 +27,58 @@
- New
- Note
- Draft
- Finished
+ New
+ Note
+ Draft
+ Finished
- New
- Minor
- Major
- Main
+ New
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Plot
+ Plot
-
- Characters
+ Characters
-
- World
+ World
-
- Title Page
+ Title Page
-
- New Chapter
+ New Chapter
-
- New Chapter
+ New Chapter
-
- New Scene
+ New Scene
-
- Hello
+ Hello
-
- Jane
+ Jane
diff --git a/tests/reference/coreProject_NewMinimal_nwProject.nwx b/tests/reference/coreProject_NewMinimal_nwProject.nwx
index 4581e521..0bd9c54a 100644
--- a/tests/reference/coreProject_NewMinimal_nwProject.nwx
+++ b/tests/reference/coreProject_NewMinimal_nwProject.nwx
@@ -1,5 +1,5 @@
-
+
New Project
@@ -27,50 +27,50 @@
- New
- Note
- Draft
- Finished
+ New
+ Note
+ Draft
+ Finished
- New
- Minor
- Major
- Main
+ New
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Plot
+ Plot
-
- Characters
+ Characters
-
- World
+ World
-
- Title Page
+ Title Page
-
- New Chapter
+ New Chapter
-
- New Chapter
+ New Chapter
-
- New Scene
+ New Scene
diff --git a/tests/reference/coreProject_NewRoot_nwProject.nwx b/tests/reference/coreProject_NewRoot_nwProject.nwx
index 25b47036..74edeecd 100644
--- a/tests/reference/coreProject_NewRoot_nwProject.nwx
+++ b/tests/reference/coreProject_NewRoot_nwProject.nwx
@@ -1,5 +1,5 @@
-
+
New Project
@@ -27,82 +27,82 @@
- New
- Note
- Draft
- Finished
+ New
+ Note
+ Draft
+ Finished
- New
- Minor
- Major
- Main
+ New
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Plot
+ Plot
-
- Characters
+ Characters
-
- World
+ World
-
- Title Page
+ Title Page
-
- New Chapter
+ New Chapter
-
- New Chapter
+ New Chapter
-
- New Scene
+ New Scene
-
- Novel
+ Novel
-
- Plot
+ Plot
-
- Character
+ Character
-
- World
+ World
-
- Timeline
+ Timeline
-
- Object
+ Object
-
- Custom1
+ Custom1
-
- Custom2
+ Custom2
diff --git a/tests/reference/guiEditor_Main_Final_nwProject.nwx b/tests/reference/guiEditor_Main_Final_nwProject.nwx
index a33a6e6a..c6e522b1 100644
--- a/tests/reference/guiEditor_Main_Final_nwProject.nwx
+++ b/tests/reference/guiEditor_Main_Final_nwProject.nwx
@@ -1,5 +1,5 @@
-
+
New Project
@@ -27,66 +27,66 @@
- New
- Note
- Draft
- Finished
+ New
+ Note
+ Draft
+ Finished
- New
- Minor
- Major
- Main
+ New
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Title Page
+ Title Page
-
- New Chapter
+ New Chapter
-
- New Chapter
+ New Chapter
-
- New Scene
+ New Scene
-
- Plot
+ Plot
-
- New File
+ New File
-
- Characters
+ Characters
-
- New File
+ New File
-
- World
+ World
-
- New File
+ New File
-
- Trash
+ Trash
diff --git a/tests/reference/guiEditor_Main_Initial_nwProject.nwx b/tests/reference/guiEditor_Main_Initial_nwProject.nwx
index 5fbd17bb..a9f83ce2 100644
--- a/tests/reference/guiEditor_Main_Initial_nwProject.nwx
+++ b/tests/reference/guiEditor_Main_Initial_nwProject.nwx
@@ -1,5 +1,5 @@
-
+
New Project
@@ -27,50 +27,50 @@
- New
- Note
- Draft
- Finished
+ New
+ Note
+ Draft
+ Finished
- New
- Minor
- Major
- Main
+ New
+ Minor
+ Major
+ Main
-
- Novel
+ Novel
-
- Title Page
+ Title Page
-
- New Chapter
+ New Chapter
-
- New Chapter
+ New Chapter
-
- New Scene
+ New Scene
-
- Plot
+ Plot
-
- Characters
+ Characters
-
- World
+ World
diff --git a/tests/reference/guiProjSettings_Dialog_nwProject.nwx b/tests/reference/guiProjSettings_Dialog_nwProject.nwx
index e34a844b..ab60874a 100644
--- a/tests/reference/guiProjSettings_Dialog_nwProject.nwx
+++ b/tests/reference/guiProjSettings_Dialog_nwProject.nwx
@@ -1,5 +1,5 @@
-
+
Project Name
Project Title
@@ -33,50 +33,50 @@
- New
- Note
- Finished
- Final
+ New
+ Note
+ Finished
+ Final
- New
- Minor
- Major
- Final
+ New
+ Minor
+ Major
+ Final
-
- Novel
+ Novel
-
- Title Page
+ Title Page
-
- New Chapter
+ New Chapter
-
- New Chapter
+ New Chapter
-
- New Scene
+ New Scene
-
- Plot
+ Plot
-
- Characters
+ Characters
-
- World
+ World
diff --git a/tests/test_core/test_core_item.py b/tests/test_core/test_core_item.py
index 05c1d077..874177e1 100644
--- a/tests/test_core/test_core_item.py
+++ b/tests/test_core/test_core_item.py
@@ -23,6 +23,8 @@ import pytest
from lxml import etree
+from PyQt5.QtGui import QIcon
+
from novelwriter.core import NWProject
from novelwriter.core.item import NWItem
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
@@ -86,16 +88,17 @@ def testCoreItem_Setters(mockGUI):
assert theItem.itemOrder == 1
# Importance
- 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"
+ theItem._class = nwItemClass.CHARACTER
+ theItem.setImport("Nonsense")
+ assert theItem.itemImport == "New"
+ theItem.setImport("New")
+ assert theItem.itemImport == "New"
+ theItem.setImport("Minor")
+ assert theItem.itemImport == "Minor"
+ theItem.setImport("Major")
+ assert theItem.itemImport == "Major"
+ theItem.setImport("Main")
+ assert theItem.itemImport == "Main"
# Status
theItem._class = nwItemClass.NOVEL
@@ -110,6 +113,27 @@ def testCoreItem_Setters(mockGUI):
theItem.setStatus("Finished")
assert theItem.itemStatus == "Finished"
+ # Status/Importance Wrapper
+ theItem._class = nwItemClass.CHARACTER
+ theItem.setImportStatus("New")
+ assert theItem.itemImport == "New"
+ theItem.setImportStatus("Minor")
+ assert theItem.itemImport == "Minor"
+ theItem.setImportStatus("Note")
+ assert theItem.itemImport == "New"
+ theItem.setImportStatus("Draft")
+ assert theItem.itemImport == "New"
+
+ theItem._class = nwItemClass.NOVEL
+ theItem.setImportStatus("New")
+ assert theItem.itemStatus == "New"
+ theItem.setImportStatus("Minor")
+ assert theItem.itemStatus == "New"
+ theItem.setImportStatus("Note")
+ assert theItem.itemStatus == "Note"
+ theItem.setImportStatus("Draft")
+ assert theItem.itemStatus == "Draft"
+
# Expanded
theItem.setExpanded(8)
assert theItem.isExpanded is False
@@ -208,6 +232,22 @@ def testCoreItem_Methods(mockGUI):
theItem.setLayout("NOTE")
assert theItem.describeMe() == "Project Note"
+ # Status + Icon
+ # =============
+ theItem.setType("FILE")
+ theItem.setStatus("Note")
+ theItem.setImport("Minor")
+
+ theItem.setClass("NOVEL")
+ stT, stI = theItem.getImportStatus()
+ assert stT == "Note"
+ assert isinstance(stI, QIcon)
+
+ theItem.setClass("CHARACTER")
+ stT, stI = theItem.getImportStatus()
+ assert stT == "Minor"
+ assert isinstance(stI, QIcon)
+
# Representation
# ==============
@@ -358,7 +398,7 @@ def testCoreItem_XMLPackUnpack(mockGUI, caplog):
b''
b'- A Name
'
+ b'cursorPos="11"/>A Name'
b''
)
@@ -403,8 +443,8 @@ def testCoreItem_XMLPackUnpack(mockGUI, caplog):
assert etree.tostring(xContent, pretty_print=False, encoding="utf-8") == (
b''
b'- A Name'
- b'
'
+ b'type="FOLDER" class="NOVEL">A Name'
b''
)
diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py
index 2f9d40e3..bfcc5171 100644
--- a/tests/test_core/test_core_project.py
+++ b/tests/test_core/test_core_project.py
@@ -61,10 +61,6 @@ def testCoreProject_NewMinimal(fncDir, outDir, refDir, mockGUI):
# Creating the project once more should fail
assert theProject.newProject({"projPath": fncDir}) is False
- # Check the new project
- copyfile(projFile, testFile)
- assert cmpFiles(testFile, compFile, [2, 6, 7, 8])
-
# Open again
assert theProject.openProject(projFile) is True
@@ -857,7 +853,7 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, mockGUI, tmpDir):
# Change importance
fHandle = theProject.newFile("Jane Doe", nwItemClass.CHARACTER, "afb3043c7b2b3")
- theProject.projTree[fHandle].setStatus("Main")
+ theProject.projTree[fHandle].setImport("Main")
newList = [
("New", 1, 1, 1, "New"),
("Minor", 2, 2, 2, "Minor"),
@@ -872,7 +868,7 @@ def testCoreProject_Methods(monkeypatch, nwMinimal, mockGUI, tmpDir):
assert theProject.importItems._theColours == [
(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5)
]
- assert theProject.projTree[fHandle].itemStatus == "Min"
+ assert theProject.projTree[fHandle].itemImport == "Min"
# Check status counts
assert theProject.statusItems._theCounts == [0, 0, 0, 0, 0]
diff --git a/tests/test_core/test_core_status.py b/tests/test_core/test_core_status.py
index ab5af333..a7a2d55e 100644
--- a/tests/test_core/test_core_status.py
+++ b/tests/test_core/test_core_status.py
@@ -23,6 +23,8 @@ import pytest
from lxml import etree
+from PyQt5.QtGui import QIcon
+
from novelwriter.core.status import NWStatus
@@ -48,9 +50,9 @@ def testCoreStatus_Entries():
assert theStatus._theLength == 4
# Lookups
- assert theStatus.lookupEntry(None) is None
- assert theStatus.lookupEntry("stuff") is None
- assert theStatus.lookupEntry("Main") == 3
+ assert theStatus._getIndex(None) is None
+ assert theStatus._getIndex("stuff") is None
+ assert theStatus._getIndex("Main") == 3
# Checks
assert theStatus.checkEntry(123) == "New"
@@ -58,6 +60,10 @@ def testCoreStatus_Entries():
assert theStatus.checkEntry("New ") == "New"
assert theStatus.checkEntry(" Main ") == "Main"
+ # Icons
+ assert isinstance(theStatus.getIcon("Stuff"), QIcon)
+ assert isinstance(theStatus.getIcon("New"), QIcon)
+
# Set new list
newList = [
("New", 1, 1, 1, "New"),
@@ -87,12 +93,17 @@ def testCoreStatus_Entries():
assert theStatus._theCounts == countTo
# Iterate
- for i, (sA, sB, sC) in enumerate(theStatus):
+ for i, (sA, sB, sC, sD) in enumerate(theStatus):
assert sA == theStatus._theLabels[i]
assert sB == theStatus._theColours[i]
assert sC == theStatus._theCounts[i]
+ assert sD == theStatus._theIcons[i]
- assert theStatus[9] == (None, None, None)
+ sA, sB, sC, sD = theStatus[9]
+ assert sA is None
+ assert sB is None
+ assert sC is None
+ assert isinstance(sD, QIcon)
# Clear counts
theStatus.resetCounts()
@@ -122,12 +133,12 @@ def testCoreStatus_XMLPackUnpack():
xStatus = etree.SubElement(nwXML, "status")
theStatus.packXML(xStatus)
assert etree.tostring(xStatus, pretty_print=False, encoding="utf-8") == (
- b""
- b"New"
- b"Minor"
- b"Major"
- b"Main"
- b""
+ b''
+ b'New'
+ b'Minor'
+ b'Major'
+ b'Main'
+ b''
)
# Unpack
diff --git a/tests/test_core/test_core_tokenizer.py b/tests/test_core/test_core_tokenizer.py
index d277a601..088de786 100644
--- a/tests/test_core/test_core_tokenizer.py
+++ b/tests/test_core/test_core_tokenizer.py
@@ -30,7 +30,7 @@ from novelwriter.core.tokenizer import Tokenizer
class BareTokenizer(Tokenizer):
def doConvert(self):
- pass
+ super().doConvert()
@pytest.mark.core
@@ -219,6 +219,10 @@ def testCoreToken_TextOps(monkeypatch, nwMinimal, mockGUI):
"# Notes: Plot\n\n"
)
+ # Ckeck abstract method
+ with pytest.raises(NotImplementedError):
+ theToken.doConvert()
+
# END Test testCoreToken_TextOps
diff --git a/tests/test_core/test_core_tree.py b/tests/test_core/test_core_tree.py
index 1e3e7d94..3fd07a43 100644
--- a/tests/test_core/test_core_tree.py
+++ b/tests/test_core/test_core_tree.py
@@ -397,27 +397,32 @@ def testCoreTree_XMLPackUnpack(mockGUI, mockItems):
b''
b''
b'- Novel
'
- b'- Act One'
+ b'class="NOVEL">Novel'
b'
'
+ b'- Act One
'
b'- Chapter One'
- b'
'
+ b'paraCount="2" cursorPos="0"/>Chapter One'
b'- Scene One'
- b'
'
+ b'paraCount="20" cursorPos="0"/>Scene One'
b'- Outtakes
'
+ b'class="ARCHIVE">Outtakes'
b'- Trash
'
+ b'class="TRASH">Trash'
+ b''
b'- Characters
'
+ b'class="CHARACTER">Characters'
b'- Jane Doe
'
+ b'paraCount="16" cursorPos="0"/>Jane Doe'
b''
b''
)
diff --git a/tests/test_dialogs/test_dlg_itemeditor.py b/tests/test_dialogs/test_dlg_itemeditor.py
index 4d183408..79038345 100644
--- a/tests/test_dialogs/test_dlg_itemeditor.py
+++ b/tests/test_dialogs/test_dlg_itemeditor.py
@@ -174,11 +174,12 @@ def testDlgItemEditor_Note(qtbot, monkeypatch, nwGUI, fncProj):
itemEdit.editName.setText("New Character")
itemEdit.editStatus.setCurrentIndex(1)
itemEdit.editExport.setChecked(False)
+ itemEdit._doSave()
# Check New Settings
- itemEdit._doSave()
assert itemEdit.theItem.itemName == "New Character"
- assert itemEdit.theItem.itemStatus == "Minor"
+ assert itemEdit.theItem.itemStatus == "New"
+ assert itemEdit.theItem.itemImport == "Minor"
assert itemEdit.theItem.itemLayout == nwItemLayout.NOTE
assert itemEdit.theItem.isExported is False