Merge branch 'main' into outline_view

This commit is contained in:
Veronica Berglyd Olsen
2022-06-05 13:36:54 +02:00
47 changed files with 1881 additions and 1510 deletions
+5 -5
View File
@@ -34,7 +34,7 @@ def trConst(tString):
return QCoreApplication.translate("Constant", tString) return QCoreApplication.translate("Constant", tString)
class nwConst(): class nwConst:
# Date and Time Formats # Date and Time Formats
FMT_TSTAMP = "%Y-%m-%d %H:%M:%S" # Default format FMT_TSTAMP = "%Y-%m-%d %H:%M:%S" # Default format
@@ -48,7 +48,7 @@ class nwConst():
# END Class nwConst # END Class nwConst
class nwRegEx(): class nwRegEx:
FMT_EI = r"(?<![\w\\])(_)(?![\s_])(.+?)(?<![\s\\])(\1)(?!\w)" FMT_EI = r"(?<![\w\\])(_)(?![\s_])(.+?)(?<![\s\\])(\1)(?!\w)"
FMT_EB = r"(?<![\w\\])([\*]{2})(?![\s\*])(.+?)(?<![\s\\])(\1)(?!\w)" FMT_EB = r"(?<![\w\\])([\*]{2})(?![\s\*])(.+?)(?<![\s\\])(\1)(?!\w)"
@@ -57,7 +57,7 @@ class nwRegEx():
# END Class nwRegEx # END Class nwRegEx
class nwFiles(): class nwFiles:
PROJ_FILE = "nwProject.nwx" PROJ_FILE = "nwProject.nwx"
PROJ_DICT = "wordlist.txt" PROJ_DICT = "wordlist.txt"
@@ -107,7 +107,7 @@ class nwKeyWords:
# END Class nwKeyWords # END Class nwKeyWords
class nwLabels(): class nwLabels:
CLASS_NAME = { CLASS_NAME = {
nwItemClass.NO_CLASS: QT_TRANSLATE_NOOP("Constant", "None"), nwItemClass.NO_CLASS: QT_TRANSLATE_NOOP("Constant", "None"),
@@ -185,7 +185,7 @@ class nwLabels():
# END Class nwLabels # END Class nwLabels
class nwQuotes(): class nwQuotes:
"""Allowed quotation marks. """Allowed quotation marks.
Source: https://en.wikipedia.org/wiki/Quotation_mark Source: https://en.wikipedia.org/wiki/Quotation_mark
""" """
+1 -2
View File
@@ -20,7 +20,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from novelwriter.core.document import NWDoc from novelwriter.core.document import NWDoc
from novelwriter.core.index import NWIndex, countWords from novelwriter.core.index import countWords
from novelwriter.core.project import NWProject from novelwriter.core.project import NWProject
from novelwriter.core.spellcheck import NWSpellEnchant from novelwriter.core.spellcheck import NWSpellEnchant
from novelwriter.core.tohtml import ToHtml from novelwriter.core.tohtml import ToHtml
@@ -30,7 +30,6 @@ from novelwriter.core.tomd import ToMarkdown
__all__ = [ __all__ = [
"countWords", "countWords",
"NWDoc", "NWDoc",
"NWIndex",
"NWProject", "NWProject",
"NWSpellEnchant", "NWSpellEnchant",
"ToHtml", "ToHtml",
+1 -1
View File
@@ -52,7 +52,7 @@ class NWDoc():
self._docHandle = theHandle self._docHandle = theHandle
if self._docHandle is not None: if self._docHandle is not None:
self._theItem = self.theProject.projTree[theHandle] self._theItem = self.theProject.tree[theHandle]
return return
+738 -337
View File
File diff suppressed because it is too large Load Diff
+56 -38
View File
@@ -37,6 +37,7 @@ from PyQt5.QtCore import QCoreApplication
from novelwriter.core.tree import NWTree from novelwriter.core.tree import NWTree
from novelwriter.core.item import NWItem from novelwriter.core.item import NWItem
from novelwriter.core.index import NWIndex
from novelwriter.core.status import NWStatus from novelwriter.core.status import NWStatus
from novelwriter.core.options import OptionState from novelwriter.core.options import OptionState
from novelwriter.core.document import NWDoc from novelwriter.core.document import NWDoc
@@ -62,9 +63,10 @@ class NWProject():
self.mainConf = novelwriter.CONFIG self.mainConf = novelwriter.CONFIG
# Core Elements # Core Elements
self.optState = OptionState(self) # Project-specific GUI options self._optState = OptionState(self) # Project-specific GUI options
self.projTree = NWTree(self) # The project tree self._projTree = NWTree(self) # The project tree
self.langData = {} # Localisation data self._projIndex = NWIndex(self) # The projecty index
self._langData = {} # Localisation data
# Project Status # Project Status
self.projOpened = 0 # The time stamp of when the project file was opened self.projOpened = 0 # The time stamp of when the project file was opened
@@ -116,6 +118,22 @@ class NWProject():
return return
##
# Properties
##
@property
def index(self):
return self._projIndex
@property
def tree(self):
return self._projTree
@property
def options(self):
return self._optState
## ##
# Item Methods # Item Methods
## ##
@@ -129,8 +147,8 @@ class NWProject():
newItem.setName(label) newItem.setName(label)
newItem.setType(nwItemType.ROOT) newItem.setType(nwItemType.ROOT)
newItem.setClass(itemClass) newItem.setClass(itemClass)
self.projTree.append(None, None, newItem) self._projTree.append(None, None, newItem)
self.projTree.updateItemData(newItem.itemHandle) self._projTree.updateItemData(newItem.itemHandle)
return newItem.itemHandle return newItem.itemHandle
def newFolder(self, label, pHandle): def newFolder(self, label, pHandle):
@@ -139,8 +157,8 @@ class NWProject():
newItem = NWItem(self) newItem = NWItem(self)
newItem.setName(label) newItem.setName(label)
newItem.setType(nwItemType.FOLDER) newItem.setType(nwItemType.FOLDER)
self.projTree.append(None, pHandle, newItem) self._projTree.append(None, pHandle, newItem)
self.projTree.updateItemData(newItem.itemHandle) self._projTree.updateItemData(newItem.itemHandle)
return newItem.itemHandle return newItem.itemHandle
def newFile(self, label, pHandle): def newFile(self, label, pHandle):
@@ -149,21 +167,21 @@ class NWProject():
newItem = NWItem(self) newItem = NWItem(self)
newItem.setName(label) newItem.setName(label)
newItem.setType(nwItemType.FILE) newItem.setType(nwItemType.FILE)
self.projTree.append(None, pHandle, newItem) self._projTree.append(None, pHandle, newItem)
self.projTree.updateItemData(newItem.itemHandle) self._projTree.updateItemData(newItem.itemHandle)
return newItem.itemHandle return newItem.itemHandle
def trashFolder(self): def trashFolder(self):
"""Add the special trash root folder to the project. """Add the special trash root folder to the project.
""" """
trashHandle = self.projTree.trashRoot() trashHandle = self._projTree.trashRoot()
if trashHandle is None: if trashHandle is None:
newItem = NWItem(self) newItem = NWItem(self)
newItem.setName(trConst(nwLabels.CLASS_NAME[nwItemClass.TRASH])) newItem.setName(trConst(nwLabels.CLASS_NAME[nwItemClass.TRASH]))
newItem.setType(nwItemType.ROOT) newItem.setType(nwItemType.ROOT)
newItem.setClass(nwItemClass.TRASH) newItem.setClass(nwItemClass.TRASH)
self.projTree.append(None, None, newItem) self._projTree.append(None, None, newItem)
self.projTree.updateItemData(newItem.itemHandle) self._projTree.updateItemData(newItem.itemHandle)
return newItem.itemHandle return newItem.itemHandle
return trashHandle return trashHandle
@@ -184,7 +202,7 @@ class NWProject():
self.autoCount = 0 self.autoCount = 0
# Project Tree # Project Tree
self.projTree.clear() self._projTree.clear()
# Project Settings # Project Settings
self.projPath = None self.projPath = None
@@ -588,9 +606,9 @@ class NWProject():
elif xChild.tag == "content": elif xChild.tag == "content":
logger.debug("Found project content") logger.debug("Found project content")
self.projTree.unpackXML(xChild) self._projTree.unpackXML(xChild)
self.optState.loadSettings() self._optState.loadSettings()
# Sort out old file locations # Sort out old file locations
if legacyList: if legacyList:
@@ -608,12 +626,12 @@ class NWProject():
self.mainConf.saveRecentCache() self.mainConf.saveRecentCache()
# Check the project tree consistency # Check the project tree consistency
for tItem in self.projTree: for tItem in self._projTree:
tHandle = tItem.itemHandle tHandle = tItem.itemHandle
logger.verbose("Checking item '%s'", tHandle) logger.verbose("Checking item '%s'", tHandle)
if not self.projTree.updateItemData(tHandle): if not self._projTree.updateItemData(tHandle):
logger.error("There was a problem item '%s', and it has been removed", tHandle) logger.error("There was a problem item '%s', and it has been removed", tHandle)
del self.projTree[tHandle] # The file will be re-added as orphaned del self._projTree[tHandle] # The file will be re-added as orphaned
self._scanProjectFolder() self._scanProjectFolder()
self._loadProjectLocalisation() self._loadProjectLocalisation()
@@ -700,7 +718,7 @@ class NWProject():
# Save Tree Content # Save Tree Content
logger.debug("Writing project content") logger.debug("Writing project content")
self.projTree.packXML(nwXML) self._projTree.packXML(nwXML)
# Write the xml tree to file # Write the xml tree to file
tempFile = os.path.join(self.projPath, self.projFile+"~") tempFile = os.path.join(self.projPath, self.projFile+"~")
@@ -733,7 +751,7 @@ class NWProject():
return False return False
# Save project GUI options # Save project GUI options
self.optState.saveSettings() self._optState.saveSettings()
# Update recent projects # Update recent projects
self.mainConf.updateRecentCache(self.projPath, self.projName, self.currWCount, saveTime) self.mainConf.updateRecentCache(self.projPath, self.projName, self.currWCount, saveTime)
@@ -749,8 +767,8 @@ class NWProject():
"""Close the current project and clear all meta data. """Close the current project and clear all meta data.
""" """
logger.info("Closing project: %s", self.projPath) logger.info("Closing project: %s", self.projPath)
self.optState.saveSettings() self._optState.saveSettings()
self.projTree.writeToCFile() self._projTree.writeToCFile()
self._appendSessionStats(idleTime) self._appendSessionStats(idleTime)
self._clearLockFile() self._clearLockFile()
self.clearProject() self.clearProject()
@@ -1050,9 +1068,9 @@ class NWProject():
items in the GUI project tree. The user can rearrange the order items in the GUI project tree. The user can rearrange the order
by drag-and-drop. Forwarded to the NWTree class. by drag-and-drop. Forwarded to the NWTree class.
""" """
if len(self.projTree) != len(newOrder): if len(self._projTree) != len(newOrder):
logger.warning("Sizes of new and old tree order do not match") logger.warning("Sizes of new and old tree order do not match")
self.projTree.setOrder(newOrder) self._projTree.setOrder(newOrder)
self.setProjectChanged(True) self.setProjectChanged(True)
return True return True
@@ -1146,16 +1164,16 @@ class NWProject():
capable of handling it. capable of handling it.
""" """
sentItems = [] sentItems = []
iterItems = self.projTree.handles() iterItems = self._projTree.handles()
n = 0 n = 0
nMax = min(len(iterItems), 10000) nMax = min(len(iterItems), 10000)
while n < nMax: while n < nMax:
tHandle = iterItems[n] tHandle = iterItems[n]
tItem = self.projTree[tHandle] tItem = self._projTree[tHandle]
n += 1 n += 1
if tItem is None: if tItem is None:
# Technically a bug since treeOrder is built from the # Technically a bug since treeOrder is built from the
# same data as projTree # same data as _projTree
continue continue
elif tItem.itemParent is None: elif tItem.itemParent is None:
# Item is a root, or already been identified as an # Item is a root, or already been identified as an
@@ -1186,7 +1204,7 @@ class NWProject():
def updateWordCounts(self): def updateWordCounts(self):
"""Update the total word count values. """Update the total word count values.
""" """
wcNovel, wcNotes = self.projTree.sumWords() wcNovel, wcNotes = self._projTree.sumWords()
wcTotal = wcNovel + wcNotes wcTotal = wcNovel + wcNotes
if wcTotal != self.currWCount: if wcTotal != self.currWCount:
self.currNovelWC = wcNovel self.currNovelWC = wcNovel
@@ -1202,7 +1220,7 @@ class NWProject():
""" """
self.statusItems.resetCounts() self.statusItems.resetCounts()
self.importItems.resetCounts() self.importItems.resetCounts()
for nwItem in self.projTree: for nwItem in self._projTree:
if nwItem.isNovelLike(): if nwItem.isNovelLike():
self.statusItems.increment(nwItem.itemStatus) self.statusItems.increment(nwItem.itemStatus)
else: else:
@@ -1214,7 +1232,7 @@ class NWProject():
return it. The variable is cast to a string before lookup. If return it. The variable is cast to a string before lookup. If
the word does not exist, it returns itself. the word does not exist, it returns itself.
""" """
return self.langData.get(str(theWord), str(theWord)) return self._langData.get(str(theWord), str(theWord))
## ##
# Internal Functions # Internal Functions
@@ -1246,7 +1264,7 @@ class NWProject():
"""Load the language data for the current project language. """Load the language data for the current project language.
""" """
if self.projLang is None: if self.projLang is None:
self.langData = {} self._langData = {}
return False return False
langFile = os.path.join(self.mainConf.nwLangPath, "project_%s.json" % self.projLang) langFile = os.path.join(self.mainConf.nwLangPath, "project_%s.json" % self.projLang)
@@ -1255,7 +1273,7 @@ class NWProject():
try: try:
with open(langFile, mode="r", encoding="utf-8") as inFile: with open(langFile, mode="r", encoding="utf-8") as inFile:
self.langData = json.load(inFile) self._langData = json.load(inFile)
logger.debug("Loaded project language file: %s", os.path.basename(langFile)) logger.debug("Loaded project language file: %s", os.path.basename(langFile))
except Exception: except Exception:
@@ -1390,7 +1408,7 @@ class NWProject():
logger.warning("Skipping file: %s", fileItem) logger.warning("Skipping file: %s", fileItem)
continue continue
if fHandle in self.projTree: if fHandle in self._projTree:
self.projFiles.append(fHandle) self.projFiles.append(fHandle)
logger.debug("Checking file %s, handle '%s': OK", fileItem, fHandle) logger.debug("Checking file %s, handle '%s': OK", fileItem, fHandle)
else: else:
@@ -1437,10 +1455,10 @@ class NWProject():
if oLayout is None: if oLayout is None:
oLayout = nwItemLayout.NOTE oLayout = nwItemLayout.NOTE
if oParent is None or oParent not in self.projTree: if oParent is None or oParent not in self._projTree:
oParent = self.projTree.findRoot(oClass) oParent = self._projTree.findRoot(oClass)
if oParent is None: if oParent is None:
oParent = self.projTree.findRoot(nwItemClass.NOVEL) oParent = self._projTree.findRoot(nwItemClass.NOVEL)
# If the file still has no parent item, skip it # If the file still has no parent item, skip it
if oParent is None: if oParent is None:
@@ -1452,8 +1470,8 @@ class NWProject():
orphItem.setType(nwItemType.FILE) orphItem.setType(nwItemType.FILE)
orphItem.setClass(oClass) orphItem.setClass(oClass)
orphItem.setLayout(oLayout) orphItem.setLayout(oLayout)
self.projTree.append(oHandle, oParent, orphItem) self._projTree.append(oHandle, oParent, orphItem)
self.projTree.updateItemData(orphItem.itemHandle) self._projTree.updateItemData(orphItem.itemHandle)
if noWhere: if noWhere:
self.theParent.makeAlert(self.tr( self.theParent.makeAlert(self.tr(
+1 -1
View File
@@ -451,7 +451,7 @@ class ToHtml(Tokenizer):
def _formatKeywords(self, tText): def _formatKeywords(self, tText):
"""Apply HTML formatting to keywords. """Apply HTML formatting to keywords.
""" """
isValid, theBits, _ = self.theParent.theIndex.scanThis("@"+tText) isValid, theBits, _ = self.theProject.index.scanThis("@"+tText)
if not isValid or not theBits: if not isValid or not theBits:
return "" return ""
+3 -3
View File
@@ -275,7 +275,7 @@ class Tokenizer(ABC):
def addRootHeading(self, theHandle): def addRootHeading(self, theHandle):
"""Add a heading at the start of a new root folder. """Add a heading at the start of a new root folder.
""" """
if not self.theProject.projTree.checkType(theHandle, nwItemType.ROOT): if not self.theProject.tree.checkType(theHandle, nwItemType.ROOT):
return False return False
if self._isFirst: if self._isFirst:
@@ -284,7 +284,7 @@ class Tokenizer(ABC):
else: else:
textAlign = self.A_PBB | self.A_CENTRE textAlign = self.A_PBB | self.A_CENTRE
theItem = self.theProject.projTree[theHandle] theItem = self.theProject.tree[theHandle]
locNotes = self._localLookup("Notes") locNotes = self._localLookup("Notes")
theTitle = f"{locNotes}: {theItem.itemName}" theTitle = f"{locNotes}: {theItem.itemName}"
self._theTokens = [] self._theTokens = []
@@ -301,7 +301,7 @@ class Tokenizer(ABC):
not set, load it from the file. not set, load it from the file.
""" """
self._theHandle = theHandle self._theHandle = theHandle
self._theItem = self.theProject.projTree[theHandle] self._theItem = self.theProject.tree[theHandle]
if self._theItem is None: if self._theItem is None:
return False return False
+1 -1
View File
@@ -193,7 +193,7 @@ class ToMarkdown(Tokenizer):
def _formatKeywords(self, tText, tStyle): def _formatKeywords(self, tText, tStyle):
"""Apply Markdown formatting to keywords. """Apply Markdown formatting to keywords.
""" """
isValid, theBits, _ = self.theParent.theIndex.scanThis("@"+tText) isValid, theBits, _ = self.theProject.index.scanThis("@"+tText)
if not isValid or not theBits: if not isValid or not theBits:
return "" return ""
+1 -1
View File
@@ -550,7 +550,7 @@ class ToOdt(Tokenizer):
def _formatKeywords(self, tText): def _formatKeywords(self, tText):
"""Apply formatting to keywords. """Apply formatting to keywords.
""" """
isValid, theBits, _ = self.theParent.theIndex.scanThis("@"+tText) isValid, theBits, _ = self.theProject.index.scanThis("@"+tText)
if not isValid or not theBits: if not isValid or not theBits:
return "" return ""
+4 -4
View File
@@ -125,13 +125,13 @@ class GuiDocMerge(QDialog):
), nwAlert.ERROR) ), nwAlert.ERROR)
return False return False
srcItem = self.theProject.projTree[self.sourceItem] srcItem = self.theProject.tree[self.sourceItem]
if srcItem is None: if srcItem is None:
self.theParent.makeAlert(self.tr("Internal error."), nwAlert.ERROR) self.theParent.makeAlert(self.tr("Internal error."), nwAlert.ERROR)
return False return False
nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemParent) nHandle = self.theProject.newFile(srcItem.itemName, srcItem.itemParent)
newItem = self.theProject.projTree[nHandle] newItem = self.theProject.tree[nHandle]
newItem.setStatus(srcItem.itemStatus) newItem.setStatus(srcItem.itemStatus)
newItem.setImport(srcItem.itemImport) newItem.setImport(srcItem.itemImport)
@@ -170,7 +170,7 @@ class GuiDocMerge(QDialog):
if tHandle is None: if tHandle is None:
return False return False
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
if nwItem is None: if nwItem is None:
return False return False
@@ -182,7 +182,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.projTree[sHandle] nwItem = self.theProject.tree[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)
+6 -7
View File
@@ -50,7 +50,6 @@ class GuiDocSplit(QDialog):
self.mainConf = novelwriter.CONFIG self.mainConf = novelwriter.CONFIG
self.theParent = theParent self.theParent = theParent
self.theProject = theParent.theProject self.theProject = theParent.theProject
self.optState = theParent.theProject.optState
self.sourceItem = None self.sourceItem = None
self.sourceText = [] self.sourceText = []
@@ -75,7 +74,7 @@ class GuiDocSplit(QDialog):
self.splitLevel.addItem(self.tr("Split up to Header Level 3 (Scene)"), 3) self.splitLevel.addItem(self.tr("Split up to Header Level 3 (Scene)"), 3)
self.splitLevel.addItem(self.tr("Split up to Header Level 4 (Section)"), 4) self.splitLevel.addItem(self.tr("Split up to Header Level 4 (Section)"), 4)
spIndex = self.splitLevel.findData( spIndex = self.splitLevel.findData(
self.optState.getInt("GuiDocSplit", "spLevel", 3) self.theProject.options.getInt("GuiDocSplit", "spLevel", 3)
) )
if spIndex != -1: if spIndex != -1:
self.splitLevel.setCurrentIndex(spIndex) self.splitLevel.setCurrentIndex(spIndex)
@@ -121,7 +120,7 @@ class GuiDocSplit(QDialog):
), nwAlert.ERROR) ), nwAlert.ERROR)
return False return False
srcItem = self.theProject.projTree[self.sourceItem] srcItem = self.theProject.tree[self.sourceItem]
if srcItem is None: if srcItem is None:
self.theParent.makeAlert(self.tr( self.theParent.makeAlert(self.tr(
"Could not parse source document." "Could not parse source document."
@@ -184,7 +183,7 @@ class GuiDocSplit(QDialog):
wTitle = wTitle.lstrip("#").strip() wTitle = wTitle.lstrip("#").strip()
nHandle = self.theProject.newFile(wTitle, fHandle) nHandle = self.theProject.newFile(wTitle, fHandle)
newItem = self.theProject.projTree[nHandle] newItem = self.theProject.tree[nHandle]
newItem.setStatus(srcItem.itemStatus) newItem.setStatus(srcItem.itemStatus)
newItem.setImport(srcItem.itemImport) newItem.setImport(srcItem.itemImport)
logger.verbose( logger.verbose(
@@ -211,7 +210,7 @@ class GuiDocSplit(QDialog):
def _doClose(self): def _doClose(self):
"""Close the dialog window without doing anything. """Close the dialog window without doing anything.
""" """
self.optState.saveSettings() self.theProject.options.saveSettings()
self.close() self.close()
return return
@@ -232,7 +231,7 @@ class GuiDocSplit(QDialog):
if self.sourceItem is None: if self.sourceItem is None:
return False return False
nwItem = self.theProject.projTree[self.sourceItem] nwItem = self.theProject.tree[self.sourceItem]
if nwItem is None: if nwItem is None:
return False return False
@@ -249,7 +248,7 @@ class GuiDocSplit(QDialog):
return False return False
spLevel = self.splitLevel.currentData() spLevel = self.splitLevel.currentData()
self.optState.setValue("GuiDocSplit", "spLevel", spLevel) self.theProject.options.setValue("GuiDocSplit", "spLevel", spLevel)
logger.debug( logger.debug(
"Scanning document '%s' for headings level <= %d", "Scanning document '%s' for headings level <= %d",
self.sourceItem, spLevel self.sourceItem, spLevel
+1 -1
View File
@@ -55,7 +55,7 @@ class GuiItemEditor(QDialog):
# Build GUI # Build GUI
## ##
self.theItem = self.theProject.projTree[tHandle] self.theItem = self.theProject.tree[tHandle]
if self.theItem is None: if self.theItem is None:
self.close() self.close()
return return
+27 -27
View File
@@ -52,18 +52,18 @@ class GuiProjectDetails(PagedDialog):
self.mainConf = novelwriter.CONFIG self.mainConf = novelwriter.CONFIG
self.theParent = theParent self.theParent = theParent
self.theProject = theParent.theProject self.theProject = theParent.theProject
self.optState = theParent.theProject.optState
self.setWindowTitle(self.tr("Project Details")) self.setWindowTitle(self.tr("Project Details"))
wW = self.mainConf.pxInt(600) wW = self.mainConf.pxInt(600)
wH = self.mainConf.pxInt(400) wH = self.mainConf.pxInt(400)
pOptions = self.theProject.options
self.setMinimumWidth(wW) self.setMinimumWidth(wW)
self.setMinimumHeight(wH) self.setMinimumHeight(wH)
self.resize( self.resize(
self.mainConf.pxInt(self.optState.getInt("GuiProjectDetails", "winWidth", wW)), self.mainConf.pxInt(pOptions.getInt("GuiProjectDetails", "winWidth", wW)),
self.mainConf.pxInt(self.optState.getInt("GuiProjectDetails", "winHeight", wH)) self.mainConf.pxInt(pOptions.getInt("GuiProjectDetails", "winHeight", wH))
) )
self.tabMain = GuiProjectDetailsMain(self.theParent, self.theProject) self.tabMain = GuiProjectDetailsMain(self.theParent, self.theProject)
@@ -120,16 +120,17 @@ class GuiProjectDetails(PagedDialog):
countFrom = self.tabContents.poValue.value() countFrom = self.tabContents.poValue.value()
clearDouble = self.tabContents.dblValue.isChecked() clearDouble = self.tabContents.dblValue.isChecked()
self.optState.setValue("GuiProjectDetails", "winWidth", winWidth) pOptions = self.theProject.options
self.optState.setValue("GuiProjectDetails", "winHeight", winHeight) pOptions.setValue("GuiProjectDetails", "winWidth", winWidth)
self.optState.setValue("GuiProjectDetails", "widthCol0", widthCol0) pOptions.setValue("GuiProjectDetails", "winHeight", winHeight)
self.optState.setValue("GuiProjectDetails", "widthCol1", widthCol1) pOptions.setValue("GuiProjectDetails", "widthCol0", widthCol0)
self.optState.setValue("GuiProjectDetails", "widthCol2", widthCol2) pOptions.setValue("GuiProjectDetails", "widthCol1", widthCol1)
self.optState.setValue("GuiProjectDetails", "widthCol3", widthCol3) pOptions.setValue("GuiProjectDetails", "widthCol2", widthCol2)
self.optState.setValue("GuiProjectDetails", "widthCol4", widthCol4) pOptions.setValue("GuiProjectDetails", "widthCol3", widthCol3)
self.optState.setValue("GuiProjectDetails", "wordsPerPage", wordsPerPage) pOptions.setValue("GuiProjectDetails", "widthCol4", widthCol4)
self.optState.setValue("GuiProjectDetails", "countFrom", countFrom) pOptions.setValue("GuiProjectDetails", "wordsPerPage", wordsPerPage)
self.optState.setValue("GuiProjectDetails", "clearDouble", clearDouble) pOptions.setValue("GuiProjectDetails", "countFrom", countFrom)
pOptions.setValue("GuiProjectDetails", "clearDouble", clearDouble)
return return
@@ -145,7 +146,6 @@ class GuiProjectDetailsMain(QWidget):
self.theParent = theParent self.theParent = theParent
self.theProject = theProject self.theProject = theProject
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theIndex = theParent.theIndex
fPx = self.theTheme.fontPixelSize fPx = self.theTheme.fontPixelSize
fPt = self.theTheme.fontPointSize fPt = self.theTheme.fontPointSize
@@ -245,8 +245,9 @@ class GuiProjectDetailsMain(QWidget):
def updateValues(self): def updateValues(self):
"""Set all the values. """Set all the values.
""" """
hCounts = self.theIndex.getNovelTitleCounts() pIndex = self.theProject.index
nwCount = self.theIndex.getNovelWordCount() hCounts = pIndex.getNovelTitleCounts()
nwCount = pIndex.getNovelWordCount()
edTime = self.theProject.getCurrentEditTime() edTime = self.theProject.getCurrentEditTime()
self.wordCountVal.setText(f"{nwCount:n}") self.wordCountVal.setText(f"{nwCount:n}")
@@ -277,8 +278,6 @@ class GuiProjectDetailsContents(QWidget):
self.theParent = theParent self.theParent = theParent
self.theProject = theProject self.theProject = theProject
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theIndex = theParent.theIndex
self.optState = theProject.optState
# Internal # Internal
self._theToC = [] self._theToC = []
@@ -286,6 +285,7 @@ class GuiProjectDetailsContents(QWidget):
iPx = self.theTheme.baseIconSize iPx = self.theTheme.baseIconSize
hPx = self.mainConf.pxInt(12) hPx = self.mainConf.pxInt(12)
vPx = self.mainConf.pxInt(4) vPx = self.mainConf.pxInt(4)
pOptions = self.theProject.options
# Contents Tree # Contents Tree
# ============= # =============
@@ -314,11 +314,11 @@ class GuiProjectDetailsContents(QWidget):
treeHeader.setStretchLastSection(True) treeHeader.setStretchLastSection(True)
treeHeader.setMinimumSectionSize(hPx) treeHeader.setMinimumSectionSize(hPx)
wCol0 = self.mainConf.pxInt(self.optState.getInt("GuiProjectDetails", "widthCol0", 200)) wCol0 = self.mainConf.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol0", 200))
wCol1 = self.mainConf.pxInt(self.optState.getInt("GuiProjectDetails", "widthCol1", 60)) wCol1 = self.mainConf.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol1", 60))
wCol2 = self.mainConf.pxInt(self.optState.getInt("GuiProjectDetails", "widthCol2", 60)) wCol2 = self.mainConf.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol2", 60))
wCol3 = self.mainConf.pxInt(self.optState.getInt("GuiProjectDetails", "widthCol3", 60)) wCol3 = self.mainConf.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol3", 60))
wCol4 = self.mainConf.pxInt(self.optState.getInt("GuiProjectDetails", "widthCol4", 90)) wCol4 = self.mainConf.pxInt(pOptions.getInt("GuiProjectDetails", "widthCol4", 90))
self.tocTree.setColumnWidth(0, wCol0) self.tocTree.setColumnWidth(0, wCol0)
self.tocTree.setColumnWidth(1, wCol1) self.tocTree.setColumnWidth(1, wCol1)
@@ -330,9 +330,9 @@ class GuiProjectDetailsContents(QWidget):
# Options # Options
# ======= # =======
wordsPerPage = self.optState.getInt("GuiProjectDetails", "wordsPerPage", 350) wordsPerPage = pOptions.getInt("GuiProjectDetails", "wordsPerPage", 350)
countFrom = self.optState.getInt("GuiProjectDetails", "countFrom", 1) countFrom = pOptions.getInt("GuiProjectDetails", "countFrom", 1)
clearDouble = self.optState.getInt("GuiProjectDetails", "clearDouble", True) clearDouble = pOptions.getInt("GuiProjectDetails", "clearDouble", True)
wordsHelp = ( wordsHelp = (
self.tr("Typical word count for a 5 by 8 inch book page with 11 pt font is 350.") self.tr("Typical word count for a 5 by 8 inch book page with 11 pt font is 350.")
@@ -424,7 +424,7 @@ class GuiProjectDetailsContents(QWidget):
"""Extract the data for the tree. """Extract the data for the tree.
""" """
self._theToC = [] self._theToC = []
self._theToC = self.theIndex.getTableOfContents(2) self._theToC = self.theProject.index.getTableOfContents(2)
self._theToC.append(("", 0, self.tr("END"), 0)) self._theToC.append(("", 0, self.tr("END"), 0))
return return
+11 -12
View File
@@ -52,19 +52,19 @@ class GuiProjectSettings(PagedDialog):
self.mainConf = novelwriter.CONFIG self.mainConf = novelwriter.CONFIG
self.theParent = theParent self.theParent = theParent
self.theProject = theParent.theProject self.theProject = theParent.theProject
self.optState = theParent.theProject.optState
self.theProject.countStatus() self.theProject.countStatus()
self.setWindowTitle(self.tr("Project Settings")) self.setWindowTitle(self.tr("Project Settings"))
wW = self.mainConf.pxInt(570) wW = self.mainConf.pxInt(570)
wH = self.mainConf.pxInt(375) wH = self.mainConf.pxInt(375)
pOptions = self.theProject.options
self.setMinimumWidth(wW) self.setMinimumWidth(wW)
self.setMinimumHeight(wH) self.setMinimumHeight(wH)
self.resize( self.resize(
self.mainConf.pxInt(self.optState.getInt("GuiProjectSettings", "winWidth", wW)), self.mainConf.pxInt(pOptions.getInt("GuiProjectSettings", "winWidth", wW)),
self.mainConf.pxInt(self.optState.getInt("GuiProjectSettings", "winHeight", wH)) self.mainConf.pxInt(pOptions.getInt("GuiProjectSettings", "winHeight", wH))
) )
self.tabMain = GuiProjectEditMain(self.theParent, self.theProject) self.tabMain = GuiProjectEditMain(self.theParent, self.theProject)
@@ -152,11 +152,12 @@ class GuiProjectSettings(PagedDialog):
statusColW = self.mainConf.rpxInt(self.tabStatus.listBox.columnWidth(0)) statusColW = self.mainConf.rpxInt(self.tabStatus.listBox.columnWidth(0))
importColW = self.mainConf.rpxInt(self.tabImport.listBox.columnWidth(0)) importColW = self.mainConf.rpxInt(self.tabImport.listBox.columnWidth(0))
self.optState.setValue("GuiProjectSettings", "winWidth", winWidth) pOptions = self.theProject.options
self.optState.setValue("GuiProjectSettings", "winHeight", winHeight) pOptions.setValue("GuiProjectSettings", "winWidth", winWidth)
self.optState.setValue("GuiProjectSettings", "replaceColW", replaceColW) pOptions.setValue("GuiProjectSettings", "winHeight", winHeight)
self.optState.setValue("GuiProjectSettings", "statusColW", statusColW) pOptions.setValue("GuiProjectSettings", "replaceColW", replaceColW)
self.optState.setValue("GuiProjectSettings", "importColW", importColW) pOptions.setValue("GuiProjectSettings", "statusColW", statusColW)
pOptions.setValue("GuiProjectSettings", "importColW", importColW)
return return
@@ -261,7 +262,6 @@ class GuiProjectEditStatus(QWidget):
self.mainConf = novelwriter.CONFIG self.mainConf = novelwriter.CONFIG
self.theParent = theParent self.theParent = theParent
self.theProject = theProject self.theProject = theProject
self.optState = theProject.optState
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
if isStatus: if isStatus:
@@ -274,7 +274,7 @@ class GuiProjectEditStatus(QWidget):
colSetting = "importColW" colSetting = "importColW"
wCol0 = self.mainConf.pxInt( wCol0 = self.mainConf.pxInt(
self.optState.getInt("GuiProjectSettings", colSetting, 130) self.theProject.options.getInt("GuiProjectSettings", colSetting, 130)
) )
self.colDeleted = [] self.colDeleted = []
@@ -534,11 +534,10 @@ class GuiProjectEditReplace(QWidget):
self.theParent = theParent self.theParent = theParent
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theProject = theProject self.theProject = theProject
self.optState = theProject.optState
self.arChanged = False self.arChanged = False
wCol0 = self.mainConf.pxInt( wCol0 = self.mainConf.pxInt(
self.optState.getInt("GuiProjectSettings", "replaceColW", 130) self.theProject.options.getInt("GuiProjectSettings", "replaceColW", 130)
) )
pageLabel = self.tr("Text Replace List for Preview and Export") pageLabel = self.tr("Text Replace List for Preview and Export")
+6 -5
View File
@@ -52,19 +52,19 @@ class GuiWordList(QDialog):
self.theParent = theParent self.theParent = theParent
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theProject = theParent.theProject self.theProject = theParent.theProject
self.optState = theParent.theProject.optState
self.setWindowTitle(self.tr("Project Word List")) self.setWindowTitle(self.tr("Project Word List"))
mS = self.mainConf.pxInt(250) mS = self.mainConf.pxInt(250)
wW = self.mainConf.pxInt(320) wW = self.mainConf.pxInt(320)
wH = self.mainConf.pxInt(340) wH = self.mainConf.pxInt(340)
pOptions = self.theProject.options
self.setMinimumWidth(mS) self.setMinimumWidth(mS)
self.setMinimumHeight(mS) self.setMinimumHeight(mS)
self.resize( self.resize(
self.mainConf.pxInt(self.optState.getInt("GuiWordList", "winWidth", wW)), self.mainConf.pxInt(pOptions.getInt("GuiWordList", "winWidth", wW)),
self.mainConf.pxInt(self.optState.getInt("GuiWordList", "winHeight", wH)) self.mainConf.pxInt(pOptions.getInt("GuiWordList", "winHeight", wH))
) )
# Main Widgets # Main Widgets
@@ -207,8 +207,9 @@ class GuiWordList(QDialog):
winWidth = self.mainConf.rpxInt(self.width()) winWidth = self.mainConf.rpxInt(self.width())
winHeight = self.mainConf.rpxInt(self.height()) winHeight = self.mainConf.rpxInt(self.height())
self.optState.setValue("GuiWordList", "winWidth", winWidth) pOptions = self.theProject.options
self.optState.setValue("GuiWordList", "winHeight", winHeight) pOptions.setValue("GuiWordList", "winWidth", winWidth)
pOptions.setValue("GuiWordList", "winHeight", winHeight)
return return
+5 -5
View File
@@ -409,10 +409,10 @@ class PagedDialog(QDialog):
return return
def addTab(self, tabWidget, tabLabel): def addTab(self, widget, label):
"""Forwards the adding of tabs to the QTabWidget. """Forwards the adding of tabs to the QTabWidget.
""" """
self._tabBox.addTab(tabWidget, tabLabel) self._tabBox.addTab(widget, label)
return return
def addControls(self, buttonBar): def addControls(self, buttonBar):
@@ -431,15 +431,15 @@ class VerticalTabBar(QTabBar):
self._mW = novelwriter.CONFIG.pxInt(150) self._mW = novelwriter.CONFIG.pxInt(150)
return return
def tabSizeHint(self, theIndex): def tabSizeHint(self, index):
"""Returns a transposed size hint for the rotated bar. """Returns a transposed size hint for the rotated bar.
""" """
tSize = QTabBar.tabSizeHint(self, theIndex) tSize = QTabBar.tabSizeHint(self, index)
tSize.transpose() tSize.transpose()
tSize.setWidth(min(tSize.width(), self._mW)) tSize.setWidth(min(tSize.width(), self._mW))
return tSize return tSize
def paintEvent(self, theEvent): def paintEvent(self, event):
"""Custom implementation of the label painter that rotates the """Custom implementation of the label painter that rotates the
label 90 degrees. label 90 degrees.
""" """
+10 -12
View File
@@ -81,7 +81,6 @@ class GuiDocEditor(QTextEdit):
self.mainConf = novelwriter.CONFIG self.mainConf = novelwriter.CONFIG
self.theParent = theParent self.theParent = theParent
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theIndex = theParent.theIndex
self.theProject = theParent.theProject self.theProject = theParent.theProject
self._nwDocument = None self._nwDocument = None
@@ -403,7 +402,7 @@ class GuiDocEditor(QTextEdit):
self.document().rootFrame().setFrameFormat(docFrame) self.document().rootFrame().setFrameFormat(docFrame)
self.docFooter.updateLineCount() self.docFooter.updateLineCount()
self._docHeaders = self.theIndex.getHandleHeaders(self._docHandle) self._docHeaders = self.theProject.index.getHandleHeaders(self._docHandle)
qApp.processEvents() qApp.processEvents()
self.document().clearUndoRedoStacks() self.document().clearUndoRedoStacks()
@@ -508,9 +507,9 @@ class GuiDocEditor(QTextEdit):
self.setDocumentChanged(False) self.setDocumentChanged(False)
oldHeader = self.theIndex.getHandleHeaderLevel(tHandle) oldHeader = self.theProject.index.getHandleHeaderLevel(tHandle)
self.theIndex.scanText(tHandle, docText) self.theProject.index.scanText(tHandle, docText)
newHeader = self.theIndex.getHandleHeaderLevel(tHandle) newHeader = self.theProject.index.getHandleHeaderLevel(tHandle)
if self._updateHeaders(checkLevel=True): if self._updateHeaders(checkLevel=True):
self.theParent.requestNovelTreeRefresh() self.theParent.requestNovelTreeRefresh()
@@ -2005,7 +2004,7 @@ class GuiDocEditor(QTextEdit):
if self._docHandle is None: if self._docHandle is None:
return False return False
newHeaders = self.theIndex.getHandleHeaders(self._docHandle) newHeaders = self.theProject.index.getHandleHeaders(self._docHandle)
if checkPos: if checkPos:
newPos = [x[0] for x in newHeaders] newPos = [x[0] for x in newHeaders]
oldPos = [x[0] for x in self._docHeaders] oldPos = [x[0] for x in self._docHeaders]
@@ -2704,15 +2703,15 @@ class GuiDocEditHeader(QWidget):
if self.mainConf.showFullPath: if self.mainConf.showFullPath:
tTitle = [] tTitle = []
tTree = self.theProject.projTree.getItemPath(tHandle) tTree = self.theProject.tree.getItemPath(tHandle)
for aHandle in reversed(tTree): for aHandle in reversed(tTree):
nwItem = self.theProject.projTree[aHandle] nwItem = self.theProject.tree[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.theTitle.setText(sSep.join(tTitle)) self.theTitle.setText(sSep.join(tTitle))
else: else:
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
if nwItem is None: if nwItem is None:
return False return False
self.theTitle.setText(nwItem.itemName) self.theTitle.setText(nwItem.itemName)
@@ -2798,7 +2797,6 @@ class GuiDocEditFooter(QWidget):
self.theParent = docEditor.theParent self.theParent = docEditor.theParent
self.theProject = docEditor.theProject self.theProject = docEditor.theProject
self.theTheme = docEditor.theTheme self.theTheme = docEditor.theTheme
self.optState = docEditor.theProject.optState
self._theItem = None self._theItem = None
self._docHandle = None self._docHandle = None
@@ -2921,7 +2919,7 @@ class GuiDocEditFooter(QWidget):
logger.verbose("No handle set, so clearing the editor footer") logger.verbose("No handle set, so clearing the editor footer")
self._theItem = None self._theItem = None
else: else:
self._theItem = self.theProject.projTree[self._docHandle] self._theItem = self.theProject.tree[self._docHandle]
self.setHasSelection(False) self.setHasSelection(False)
self.updateInfo() self.updateInfo()
@@ -2945,7 +2943,7 @@ class GuiDocEditFooter(QWidget):
else: else:
theStatus, theIcon = self._theItem.getImportStatus() theStatus, theIcon = self._theItem.getImportStatus()
sIcon = theIcon.pixmap(self.sPx, self.sPx) sIcon = theIcon.pixmap(self.sPx, self.sPx)
hLevel = self.theParent.theIndex.getHandleHeaderLevel(self._docHandle) hLevel = self.theProject.index.getHandleHeaderLevel(self._docHandle)
sText = f"{theStatus} / {self._theItem.describeMe(hLevel)}" sText = f"{theStatus} / {self._theItem.describeMe(hLevel)}"
self.statusIcon.setPixmap(sIcon) self.statusIcon.setPixmap(sIcon)
+5 -4
View File
@@ -55,7 +55,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.spEnchant = spEnchant self.spEnchant = spEnchant
self.theParent = theParent self.theParent = theParent
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theIndex = theParent.theIndex self.theProject = theParent.theProject
self.theHandle = None self.theHandle = None
self.spellCheck = False self.spellCheck = False
self.spellRx = None self.spellRx = None
@@ -287,9 +287,10 @@ class GuiDocHighlighter(QSyntaxHighlighter):
if theText.startswith("@"): # Keywords and commands if theText.startswith("@"): # Keywords and commands
self.setCurrentBlockState(self.BLOCK_META) self.setCurrentBlockState(self.BLOCK_META)
tItem = self.theParent.theProject.projTree[self.theHandle] pIndex = self.theProject.index
isValid, theBits, thePos = self.theIndex.scanThis(theText) tItem = self.theParent.theProject.tree[self.theHandle]
isGood = self.theIndex.checkThese(theBits, tItem) isValid, theBits, thePos = pIndex.scanThis(theText)
isGood = pIndex.checkThese(theBits, tItem)
if isValid: if isValid:
for n, theBit in enumerate(theBits): for n, theBit in enumerate(theBits):
xPos = thePos[n] xPos = thePos[n]
+6 -6
View File
@@ -164,7 +164,7 @@ class GuiDocViewer(QTextBrowser):
def loadText(self, tHandle, updateHistory=True): def loadText(self, tHandle, updateHistory=True):
"""Load text into the viewer from an item handle. """Load text into the viewer from an item handle.
""" """
if not self.theProject.projTree.checkType(tHandle, nwItemType.FILE): if not self.theProject.tree.checkType(tHandle, nwItemType.FILE):
logger.warning("Item not found") logger.warning("Item not found")
return False return False
@@ -843,15 +843,15 @@ class GuiDocViewHeader(QWidget):
if self.mainConf.showFullPath: if self.mainConf.showFullPath:
tTitle = [] tTitle = []
tTree = self.theProject.projTree.getItemPath(tHandle) tTree = self.theProject.tree.getItemPath(tHandle)
for aHandle in reversed(tTree): for aHandle in reversed(tTree):
nwItem = self.theProject.projTree[aHandle] nwItem = self.theProject.tree[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.theTitle.setText(sSep.join(tTitle)) self.theTitle.setText(sSep.join(tTitle))
else: else:
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
if nwItem is None: if nwItem is None:
return False return False
self.theTitle.setText(nwItem.itemName) self.theTitle.setText(nwItem.itemName)
@@ -1179,10 +1179,10 @@ class GuiDocViewDetails(QScrollArea):
if self.theParent.docViewer.stickyRef: if self.theParent.docViewer.stickyRef:
return return
theRefs = self.theParent.theIndex.getBackReferenceList(tHandle) theRefs = self.theProject.index.getBackReferenceList(tHandle)
theList = [] theList = []
for tHandle in theRefs: for tHandle in theRefs:
tItem = self.theProject.projTree[tHandle] tItem = self.theProject.tree[tHandle]
if tItem is not None: if tItem is not None:
theList.append("<a href='%s#%s' %s>%s</a>" % ( theList.append("<a href='%s#%s' %s>%s</a>" % (
tHandle, theRefs[tHandle], self.linkStyle, tItem.itemName tHandle, theRefs[tHandle], self.linkStyle, tItem.itemName
+2 -2
View File
@@ -227,7 +227,7 @@ class GuiItemDetails(QWidget):
self.clearDetails() self.clearDetails()
return return
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
if nwItem is None: if nwItem is None:
self.clearDetails() self.clearDetails()
return return
@@ -269,7 +269,7 @@ class GuiItemDetails(QWidget):
# Layout # Layout
# ====== # ======
hLevel = self.theParent.theIndex.getHandleHeaderLevel(tHandle) hLevel = self.theProject.index.getHandleHeaderLevel(tHandle)
usageIcon = self.theTheme.getItemIcon( usageIcon = self.theTheme.getItemIcon(
nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel
) )
+8 -9
View File
@@ -54,7 +54,6 @@ class GuiNovelTree(QTreeWidget):
self.theParent = theParent self.theParent = theParent
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theProject = theParent.theProject self.theProject = theParent.theProject
self.theIndex = theParent.theIndex
# Internal Variables # Internal Variables
self._treeMap = {} self._treeMap = {}
@@ -137,7 +136,7 @@ class GuiNovelTree(QTreeWidget):
""" """
logger.verbose("Requesting refresh of the novel tree") logger.verbose("Requesting refresh of the novel tree")
treeChanged = self.theParent.treeView.changedSince(self._lastBuild) treeChanged = self.theParent.treeView.changedSince(self._lastBuild)
indexChanged = self.theIndex.novelChangedSince(self._lastBuild) indexChanged = self.theProject.index.novelChangedSince(self._lastBuild)
if not (treeChanged or indexChanged or overRide): if not (treeChanged or indexChanged or overRide):
logger.verbose("No changes have been made to the novel index") logger.verbose("No changes have been made to the novel index")
return return
@@ -158,7 +157,7 @@ class GuiNovelTree(QTreeWidget):
def updateWordCounts(self, tHandle): def updateWordCounts(self, tHandle):
"""Update the word count for a given handle. """Update the word count for a given handle.
""" """
tHeaders = self.theIndex.getHandleWordCounts(tHandle) tHeaders = self.theProject.index.getHandleWordCounts(tHandle)
for titleKey, wCount in tHeaders: for titleKey, wCount in tHeaders:
if titleKey in self._treeMap: if titleKey in self._treeMap:
self._treeMap[titleKey].setText(self.C_WORDS, f"{wCount:n}") self._treeMap[titleKey].setText(self.C_WORDS, f"{wCount:n}")
@@ -252,12 +251,12 @@ class GuiNovelTree(QTreeWidget):
currChapter = None currChapter = None
currScene = None currScene = None
for tKey, tHandle, sTitle, novIdx in self.theIndex.novelStructure(skipExcluded=True): for tKey, tHandle, sTitle, novIdx in self.theProject.index.novelStructure(skipExcl=True):
tItem = self._createTreeItem(tHandle, sTitle, tKey, novIdx) tItem = self._createTreeItem(tHandle, sTitle, tKey, novIdx)
self._treeMap[tKey] = tItem self._treeMap[tKey] = tItem
tLevel = novIdx["level"] tLevel = novIdx.level
if tLevel == "H1": if tLevel == "H1":
self.addTopLevelItem(tItem) self.addTopLevelItem(tItem)
currTitle = tItem currTitle = tItem
@@ -304,18 +303,18 @@ class GuiNovelTree(QTreeWidget):
"""Populate a tree item with all the column values. """Populate a tree item with all the column values.
""" """
newItem = QTreeWidgetItem() newItem = QTreeWidgetItem()
hIcon = "doc_%s" % novIdx["level"].lower() hIcon = "doc_%s" % novIdx.level.lower()
theData = (tHandle, sTitle[1:].lstrip("0"), titleKey) theData = (tHandle, sTitle[1:].lstrip("0"), titleKey)
wC = int(novIdx["wCount"]) wC = int(novIdx.wordCount)
newItem.setText(self.C_TITLE, novIdx["title"]) newItem.setText(self.C_TITLE, novIdx.title)
newItem.setData(self.C_TITLE, Qt.UserRole, theData) newItem.setData(self.C_TITLE, Qt.UserRole, theData)
newItem.setIcon(self.C_TITLE, self.theTheme.getIcon(hIcon)) newItem.setIcon(self.C_TITLE, self.theTheme.getIcon(hIcon))
newItem.setText(self.C_WORDS, f"{wC:n}") newItem.setText(self.C_WORDS, f"{wC:n}")
newItem.setTextAlignment(self.C_WORDS, Qt.AlignRight) newItem.setTextAlignment(self.C_WORDS, Qt.AlignRight)
theRefs = self.theIndex.getReferences(tHandle, sTitle) theRefs = self.theProject.index.getReferences(tHandle, sTitle)
newItem.setText(self.C_POV, ", ".join(theRefs[nwKeyWords.POV_KEY])) newItem.setText(self.C_POV, ", ".join(theRefs[nwKeyWords.POV_KEY]))
return newItem return newItem
+36 -36
View File
@@ -227,7 +227,7 @@ class GuiOutlineToolBar(QToolBar):
"""Fill the novel combo box. """Fill the novel combo box.
""" """
self.novelValue.clear() self.novelValue.clear()
for tHandle, nwItem in self.theProject.projTree.novelRoots().items(): for tHandle, nwItem in self.theProject.tree.novelRoots().items():
self.novelValue.addItem( self.novelValue.addItem(
self.theTheme.getIcon(nwLabels.CLASS_ICON[nwItem.itemClass]), self.theTheme.getIcon(nwLabels.CLASS_ICON[nwItem.itemClass]),
nwItem.itemName, tHandle nwItem.itemName, tHandle
@@ -309,8 +309,6 @@ class GuiOutlineView(QTreeWidget):
self.theParent = theOutline.theParent self.theParent = theOutline.theParent
self.theProject = theOutline.theParent.theProject self.theProject = theOutline.theParent.theProject
self.theTheme = theOutline.theParent.theTheme self.theTheme = theOutline.theParent.theTheme
self.theIndex = theOutline.theParent.theIndex
self.optState = theOutline.theParent.theProject.optState
self.setFrameStyle(QFrame.NoFrame) self.setFrameStyle(QFrame.NoFrame)
self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setSelectionBehavior(QAbstractItemView.SelectRows)
@@ -410,7 +408,7 @@ class GuiOutlineView(QTreeWidget):
# If the novel index or novel tree has changed since the tree # If the novel index or novel tree has changed since the tree
# was last built, we rebuild the tree from the updated index. # was last built, we rebuild the tree from the updated index.
indexChanged = self.theIndex.novelChangedSince(self._lastBuild) indexChanged = self.theProject.index.novelChangedSince(self._lastBuild)
doBuild = (novelChanged or indexChanged) and self.theProject.autoOutline doBuild = (novelChanged or indexChanged) and self.theProject.autoOutline
if doBuild or overRide: if doBuild or overRide:
logger.debug("Rebuilding Project Outline") logger.debug("Rebuilding Project Outline")
@@ -495,10 +493,12 @@ class GuiOutlineView(QTreeWidget):
"""Load the state of the main tree header, that is, column order """Load the state of the main tree header, that is, column order
and column width. and column width.
""" """
pOptions = self.theProject.options
# Load whatever we saved last time, regardless of wether it # Load whatever we saved last time, regardless of wether it
# contains the correct names or number of columns. The names # contains the correct names or number of columns. The names
# must be valid though. # must be valid though.
tempOrder = self.optState.getValue("GuiOutline", "headerOrder", []) tempOrder = pOptions.getValue("GuiOutline", "headerOrder", [])
treeOrder = [] treeOrder = []
for hName in tempOrder: for hName in tempOrder:
try: try:
@@ -521,14 +521,14 @@ class GuiOutlineView(QTreeWidget):
# We load whatever column widths and hidden states we find in # We load whatever column widths and hidden states we find in
# the file, and leave the rest in their default state. # the file, and leave the rest in their default state.
tmpWidth = self.optState.getValue("GuiOutline", "columnWidth", {}) tmpWidth = pOptions.getValue("GuiOutline", "columnWidth", {})
for hName in tmpWidth: for hName in tmpWidth:
try: try:
self._colWidth[nwOutline[hName]] = self.mainConf.pxInt(tmpWidth[hName]) self._colWidth[nwOutline[hName]] = self.mainConf.pxInt(tmpWidth[hName])
except Exception: except Exception:
logger.warning("Ignored unknown outline column '%s'", str(hName)) logger.warning("Ignored unknown outline column '%s'", str(hName))
tmpHidden = self.optState.getValue("GuiOutline", "columnHidden", {}) tmpHidden = pOptions.getValue("GuiOutline", "columnHidden", {})
for hName in tmpHidden: for hName in tmpHidden:
try: try:
self._colHidden[nwOutline[hName]] = tmpHidden[hName] self._colHidden[nwOutline[hName]] = tmpHidden[hName]
@@ -569,10 +569,11 @@ class GuiOutlineView(QTreeWidget):
if not logHidden and logWidth > 0: if not logHidden and logWidth > 0:
colWidth[hName] = logWidth colWidth[hName] = logWidth
self.optState.setValue("GuiOutline", "headerOrder", treeOrder) pOptions = self.theProject.options
self.optState.setValue("GuiOutline", "columnWidth", colWidth) pOptions.setValue("GuiOutline", "headerOrder", treeOrder)
self.optState.setValue("GuiOutline", "columnHidden", colHidden) pOptions.setValue("GuiOutline", "columnWidth", colWidth)
self.optState.saveSettings() pOptions.setValue("GuiOutline", "columnHidden", colHidden)
pOptions.saveSettings()
return return
@@ -609,11 +610,11 @@ class GuiOutlineView(QTreeWidget):
currChapter = None currChapter = None
currScene = None currScene = None
for tKey, tHandle, sTitle, novIdx in self.theIndex.novelStructure(skipExcluded=True): for _, tHandle, sTitle, novIdx in self.theProject.index.novelStructure(skipExcl=True):
tItem = self._createTreeItem(tHandle, sTitle, novIdx) tItem = self._createTreeItem(tHandle, sTitle, novIdx)
tLevel = novIdx["level"] tLevel = novIdx.level
if tLevel == "H1": if tLevel == "H1":
self.addTopLevelItem(tItem) self.addTopLevelItem(tItem)
currTitle = tItem currTitle = tItem
@@ -659,26 +660,26 @@ class GuiOutlineView(QTreeWidget):
def _createTreeItem(self, tHandle, sTitle, novIdx): def _createTreeItem(self, tHandle, sTitle, novIdx):
"""Populate a tree item with all the column values. """Populate a tree item with all the column values.
""" """
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
newItem = QTreeWidgetItem() newItem = QTreeWidgetItem()
hIcon = "doc_%s" % novIdx["level"].lower() hIcon = "doc_%s" % novIdx.level.lower()
hLevel = self.theIndex.getHandleHeaderLevel(tHandle) hLevel = self.theProject.index.getHandleHeaderLevel(tHandle)
dIcon = self.theTheme.getItemIcon(nwItemType.FILE, None, nwItemLayout.DOCUMENT, hLevel) dIcon = self.theTheme.getItemIcon(nwItemType.FILE, None, nwItemLayout.DOCUMENT, hLevel)
cC = int(novIdx["cCount"]) cC = int(novIdx.charCount)
wC = int(novIdx["wCount"]) wC = int(novIdx.wordCount)
pC = int(novIdx["pCount"]) pC = int(novIdx.paraCount)
newItem.setText(self._colIdx[nwOutline.TITLE], novIdx["title"]) newItem.setText(self._colIdx[nwOutline.TITLE], novIdx.title)
newItem.setData(self._colIdx[nwOutline.TITLE], Qt.UserRole, tHandle) newItem.setData(self._colIdx[nwOutline.TITLE], Qt.UserRole, tHandle)
newItem.setIcon(self._colIdx[nwOutline.TITLE], self.theTheme.getIcon(hIcon)) newItem.setIcon(self._colIdx[nwOutline.TITLE], self.theTheme.getIcon(hIcon))
newItem.setText(self._colIdx[nwOutline.LEVEL], novIdx["level"]) newItem.setText(self._colIdx[nwOutline.LEVEL], novIdx.level)
newItem.setText(self._colIdx[nwOutline.LABEL], nwItem.itemName) newItem.setText(self._colIdx[nwOutline.LABEL], nwItem.itemName)
newItem.setIcon(self._colIdx[nwOutline.LABEL], dIcon) newItem.setIcon(self._colIdx[nwOutline.LABEL], dIcon)
newItem.setText(self._colIdx[nwOutline.LINE], sTitle[1:].lstrip("0")) newItem.setText(self._colIdx[nwOutline.LINE], sTitle[1:].lstrip("0"))
newItem.setData(self._colIdx[nwOutline.LINE], Qt.UserRole, sTitle) newItem.setData(self._colIdx[nwOutline.LINE], Qt.UserRole, sTitle)
newItem.setText(self._colIdx[nwOutline.SYNOP], novIdx["synopsis"]) newItem.setText(self._colIdx[nwOutline.SYNOP], novIdx.synopsis)
newItem.setText(self._colIdx[nwOutline.CCOUNT], f"{cC:n}") newItem.setText(self._colIdx[nwOutline.CCOUNT], f"{cC:n}")
newItem.setText(self._colIdx[nwOutline.WCOUNT], f"{wC:n}") newItem.setText(self._colIdx[nwOutline.WCOUNT], f"{wC:n}")
newItem.setText(self._colIdx[nwOutline.PCOUNT], f"{pC:n}") newItem.setText(self._colIdx[nwOutline.PCOUNT], f"{pC:n}")
@@ -686,7 +687,7 @@ class GuiOutlineView(QTreeWidget):
newItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignRight) newItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignRight)
newItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignRight) newItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignRight)
theRefs = self.theIndex.getReferences(tHandle, sTitle) theRefs = self.theProject.index.getReferences(tHandle, sTitle)
newItem.setText(self._colIdx[nwOutline.POV], ", ".join(theRefs[nwKeyWords.POV_KEY])) newItem.setText(self._colIdx[nwOutline.POV], ", ".join(theRefs[nwKeyWords.POV_KEY]))
newItem.setText(self._colIdx[nwOutline.FOCUS], ", ".join(theRefs[nwKeyWords.FOCUS_KEY])) newItem.setText(self._colIdx[nwOutline.FOCUS], ", ".join(theRefs[nwKeyWords.FOCUS_KEY]))
newItem.setText(self._colIdx[nwOutline.CHAR], ", ".join(theRefs[nwKeyWords.CHAR_KEY])) newItem.setText(self._colIdx[nwOutline.CHAR], ", ".join(theRefs[nwKeyWords.CHAR_KEY]))
@@ -767,8 +768,6 @@ class GuiOutlineDetails(QScrollArea):
self.theParent = theOutline.theParent self.theParent = theOutline.theParent
self.theProject = theOutline.theParent.theProject self.theProject = theOutline.theParent.theProject
self.theTheme = theOutline.theParent.theTheme self.theTheme = theOutline.theParent.theTheme
self.theIndex = theOutline.theParent.theIndex
self.optState = theOutline.theParent.theProject.optState
# Sizes # Sizes
minTitle = 30*self.theTheme.textNWidth minTitle = 30*self.theTheme.textNWidth
@@ -1003,32 +1002,33 @@ class GuiOutlineDetails(QScrollArea):
"""Update the content of the tree with the given handle and line """Update the content of the tree with the given handle and line
number pointing to a header. number pointing to a header.
""" """
nwItem = self.theProject.projTree[tHandle] pIndex = self.theProject.index
novIdx = self.theIndex.getNovelData(tHandle, sTitle) nwItem = self.theProject.tree[tHandle]
theRefs = self.theIndex.getReferences(tHandle, sTitle) novIdx = pIndex.getNovelData(tHandle, sTitle)
theRefs = pIndex.getReferences(tHandle, sTitle)
if nwItem is None or novIdx is None: if nwItem is None or novIdx is None:
return False return False
if novIdx["level"] in self.LVL_MAP: if novIdx.level in self.LVL_MAP:
self.titleLabel.setText("<b>%s</b>" % self.tr(self.LVL_MAP[novIdx["level"]])) self.titleLabel.setText("<b>%s</b>" % self.tr(self.LVL_MAP[novIdx.level]))
else: else:
self.titleLabel.setText("<b>%s</b>" % self.tr("Title")) self.titleLabel.setText("<b>%s</b>" % self.tr("Title"))
self.titleValue.setText(novIdx["title"]) self.titleValue.setText(novIdx.title)
itemStatus, _ = nwItem.getImportStatus() itemStatus, _ = nwItem.getImportStatus()
self.fileValue.setText(nwItem.itemName) self.fileValue.setText(nwItem.itemName)
self.itemValue.setText(itemStatus) self.itemValue.setText(itemStatus)
cC = checkInt(novIdx["cCount"], 0) cC = checkInt(novIdx.charCount, 0)
wC = checkInt(novIdx["wCount"], 0) wC = checkInt(novIdx.wordCount, 0)
pC = checkInt(novIdx["pCount"], 0) pC = checkInt(novIdx.paraCount, 0)
self.cCValue.setText(f"{cC:n}") self.cCValue.setText(f"{cC:n}")
self.wCValue.setText(f"{wC:n}") self.wCValue.setText(f"{wC:n}")
self.pCValue.setText(f"{pC:n}") self.pCValue.setText(f"{pC:n}")
self.synopValue.setText(novIdx["synopsis"]) self.synopValue.setText(novIdx.synopsis)
self.povKeyValue.setText(self._formatTags(theRefs, nwKeyWords.POV_KEY)) self.povKeyValue.setText(self._formatTags(theRefs, nwKeyWords.POV_KEY))
self.focKeyValue.setText(self._formatTags(theRefs, nwKeyWords.FOCUS_KEY)) self.focKeyValue.setText(self._formatTags(theRefs, nwKeyWords.FOCUS_KEY))
@@ -1046,7 +1046,7 @@ class GuiOutlineDetails(QScrollArea):
def updateClasses(self): def updateClasses(self):
"""Update the visibility status of class details. """Update the visibility status of class details.
""" """
usedClasses = self.theProject.projTree.rootClasses() usedClasses = self.theProject.tree.rootClasses()
pltVisible = nwItemClass.PLOT in usedClasses pltVisible = nwItemClass.PLOT in usedClasses
timVisible = nwItemClass.TIMELINE in usedClasses timVisible = nwItemClass.TIMELINE in usedClasses
+31 -30
View File
@@ -62,7 +62,6 @@ class GuiProjectTree(QTreeWidget):
self.theParent = theParent self.theParent = theParent
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theProject = theParent.theProject self.theProject = theParent.theProject
self.theIndex = theParent.theIndex
# Internal Variables # Internal Variables
self._treeMap = {} self._treeMap = {}
@@ -183,14 +182,14 @@ class GuiProjectTree(QTreeWidget):
elif itemType in (nwItemType.FILE, nwItemType.FOLDER): elif itemType in (nwItemType.FILE, nwItemType.FOLDER):
sHandle = self.getSelectedHandle() sHandle = self.getSelectedHandle()
if sHandle is None or sHandle not in self.theProject.projTree: if sHandle is None or sHandle not in self.theProject.tree:
self.theParent.makeAlert(self.tr( self.theParent.makeAlert(self.tr(
"Did not find anywhere to add the file or folder!" "Did not find anywhere to add the file or folder!"
), nwAlert.ERROR) ), nwAlert.ERROR)
return False return False
# If the selected item is a file, the new item will be a sibling # If the selected item is a file, the new item will be a sibling
pItem = self.theProject.projTree[sHandle] pItem = self.theProject.tree[sHandle]
if pItem.itemType == nwItemType.FILE: if pItem.itemType == nwItemType.FILE:
nHandle = sHandle nHandle = sHandle
sHandle = pItem.itemParent sHandle = pItem.itemParent
@@ -198,7 +197,7 @@ class GuiProjectTree(QTreeWidget):
logger.error("Internal error") # Bug logger.error("Internal error") # Bug
return False return False
if self.theProject.projTree.isTrash(sHandle): if self.theProject.tree.isTrash(sHandle):
self.theParent.makeAlert(self.tr( self.theParent.makeAlert(self.tr(
"Cannot add new files or folders to the Trash folder." "Cannot add new files or folders to the Trash folder."
), nwAlert.ERROR) ), nwAlert.ERROR)
@@ -224,7 +223,7 @@ class GuiProjectTree(QTreeWidget):
# Add the new item to the tree # Add the new item to the tree
self.revealNewTreeItem(tHandle, nHandle) self.revealNewTreeItem(tHandle, nHandle)
self.theParent.editItem(tHandle) self.theParent.editItem(tHandle)
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
# If this is a folder, return here # If this is a folder, return here
if nwItem.itemType != nwItemType.FILE: if nwItem.itemType != nwItemType.FILE:
@@ -238,12 +237,14 @@ class GuiProjectTree(QTreeWidget):
else: else:
newText = f"# {nwItem.itemName}\n\n" newText = f"# {nwItem.itemName}\n\n"
pIndex = self.theProject.index
# Save the text and index it # Save the text and index it
newDoc.writeDocument(newText) newDoc.writeDocument(newText)
self.theIndex.scanText(tHandle, newText) pIndex.scanText(tHandle, newText)
# Get Word Counts # Get Word Counts
cC, wC, pC = self.theIndex.getCounts(tHandle) cC, wC, pC = pIndex.getCounts(tHandle)
nwItem.setCharCount(cC) nwItem.setCharCount(cC)
nwItem.setWordCount(wC) nwItem.setWordCount(wC)
nwItem.setParaCount(pC) nwItem.setParaCount(pC)
@@ -255,7 +256,7 @@ class GuiProjectTree(QTreeWidget):
def revealNewTreeItem(self, tHandle, nHandle=None): def revealNewTreeItem(self, tHandle, nHandle=None):
"""Reveal a newly added project item in the project tree. """Reveal a newly added project item in the project tree.
""" """
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
if nwItem is None: if nwItem is None:
return False return False
@@ -376,7 +377,7 @@ class GuiProjectTree(QTreeWidget):
logger.error("No project open") logger.error("No project open")
return False return False
trashHandle = self.theProject.projTree.trashRoot() trashHandle = self.theProject.tree.trashRoot()
logger.debug("Emptying Trash folder") logger.debug("Emptying Trash folder")
if trashHandle is None: if trashHandle is None:
@@ -437,7 +438,7 @@ class GuiProjectTree(QTreeWidget):
return False return False
trItemS = self._getTreeItem(tHandle) trItemS = self._getTreeItem(tHandle)
nwItemS = self.theProject.projTree[tHandle] nwItemS = self.theProject.tree[tHandle]
if trItemS is None or nwItemS is None: if trItemS is None or nwItemS is None:
logger.error("Could not find tree item for deletion") logger.error("Could not find tree item for deletion")
@@ -479,7 +480,7 @@ class GuiProjectTree(QTreeWidget):
logger.error("Could not delete item") logger.error("Could not delete item")
return False return False
if self.theProject.projTree.isTrash(tHandle): if self.theProject.tree.isTrash(tHandle):
# 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.
doPermanent = False doPermanent = False
@@ -533,7 +534,7 @@ class GuiProjectTree(QTreeWidget):
already coming from the project tree. already coming from the project tree.
""" """
trItem = self._getTreeItem(tHandle) trItem = self._getTreeItem(tHandle)
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
if trItem is None or nwItem is None: if trItem is None or nwItem is None:
return return
@@ -545,7 +546,7 @@ class GuiProjectTree(QTreeWidget):
expIcon = self.theTheme.getIcon("cross") expIcon = self.theTheme.getIcon("cross")
itemStatus, statusIcon = nwItem.getImportStatus() itemStatus, statusIcon = nwItem.getImportStatus()
hLevel = self.theIndex.getHandleHeaderLevel(tHandle) hLevel = self.theProject.index.getHandleHeaderLevel(tHandle)
itemIcon = self.theTheme.getItemIcon( itemIcon = self.theTheme.getItemIcon(
nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel
) )
@@ -598,10 +599,10 @@ class GuiProjectTree(QTreeWidget):
pHandle = pItem.data(self.C_NAME, Qt.UserRole) pHandle = pItem.data(self.C_NAME, Qt.UserRole)
if pHandle: if pHandle:
if self.theProject.projTree.checkType(pHandle, nwItemType.FILE): if self.theProject.tree.checkType(pHandle, nwItemType.FILE):
# A file has an internal word count we need to account # A file has an internal word count we need to account
# for, but a folder always has 0 words on its own. # for, but a folder always has 0 words on its own.
pCount += self.theIndex.getCounts(pHandle)[1] pCount += self.theProject.index.getCounts(pHandle)[1]
self.propagateCount(pHandle, pCount, countChildren=False) self.propagateCount(pHandle, pCount, countChildren=False)
@@ -713,7 +714,7 @@ class GuiProjectTree(QTreeWidget):
if isinstance(selItem, QTreeWidgetItem): if isinstance(selItem, QTreeWidgetItem):
tHandle = selItem.data(self.C_NAME, Qt.UserRole) tHandle = selItem.data(self.C_NAME, Qt.UserRole)
self.setSelectedHandle(tHandle) # Just to be safe self.setSelectedHandle(tHandle) # Just to be safe
tItem = self.theProject.projTree[tHandle] tItem = self.theProject.tree[tHandle]
if tItem is not None: if tItem is not None:
if self.ctxMenu.filterActions(tItem): if self.ctxMenu.filterActions(tItem):
# Only open menu if any actions remain after filter # Only open menu if any actions remain after filter
@@ -751,7 +752,7 @@ class GuiProjectTree(QTreeWidget):
return return
tHandle = selItem.data(self.C_NAME, Qt.UserRole) tHandle = selItem.data(self.C_NAME, Qt.UserRole)
tItem = self.theProject.projTree[tHandle] tItem = self.theProject.tree[tHandle]
if tItem is None: if tItem is None:
return return
@@ -799,7 +800,7 @@ class GuiProjectTree(QTreeWidget):
"""Run various maintenance tasks for a moved item. """Run various maintenance tasks for a moved item.
""" """
trItemS = self._getTreeItem(tHandle) trItemS = self._getTreeItem(tHandle)
nwItemS = self.theProject.projTree[tHandle] nwItemS = self.theProject.tree[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)
@@ -816,13 +817,13 @@ class GuiProjectTree(QTreeWidget):
logger.debug("A total of %d item(s) were moved", len(mHandles)) logger.debug("A total of %d item(s) were moved", len(mHandles))
for mHandle in mHandles: for mHandle in mHandles:
logger.debug("Updating item '%s'", mHandle) logger.debug("Updating item '%s'", mHandle)
self.theProject.projTree.updateItemData(mHandle) self.theProject.tree.updateItemData(mHandle)
# Update the index # Update the index
if nwItemS.isInactive(): if nwItemS.isInactive():
self.theIndex.deleteHandle(mHandle) self.theProject.index.deleteHandle(mHandle)
else: else:
self.theIndex.reIndexHandle(mHandle) self.theProject.index.reIndexHandle(mHandle)
self.setTreeItemValues(mHandle) self.setTreeItemValues(mHandle)
@@ -849,7 +850,7 @@ class GuiProjectTree(QTreeWidget):
def _deleteTreeItem(self, tHandle): def _deleteTreeItem(self, tHandle):
"""Permanently delete a tree item from the project and the map. """Permanently delete a tree item from the project and the map.
""" """
if self.theProject.projTree.checkType(tHandle, nwItemType.FILE): if self.theProject.tree.checkType(tHandle, nwItemType.FILE):
delDoc = NWDoc(self.theProject, tHandle) delDoc = NWDoc(self.theProject, tHandle)
if not delDoc.deleteDocument(): if not delDoc.deleteDocument():
self.theParent.makeAlert([ self.theParent.makeAlert([
@@ -857,8 +858,8 @@ class GuiProjectTree(QTreeWidget):
], nwAlert.ERROR) ], nwAlert.ERROR)
return False return False
self.theIndex.deleteHandle(tHandle) self.theProject.index.deleteHandle(tHandle)
del self.theProject.projTree[tHandle] del self.theProject.tree[tHandle]
self._treeMap.pop(tHandle, None) self._treeMap.pop(tHandle, None)
return True return True
@@ -871,7 +872,7 @@ class GuiProjectTree(QTreeWidget):
cCount = tItem.childCount() cCount = tItem.childCount()
# Update tree-related meta data # Update tree-related meta data
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
nwItem.setExpanded(tItem.isExpanded() and cCount > 0) nwItem.setExpanded(tItem.isExpanded() and cCount > 0)
nwItem.setOrder(tIndex) nwItem.setOrder(tIndex)
@@ -945,7 +946,7 @@ class GuiProjectTree(QTreeWidget):
trItem = self._getTreeItem(trashHandle) trItem = self._getTreeItem(trashHandle)
if trItem is None: if trItem is None:
trItem = self._addTreeItem( trItem = self._addTreeItem(
self.theProject.projTree[trashHandle] self.theProject.tree[trashHandle]
) )
if trItem is not None: if trItem is not None:
trItem.setExpanded(True) trItem.setExpanded(True)
@@ -965,8 +966,8 @@ class GuiProjectTree(QTreeWidget):
def _emitItemChange(self, tHandle): def _emitItemChange(self, tHandle):
"""Emit an item change signal for a given handle. """Emit an item change signal for a given handle.
""" """
if self.theProject.projTree.checkType(tHandle, nwItemType.FILE): if self.theProject.tree.checkType(tHandle, nwItemType.FILE):
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.tree[tHandle]
if nwItem.isNovelLike(): if nwItem.isNovelLike():
self.novelItemChanged.emit() self.novelItemChanged.emit()
else: else:
@@ -1049,9 +1050,9 @@ class GuiProjectTreeMenu(QMenu):
logger.error("Failed to extract information to build tree context menu") logger.error("Failed to extract information to build tree context menu")
return False return False
trashHandle = self.theTree.theProject.projTree.trashRoot() trashHandle = self.theTree.theProject.tree.trashRoot()
inTrash = self.theTree.theProject.projTree.isTrash(theItem.itemHandle) inTrash = self.theTree.theProject.tree.isTrash(theItem.itemHandle)
isTrash = theItem.itemHandle == trashHandle and trashHandle is not None isTrash = theItem.itemHandle == trashHandle and trashHandle is not None
isFile = theItem.itemType == nwItemType.FILE isFile = theItem.itemType == nwItemType.FILE
+19 -29
View File
@@ -51,7 +51,7 @@ from novelwriter.dialogs import (
from novelwriter.tools import ( from novelwriter.tools import (
GuiBuildNovel, GuiLipsum, GuiProjectWizard, GuiWritingStats GuiBuildNovel, GuiLipsum, GuiProjectWizard, GuiWritingStats
) )
from novelwriter.core import NWProject, NWIndex from novelwriter.core import NWProject
from novelwriter.enum import ( from novelwriter.enum import (
nwDocMode, nwItemType, nwItemClass, nwAlert, nwWidget, nwState, nwView nwDocMode, nwItemType, nwItemClass, nwAlert, nwWidget, nwState, nwView
) )
@@ -87,7 +87,6 @@ class GuiMain(QMainWindow):
# Core Classes and Settings # Core Classes and Settings
self.theTheme = GuiTheme() self.theTheme = GuiTheme()
self.theProject = NWProject(self) self.theProject = NWProject(self)
self.theIndex = NWIndex(self.theProject)
self.hasProject = False self.hasProject = False
self.isFocusMode = False self.isFocusMode = False
self.idleRefTime = time() self.idleRefTime = time()
@@ -420,7 +419,7 @@ class GuiMain(QMainWindow):
self.idleRefTime = time() self.idleRefTime = time()
self.idleTime = 0.0 self.idleTime = 0.0
self.theIndex.clearIndex() self.theProject.index.clearIndex()
self.clearGUI() self.clearGUI()
self.hasProject = False self.hasProject = False
self._changeView(nwView.PROJECT) self._changeView(nwView.PROJECT)
@@ -497,7 +496,7 @@ class GuiMain(QMainWindow):
self.idleTime = 0.0 self.idleTime = 0.0
# Load the tag index # Load the tag index
self.theIndex.loadIndex() self.theProject.index.loadIndex()
# Update GUI # Update GUI
self._updateWindowTitle(self.theProject.projName) self._updateWindowTitle(self.theProject.projName)
@@ -516,7 +515,7 @@ class GuiMain(QMainWindow):
self.viewDocument(self.theProject.lastViewed) self.viewDocument(self.theProject.lastViewed)
# Check if we need to rebuild the index # Check if we need to rebuild the index
if self.theIndex.indexBroken: if self.theProject.index.indexBroken:
self.makeAlert(self.tr( self.makeAlert(self.tr(
"The project index is outdated or broken. Rebuilding index." "The project index is outdated or broken. Rebuilding index."
), nwAlert.INFO) ), nwAlert.INFO)
@@ -540,7 +539,7 @@ class GuiMain(QMainWindow):
self.treeView.saveTreeOrder() self.treeView.saveTreeOrder()
if self.theProject.saveProject(autoSave=autoSave): if self.theProject.saveProject(autoSave=autoSave):
self.theIndex.saveIndex() self.theProject.index.saveIndex()
return True return True
@@ -573,7 +572,7 @@ class GuiMain(QMainWindow):
logger.error("No project open") logger.error("No project open")
return False return False
if not self.theProject.projTree.checkType(tHandle, nwItemType.FILE): if not self.theProject.tree.checkType(tHandle, nwItemType.FILE):
logger.debug("Requested item '%s' is not a document", tHandle) logger.debug("Requested item '%s' is not a document", tHandle)
return False return False
@@ -601,8 +600,8 @@ class GuiMain(QMainWindow):
nHandle = None # The next handle after tHandle nHandle = None # The next handle after tHandle
fHandle = None # The first file handle we encounter fHandle = None # The first file handle we encounter
foundIt = False # We've found tHandle, pick the next we see foundIt = False # We've found tHandle, pick the next we see
for tItem in self.theProject.projTree: for tItem in self.theProject.tree:
if not self.theProject.projTree.checkType(tItem.itemHandle, nwItemType.FILE): if not self.theProject.tree.checkType(tItem.itemHandle, nwItemType.FILE):
continue continue
if fHandle is None: if fHandle is None:
fHandle = tItem.itemHandle fHandle = tItem.itemHandle
@@ -819,7 +818,7 @@ class GuiMain(QMainWindow):
logger.warning("No item selected") logger.warning("No item selected")
return False return False
tItem = self.theProject.projTree[tHandle] tItem = self.theProject.tree[tHandle]
if tItem is None: if tItem is None:
return False return False
if tItem.itemType == nwItemType.NO_TYPE: if tItem.itemType == nwItemType.NO_TYPE:
@@ -863,25 +862,16 @@ class GuiMain(QMainWindow):
tStart = time() tStart = time()
self.treeView.saveTreeOrder() self.treeView.saveTreeOrder()
self.theIndex.clearIndex() self.theProject.index.clearIndex()
for tItem in self.theProject.projTree: for tItem in self.theProject.tree:
if tItem is None: # pragma: no cover
continue # This is a bug trap
if tItem is not None: logger.verbose("Indexing '%s'", tItem.itemName)
self.setStatus(self.tr("Indexing: '{0}'").format(tItem.itemName)) if self.theProject.index.reIndexHandle(tItem.itemHandle):
else: # Update Word Counts
self.setStatus(self.tr("Indexing: '{0}'").format(self.tr("Unknown item"))) self.treeView.propagateCount(tItem.itemHandle, tItem.wordCount, countChildren=True)
if tItem is not None and tItem.itemType == nwItemType.FILE:
logger.verbose("Scanning '%s'", tItem.itemName)
self.theIndex.reIndexHandle(tItem.itemHandle)
# Get Word Counts
cC, wC, pC = self.theIndex.getCounts(tItem.itemHandle)
tItem.setCharCount(cC)
tItem.setWordCount(wC)
tItem.setParaCount(pC)
self.treeView.propagateCount(tItem.itemHandle, wC, countChildren=True)
self.treeView.setTreeItemValues(tItem.itemHandle) self.treeView.setTreeItemValues(tItem.itemHandle)
tEnd = time() tEnd = time()
@@ -1453,7 +1443,7 @@ class GuiMain(QMainWindow):
"""A wrapper function for the index lookup of a tag that will """A wrapper function for the index lookup of a tag that will
display an alert if the tag cannot be found. display an alert if the tag cannot be found.
""" """
tHandle, _, sTitle = self.theIndex.getTagSource(tTag) tHandle, sTitle = self.theProject.index.getTagSource(tTag)
if tHandle is None: if tHandle is None:
self.makeAlert(self.tr( self.makeAlert(self.tr(
"Could not find the reference for tag '{0}'. It either doesn't " "Could not find the reference for tag '{0}'. It either doesn't "
@@ -1576,7 +1566,7 @@ class GuiMain(QMainWindow):
""" """
tHandle = self.treeView.getSelectedHandle() tHandle = self.treeView.getSelectedHandle()
if tHandle is not None: if tHandle is not None:
tItem = self.theProject.projTree[tHandle] tItem = self.theProject.tree[tHandle]
if tItem is None: if tItem is None:
return return
if tItem.itemType == nwItemType.FILE: if tItem.itemType == nwItemType.FILE:
+45 -45
View File
@@ -75,7 +75,6 @@ class GuiBuildNovel(QDialog):
self.theParent = theParent self.theParent = theParent
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theProject = theParent.theProject self.theProject = theParent.theProject
self.optState = theParent.theProject.optState
self.htmlText = [] # List of html documents self.htmlText = [] # List of html documents
self.htmlStyle = [] # List of html styles self.htmlStyle = [] # List of html styles
@@ -86,9 +85,10 @@ class GuiBuildNovel(QDialog):
self.setMinimumWidth(self.mainConf.pxInt(700)) self.setMinimumWidth(self.mainConf.pxInt(700))
self.setMinimumHeight(self.mainConf.pxInt(600)) self.setMinimumHeight(self.mainConf.pxInt(600))
pOptions = self.theProject.options
self.resize( self.resize(
self.mainConf.pxInt(self.optState.getInt("GuiBuildNovel", "winWidth", 900)), self.mainConf.pxInt(pOptions.getInt("GuiBuildNovel", "winWidth", 900)),
self.mainConf.pxInt(self.optState.getInt("GuiBuildNovel", "winHeight", 800)) self.mainConf.pxInt(pOptions.getInt("GuiBuildNovel", "winHeight", 800))
) )
self.docView = GuiBuildNovelDocView(self, self.theProject) self.docView = GuiBuildNovelDocView(self, self.theProject)
@@ -174,12 +174,12 @@ class GuiBuildNovel(QDialog):
self.hideScene = QSwitch(width=wS, height=hS) self.hideScene = QSwitch(width=wS, height=hS)
self.hideScene.setChecked( self.hideScene.setChecked(
self.optState.getBool("GuiBuildNovel", "hideScene", False) pOptions.getBool("GuiBuildNovel", "hideScene", False)
) )
self.hideSection = QSwitch(width=wS, height=hS) self.hideSection = QSwitch(width=wS, height=hS)
self.hideSection.setChecked( self.hideSection.setChecked(
self.optState.getBool("GuiBuildNovel", "hideSection", True) pOptions.getBool("GuiBuildNovel", "hideSection", True)
) )
# Wrapper boxes due to QGridView and QLineEdit expand bug # Wrapper boxes due to QGridView and QLineEdit expand bug
@@ -235,7 +235,7 @@ class GuiBuildNovel(QDialog):
self.textFont.setReadOnly(True) self.textFont.setReadOnly(True)
self.textFont.setMinimumWidth(xFmt) self.textFont.setMinimumWidth(xFmt)
self.textFont.setText( self.textFont.setText(
self.optState.getString("GuiBuildNovel", "textFont", self.mainConf.textFont) pOptions.getString("GuiBuildNovel", "textFont", self.mainConf.textFont)
) )
self.fontButton = QPushButton("...") self.fontButton = QPushButton("...")
self.fontButton.setMaximumWidth(int(2.5*self.theTheme.getTextWidth("..."))) self.fontButton.setMaximumWidth(int(2.5*self.theTheme.getTextWidth("...")))
@@ -247,7 +247,7 @@ class GuiBuildNovel(QDialog):
self.textSize.setMaximum(72) self.textSize.setMaximum(72)
self.textSize.setSingleStep(1) self.textSize.setSingleStep(1)
self.textSize.setValue( self.textSize.setValue(
self.optState.getInt("GuiBuildNovel", "textSize", self.mainConf.textSize) pOptions.getInt("GuiBuildNovel", "textSize", self.mainConf.textSize)
) )
self.lineHeight = QDoubleSpinBox(self) self.lineHeight = QDoubleSpinBox(self)
@@ -257,7 +257,7 @@ class GuiBuildNovel(QDialog):
self.lineHeight.setSingleStep(0.05) self.lineHeight.setSingleStep(0.05)
self.lineHeight.setDecimals(2) self.lineHeight.setDecimals(2)
self.lineHeight.setValue( self.lineHeight.setValue(
self.optState.getFloat("GuiBuildNovel", "lineHeight", 1.15) pOptions.getFloat("GuiBuildNovel", "lineHeight", 1.15)
) )
# Wrapper box due to QGridView and QLineEdit expand bug # Wrapper box due to QGridView and QLineEdit expand bug
@@ -291,12 +291,12 @@ class GuiBuildNovel(QDialog):
self.justifyText = QSwitch(width=wS, height=hS) self.justifyText = QSwitch(width=wS, height=hS)
self.justifyText.setChecked( self.justifyText.setChecked(
self.optState.getBool("GuiBuildNovel", "justifyText", False) pOptions.getBool("GuiBuildNovel", "justifyText", False)
) )
self.noStyling = QSwitch(width=wS, height=hS) self.noStyling = QSwitch(width=wS, height=hS)
self.noStyling.setChecked( self.noStyling.setChecked(
self.optState.getBool("GuiBuildNovel", "noStyling", False) pOptions.getBool("GuiBuildNovel", "noStyling", False)
) )
self.styleForm.addWidget(justifyLabel, 1, 0, 1, 1, Qt.AlignLeft) self.styleForm.addWidget(justifyLabel, 1, 0, 1, 1, Qt.AlignLeft)
@@ -316,22 +316,22 @@ class GuiBuildNovel(QDialog):
self.includeSynopsis = QSwitch(width=wS, height=hS) self.includeSynopsis = QSwitch(width=wS, height=hS)
self.includeSynopsis.setChecked( self.includeSynopsis.setChecked(
self.optState.getBool("GuiBuildNovel", "incSynopsis", False) pOptions.getBool("GuiBuildNovel", "incSynopsis", False)
) )
self.includeComments = QSwitch(width=wS, height=hS) self.includeComments = QSwitch(width=wS, height=hS)
self.includeComments.setChecked( self.includeComments.setChecked(
self.optState.getBool("GuiBuildNovel", "incComments", False) pOptions.getBool("GuiBuildNovel", "incComments", False)
) )
self.includeKeywords = QSwitch(width=wS, height=hS) self.includeKeywords = QSwitch(width=wS, height=hS)
self.includeKeywords.setChecked( self.includeKeywords.setChecked(
self.optState.getBool("GuiBuildNovel", "incKeywords", False) pOptions.getBool("GuiBuildNovel", "incKeywords", False)
) )
self.includeBody = QSwitch(width=wS, height=hS) self.includeBody = QSwitch(width=wS, height=hS)
self.includeBody.setChecked( self.includeBody.setChecked(
self.optState.getBool("GuiBuildNovel", "incBodyText", True) pOptions.getBool("GuiBuildNovel", "incBodyText", True)
) )
synopsisLabel = QLabel(self.tr("Include synopsis")) synopsisLabel = QLabel(self.tr("Include synopsis"))
@@ -360,17 +360,17 @@ class GuiBuildNovel(QDialog):
self.novelFiles = QSwitch(width=wS, height=hS) self.novelFiles = QSwitch(width=wS, height=hS)
self.novelFiles.setChecked( self.novelFiles.setChecked(
self.optState.getBool("GuiBuildNovel", "addNovel", True) pOptions.getBool("GuiBuildNovel", "addNovel", True)
) )
self.noteFiles = QSwitch(width=wS, height=hS) self.noteFiles = QSwitch(width=wS, height=hS)
self.noteFiles.setChecked( self.noteFiles.setChecked(
self.optState.getBool("GuiBuildNovel", "addNotes", False) pOptions.getBool("GuiBuildNovel", "addNotes", False)
) )
self.ignoreFlag = QSwitch(width=wS, height=hS) self.ignoreFlag = QSwitch(width=wS, height=hS)
self.ignoreFlag.setChecked( self.ignoreFlag.setChecked(
self.optState.getBool("GuiBuildNovel", "ignoreFlag", False) pOptions.getBool("GuiBuildNovel", "ignoreFlag", False)
) )
novelLabel = QLabel(self.tr("Include novel files")) novelLabel = QLabel(self.tr("Include novel files"))
@@ -396,12 +396,12 @@ class GuiBuildNovel(QDialog):
self.replaceTabs = QSwitch(width=wS, height=hS) self.replaceTabs = QSwitch(width=wS, height=hS)
self.replaceTabs.setChecked( self.replaceTabs.setChecked(
self.optState.getBool("GuiBuildNovel", "replaceTabs", False) pOptions.getBool("GuiBuildNovel", "replaceTabs", False)
) )
self.replaceUCode = QSwitch(width=wS, height=hS) self.replaceUCode = QSwitch(width=wS, height=hS)
self.replaceUCode.setChecked( self.replaceUCode.setChecked(
self.optState.getBool("GuiBuildNovel", "replaceUCode", False) pOptions.getBool("GuiBuildNovel", "replaceUCode", False)
) )
tabsLabel = QLabel(self.tr("Replace tabs with spaces")) tabsLabel = QLabel(self.tr("Replace tabs with spaces"))
@@ -493,9 +493,9 @@ class GuiBuildNovel(QDialog):
# Splitter Position # Splitter Position
boxWidth = self.mainConf.pxInt(350) boxWidth = self.mainConf.pxInt(350)
boxWidth = self.optState.getInt("GuiBuildNovel", "boxWidth", boxWidth) boxWidth = pOptions.getInt("GuiBuildNovel", "boxWidth", boxWidth)
docWidth = max(self.width() - boxWidth, 100) docWidth = max(self.width() - boxWidth, 100)
docWidth = self.optState.getInt("GuiBuildNovel", "docWidth", docWidth) docWidth = pOptions.getInt("GuiBuildNovel", "docWidth", docWidth)
# The Tool Box # The Tool Box
self.toolsBox = QVBoxLayout() self.toolsBox = QVBoxLayout()
@@ -712,10 +712,10 @@ class GuiBuildNovel(QDialog):
self.theParent.treeView.flushTreeOrder() self.theParent.treeView.flushTreeOrder()
self.theParent.saveDocument() self.theParent.saveDocument()
self.buildProgress.setMaximum(len(self.theProject.projTree)) self.buildProgress.setMaximum(len(self.theProject.tree))
self.buildProgress.setValue(0) self.buildProgress.setValue(0)
for nItt, tItem in enumerate(self.theProject.projTree): for nItt, tItem in enumerate(self.theProject.tree):
noteRoot = noteFiles noteRoot = noteFiles
noteRoot &= tItem.itemType == nwItemType.ROOT noteRoot &= tItem.itemType == nwItemType.ROOT
@@ -1153,28 +1153,28 @@ class GuiBuildNovel(QDialog):
self.theProject.setProjectLang(buildLang) self.theProject.setProjectLang(buildLang)
# GUI Settings # GUI Settings
self.optState.setValue("GuiBuildNovel", "hideScene", hideScene) pOptions = self.theProject.options
self.optState.setValue("GuiBuildNovel", "hideSection", hideSection) pOptions.setValue("GuiBuildNovel", "hideScene", hideScene)
self.optState.setValue("GuiBuildNovel", "winWidth", winWidth) pOptions.setValue("GuiBuildNovel", "hideSection", hideSection)
self.optState.setValue("GuiBuildNovel", "winHeight", winHeight) pOptions.setValue("GuiBuildNovel", "winWidth", winWidth)
self.optState.setValue("GuiBuildNovel", "boxWidth", boxWidth) pOptions.setValue("GuiBuildNovel", "winHeight", winHeight)
self.optState.setValue("GuiBuildNovel", "docWidth", docWidth) pOptions.setValue("GuiBuildNovel", "boxWidth", boxWidth)
self.optState.setValue("GuiBuildNovel", "justifyText", justifyText) pOptions.setValue("GuiBuildNovel", "docWidth", docWidth)
self.optState.setValue("GuiBuildNovel", "noStyling", noStyling) pOptions.setValue("GuiBuildNovel", "justifyText", justifyText)
self.optState.setValue("GuiBuildNovel", "textFont", textFont) pOptions.setValue("GuiBuildNovel", "noStyling", noStyling)
self.optState.setValue("GuiBuildNovel", "textSize", textSize) pOptions.setValue("GuiBuildNovel", "textFont", textFont)
self.optState.setValue("GuiBuildNovel", "lineHeight", lineHeight) pOptions.setValue("GuiBuildNovel", "textSize", textSize)
self.optState.setValue("GuiBuildNovel", "addNovel", novelFiles) pOptions.setValue("GuiBuildNovel", "lineHeight", lineHeight)
self.optState.setValue("GuiBuildNovel", "addNotes", noteFiles) pOptions.setValue("GuiBuildNovel", "addNovel", novelFiles)
self.optState.setValue("GuiBuildNovel", "ignoreFlag", ignoreFlag) pOptions.setValue("GuiBuildNovel", "addNotes", noteFiles)
self.optState.setValue("GuiBuildNovel", "incSynopsis", incSynopsis) pOptions.setValue("GuiBuildNovel", "ignoreFlag", ignoreFlag)
self.optState.setValue("GuiBuildNovel", "incComments", incComments) pOptions.setValue("GuiBuildNovel", "incSynopsis", incSynopsis)
self.optState.setValue("GuiBuildNovel", "incKeywords", incKeywords) pOptions.setValue("GuiBuildNovel", "incComments", incComments)
self.optState.setValue("GuiBuildNovel", "incBodyText", incBodyText) pOptions.setValue("GuiBuildNovel", "incKeywords", incKeywords)
self.optState.setValue("GuiBuildNovel", "replaceTabs", replaceTabs) pOptions.setValue("GuiBuildNovel", "incBodyText", incBodyText)
self.optState.setValue("GuiBuildNovel", "replaceUCode", replaceUCode) pOptions.setValue("GuiBuildNovel", "replaceTabs", replaceTabs)
pOptions.setValue("GuiBuildNovel", "replaceUCode", replaceUCode)
self.optState.saveSettings() pOptions.saveSettings()
return return
+34 -33
View File
@@ -67,33 +67,34 @@ class GuiWritingStats(QDialog):
self.theParent = theParent self.theParent = theParent
self.theTheme = theParent.theTheme self.theTheme = theParent.theTheme
self.theProject = theParent.theProject self.theProject = theParent.theProject
self.optState = theParent.theProject.optState
self.logData = [] self.logData = []
self.filterData = [] self.filterData = []
self.timeFilter = 0.0 self.timeFilter = 0.0
self.wordOffset = 0 self.wordOffset = 0
pOptions = self.theProject.options
self.setWindowTitle(self.tr("Writing Statistics")) self.setWindowTitle(self.tr("Writing Statistics"))
self.setMinimumWidth(self.mainConf.pxInt(420)) self.setMinimumWidth(self.mainConf.pxInt(420))
self.setMinimumHeight(self.mainConf.pxInt(400)) self.setMinimumHeight(self.mainConf.pxInt(400))
self.resize( self.resize(
self.mainConf.pxInt(self.optState.getInt("GuiWritingStats", "winWidth", 550)), self.mainConf.pxInt(pOptions.getInt("GuiWritingStats", "winWidth", 550)),
self.mainConf.pxInt(self.optState.getInt("GuiWritingStats", "winHeight", 500)) self.mainConf.pxInt(pOptions.getInt("GuiWritingStats", "winHeight", 500))
) )
# List Box # List Box
wCol0 = self.mainConf.pxInt( wCol0 = self.mainConf.pxInt(
self.optState.getInt("GuiWritingStats", "widthCol0", 180) pOptions.getInt("GuiWritingStats", "widthCol0", 180)
) )
wCol1 = self.mainConf.pxInt( wCol1 = self.mainConf.pxInt(
self.optState.getInt("GuiWritingStats", "widthCol1", 80) pOptions.getInt("GuiWritingStats", "widthCol1", 80)
) )
wCol2 = self.mainConf.pxInt( wCol2 = self.mainConf.pxInt(
self.optState.getInt("GuiWritingStats", "widthCol2", 80) pOptions.getInt("GuiWritingStats", "widthCol2", 80)
) )
wCol3 = self.mainConf.pxInt( wCol3 = self.mainConf.pxInt(
self.optState.getInt("GuiWritingStats", "widthCol3", 80) pOptions.getInt("GuiWritingStats", "widthCol3", 80)
) )
self.listBox = QTreeWidget() self.listBox = QTreeWidget()
@@ -115,9 +116,9 @@ class GuiWritingStats(QDialog):
hHeader.setTextAlignment(self.C_IDLE, Qt.AlignRight) hHeader.setTextAlignment(self.C_IDLE, Qt.AlignRight)
hHeader.setTextAlignment(self.C_COUNT, Qt.AlignRight) hHeader.setTextAlignment(self.C_COUNT, Qt.AlignRight)
sortCol = checkIntRange(self.optState.getInt("GuiWritingStats", "sortCol", 0), 0, 2, 0) sortCol = checkIntRange(pOptions.getInt("GuiWritingStats", "sortCol", 0), 0, 2, 0)
sortOrder = checkIntTuple( sortOrder = checkIntTuple(
self.optState.getInt("GuiWritingStats", "sortOrder", Qt.DescendingOrder), pOptions.getInt("GuiWritingStats", "sortOrder", Qt.DescendingOrder),
(Qt.AscendingOrder, Qt.DescendingOrder), Qt.DescendingOrder (Qt.AscendingOrder, Qt.DescendingOrder), Qt.DescendingOrder
) )
self.listBox.sortByColumn(sortCol, sortOrder) self.listBox.sortByColumn(sortCol, sortOrder)
@@ -190,37 +191,37 @@ class GuiWritingStats(QDialog):
self.incNovel = QSwitch(width=2*sPx, height=sPx) self.incNovel = QSwitch(width=2*sPx, height=sPx)
self.incNovel.setChecked( self.incNovel.setChecked(
self.optState.getBool("GuiWritingStats", "incNovel", True) pOptions.getBool("GuiWritingStats", "incNovel", True)
) )
self.incNovel.clicked.connect(self._updateListBox) self.incNovel.clicked.connect(self._updateListBox)
self.incNotes = QSwitch(width=2*sPx, height=sPx) self.incNotes = QSwitch(width=2*sPx, height=sPx)
self.incNotes.setChecked( self.incNotes.setChecked(
self.optState.getBool("GuiWritingStats", "incNotes", True) pOptions.getBool("GuiWritingStats", "incNotes", True)
) )
self.incNotes.clicked.connect(self._updateListBox) self.incNotes.clicked.connect(self._updateListBox)
self.hideZeros = QSwitch(width=2*sPx, height=sPx) self.hideZeros = QSwitch(width=2*sPx, height=sPx)
self.hideZeros.setChecked( self.hideZeros.setChecked(
self.optState.getBool("GuiWritingStats", "hideZeros", True) pOptions.getBool("GuiWritingStats", "hideZeros", True)
) )
self.hideZeros.clicked.connect(self._updateListBox) self.hideZeros.clicked.connect(self._updateListBox)
self.hideNegative = QSwitch(width=2*sPx, height=sPx) self.hideNegative = QSwitch(width=2*sPx, height=sPx)
self.hideNegative.setChecked( self.hideNegative.setChecked(
self.optState.getBool("GuiWritingStats", "hideNegative", False) pOptions.getBool("GuiWritingStats", "hideNegative", False)
) )
self.hideNegative.clicked.connect(self._updateListBox) self.hideNegative.clicked.connect(self._updateListBox)
self.groupByDay = QSwitch(width=2*sPx, height=sPx) self.groupByDay = QSwitch(width=2*sPx, height=sPx)
self.groupByDay.setChecked( self.groupByDay.setChecked(
self.optState.getBool("GuiWritingStats", "groupByDay", False) pOptions.getBool("GuiWritingStats", "groupByDay", False)
) )
self.groupByDay.clicked.connect(self._updateListBox) self.groupByDay.clicked.connect(self._updateListBox)
self.showIdleTime = QSwitch(width=2*sPx, height=sPx) self.showIdleTime = QSwitch(width=2*sPx, height=sPx)
self.showIdleTime.setChecked( self.showIdleTime.setChecked(
self.optState.getBool("GuiWritingStats", "showIdleTime", False) pOptions.getBool("GuiWritingStats", "showIdleTime", False)
) )
self.showIdleTime.clicked.connect(self._updateListBox) self.showIdleTime.clicked.connect(self._updateListBox)
@@ -244,7 +245,7 @@ class GuiWritingStats(QDialog):
self.histMax.setMaximum(100000) self.histMax.setMaximum(100000)
self.histMax.setSingleStep(100) self.histMax.setSingleStep(100)
self.histMax.setValue( self.histMax.setValue(
self.optState.getInt("GuiWritingStats", "histMax", 2000) pOptions.getInt("GuiWritingStats", "histMax", 2000)
) )
self.histMax.valueChanged.connect(self._updateListBox) self.histMax.valueChanged.connect(self._updateListBox)
@@ -323,23 +324,23 @@ class GuiWritingStats(QDialog):
showIdleTime = self.showIdleTime.isChecked() showIdleTime = self.showIdleTime.isChecked()
histMax = self.histMax.value() histMax = self.histMax.value()
self.optState.setValue("GuiWritingStats", "winWidth", winWidth) pOptions = self.theProject.options
self.optState.setValue("GuiWritingStats", "winHeight", winHeight) pOptions.setValue("GuiWritingStats", "winWidth", winWidth)
self.optState.setValue("GuiWritingStats", "widthCol0", widthCol0) pOptions.setValue("GuiWritingStats", "winHeight", winHeight)
self.optState.setValue("GuiWritingStats", "widthCol1", widthCol1) pOptions.setValue("GuiWritingStats", "widthCol0", widthCol0)
self.optState.setValue("GuiWritingStats", "widthCol2", widthCol2) pOptions.setValue("GuiWritingStats", "widthCol1", widthCol1)
self.optState.setValue("GuiWritingStats", "widthCol3", widthCol3) pOptions.setValue("GuiWritingStats", "widthCol2", widthCol2)
self.optState.setValue("GuiWritingStats", "sortCol", sortCol) pOptions.setValue("GuiWritingStats", "widthCol3", widthCol3)
self.optState.setValue("GuiWritingStats", "sortOrder", sortOrder) pOptions.setValue("GuiWritingStats", "sortCol", sortCol)
self.optState.setValue("GuiWritingStats", "incNovel", incNovel) pOptions.setValue("GuiWritingStats", "sortOrder", sortOrder)
self.optState.setValue("GuiWritingStats", "incNotes", incNotes) pOptions.setValue("GuiWritingStats", "incNovel", incNovel)
self.optState.setValue("GuiWritingStats", "hideZeros", hideZeros) pOptions.setValue("GuiWritingStats", "incNotes", incNotes)
self.optState.setValue("GuiWritingStats", "hideNegative", hideNegative) pOptions.setValue("GuiWritingStats", "hideZeros", hideZeros)
self.optState.setValue("GuiWritingStats", "groupByDay", groupByDay) pOptions.setValue("GuiWritingStats", "hideNegative", hideNegative)
self.optState.setValue("GuiWritingStats", "showIdleTime", showIdleTime) pOptions.setValue("GuiWritingStats", "groupByDay", groupByDay)
self.optState.setValue("GuiWritingStats", "histMax", histMax) pOptions.setValue("GuiWritingStats", "showIdleTime", showIdleTime)
pOptions.setValue("GuiWritingStats", "histMax", histMax)
self.optState.saveSettings() pOptions.saveSettings()
self.close() self.close()
return return
+1
View File
@@ -4,5 +4,6 @@
# Mars # Mars
@tag: Mars @tag: Mars
@location: Space
Its red. Dusty and red. Its red. Dusty and red.
+1 -1
View File
@@ -4,7 +4,7 @@
### Making a Scene ### Making a Scene
@pov: Jane @pov: Jane
@char: John @char: John, Jane
@location: Earth @location: Earth
A scene is defined by a level three heading, like the one at the top of this page. The scene will be assigned to the chapter preceding it in the project tree. The scene document can be sorted after the chapter document, or as a child of the chapter. Both result in the same output in the end, so it is a matter of preference. A scene is defined by a level three heading, like the one at the top of this page. The scene will be assigned to the chapter preceding it in the project tree. The scene document can be sorted after the chapter document, or as a child of the chapter. Both result in the same output in the end, so it is a matter of preference.
+2 -1
View File
@@ -1,5 +1,5 @@
%%~name: Chapter Two %%~name: Chapter Two
%%~path: e7ded148d6e4a/88706ddc78b1b %%~path: 7031beac91f75/88706ddc78b1b
%%~kind: NOVEL/DOCUMENT %%~kind: NOVEL/DOCUMENT
## Where has John Gone? ## Where has John Gone?
@@ -11,6 +11,7 @@
### Jane Cannot Find John ### Jane Cannot Find John
@pov: Jane @pov: Jane
@focus: John
@location: Space @location: Space
Jane has been looking all over for John. Hes nowhere to be found on Earth, so Jane goes to space. Jane has been looking all over for John. Hes nowhere to be found on Earth, so Jane goes to space.
+1
View File
@@ -4,6 +4,7 @@
### We Found John! ### We Found John!
@pov: John @pov: John
@focus: John
@location: Mars @location: Mars
Jane has been searching for a while, and she finally found John on Mars. He was indeed in space! What was he doing on Mars anyway? Well, it turns out, he was farming potatoes. Jane has been searching for a while, and she finally found John on Mars. He was indeed in space! What was he doing on Mars anyway? Well, it turns out, he was farming potatoes.
+1
View File
@@ -4,5 +4,6 @@
# Earth # Earth
@tag: Earth @tag: Earth
@location: Space
Third planet from the sun, fairly dense, and with lots of people on it. Third planet from the sun, fairly dense, and with lots of people on it.
+1 -1
View File
@@ -1,6 +1,6 @@
%%~name: Delete Me! %%~name: Delete Me!
%%~path: 98acd8c76c93a/b8136a5a774a0 %%~path: 98acd8c76c93a/b8136a5a774a0
%%~kind: NOVEL/DOCUMENT %%~kind: TRASH/DOCUMENT
### Delete Me! ### Delete Me!
This scene is trash. This scene is trash.
+3 -3
View File
@@ -1,13 +1,13 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="1.7-beta1" hexVersion="0x010700b1" fileVersion="1.4" timeStamp="2022-05-17 18:36:56"> <novelWriterXML appVersion="1.7-beta1" hexVersion="0x010700b1" fileVersion="1.4" timeStamp="2022-06-05 13:28:34">
<project> <project>
<name>Sample Project</name> <name>Sample Project</name>
<title>Sample Project</title> <title>Sample Project</title>
<author>Jane Smith</author> <author>Jane Smith</author>
<author>Jay Doh</author> <author>Jay Doh</author>
<saveCount>1329</saveCount> <saveCount>1331</saveCount>
<autoCount>220</autoCount> <autoCount>220</autoCount>
<editTime>67104</editTime> <editTime>67108</editTime>
</project> </project>
<settings> <settings>
<doBackup>False</doBackup> <doBackup>False</doBackup>
-1
View File
@@ -29,7 +29,6 @@ class MockGuiMain():
def __init__(self): def __init__(self):
self.mainConf = None self.mainConf = None
self.hasProject = True self.hasProject = True
self.theIndex = None
self.theProject = None self.theProject = None
self.statusBar = MockStatusBar() self.statusBar = MockStatusBar()
+121 -95
View File
@@ -1,99 +1,125 @@
{ {
"tagIndex": { "tagsIndex": {
"Bod": [3, "4c4f28287af27", "CHARACTER", "T000001"], "Bod": {"handle": "4c4f28287af27", "heading": "T000001", "class": "CHARACTER"},
"Main": [3, "2426c6f0ca922", "PLOT", "T000001"], "Main": {"handle": "2426c6f0ca922", "heading": "T000001", "class": "PLOT"},
"Europe": [3, "04468803b92e1", "WORLD", "T000001"] "Europe": {"handle": "04468803b92e1", "heading": "T000001", "class": "WORLD"}
},
"refIndex": {
"fb609cd8319dc": {
"T000001": [[3, "@pov", "Bod"], [4, "@plot", "Main"], [5, "@location", "Europe"]]
}, },
"88243afbe5ed8": { "itemIndex": {
"T000001": [[3, "@pov", "Bod"], [4, "@plot", "Main"], [5, "@location", "Europe"]] "7a992350f3eb6": {
}, "level": "H1",
"f96ec11c6a3da": { "headings": {
"T000001": [[3, "@pov", "Bod"], [4, "@plot", "Main"], [5, "@location", "Europe"]] "T000001": {"level": "H1", "title": "Lorem Ipsum", "tag": "", "cCount": 230, "wCount": 40, "pCount": 3, "synopsis": ""}
}, }
"441420a886d82": { },
"T000001": [[3, "@pov", "Bod"], [4, "@plot", "Main"], [5, "@location", "Europe"]] "8c58a65414c23": {
}, "level": "H0",
"eb103bc70c90c": { "headings": {
"T000001": [[3, "@pov", "Bod"], [4, "@plot", "Main"], [5, "@location", "Europe"]] "T000000": {"level": "H0", "title": "", "tag": "", "cCount": 1058, "wCount": 176, "pCount": 2, "synopsis": ""}
}, }
"f8c0562e50f1b": { },
"T000001": [[3, "@pov", "Bod"], [4, "@plot", "Main"], [5, "@location", "Europe"]] "88d59a277361b": {
}, "level": "H2",
"47666c91c7ccf": { "headings": {
"T000001": [[3, "@pov", "Bod"], [4, "@plot", "Main"], [5, "@location", "Europe"]] "T000001": {"level": "H2", "title": "Prologue", "tag": "", "cCount": 584, "wCount": 92, "pCount": 1, "synopsis": "Explanation from the lipsum.com website."}
}, }
"4c4f28287af27": { },
"T000001": [[4, "@plot", "Main"]] "db7e733775d4d": {
"level": "H1",
"headings": {
"T000001": {"level": "H1", "title": "Act One", "tag": "", "cCount": 35, "wCount": 6, "pCount": 1, "synopsis": ""}
}
},
"fb609cd8319dc": {
"level": "H2",
"headings": {
"T000001": {"level": "H2", "title": "Chapter One", "tag": "", "cCount": 419, "wCount": 67, "pCount": 1, "synopsis": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam."}
},
"references": {
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
}
},
"88243afbe5ed8": {
"level": "H3",
"headings": {
"T000001": {"level": "H3", "title": "Scene One", "tag": "", "cCount": 1197, "wCount": 174, "pCount": 2, "synopsis": "Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur."},
"T000013": {"level": "H4", "title": "Scene One, Section Two", "tag": "", "cCount": 1561, "wCount": 230, "pCount": 2, "synopsis": ""}
},
"references": {
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
}
},
"f96ec11c6a3da": {
"level": "H3",
"headings": {
"T000001": {"level": "H3", "title": "Scene Two", "tag": "", "cCount": 2034, "wCount": 299, "pCount": 3, "synopsis": "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci."},
"T000015": {"level": "H4", "title": "Scene Two, Section Two", "tag": "", "cCount": 2009, "wCount": 301, "pCount": 3, "synopsis": ""}
},
"references": {
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
}
},
"846352075de7d": {
"level": "H2",
"headings": {
"T000001": {"level": "H2", "title": "Why do we use it?", "tag": "", "cCount": 631, "wCount": 109, "pCount": 3, "synopsis": ""}
}
},
"441420a886d82": {
"level": "H2",
"headings": {
"T000001": {"level": "H2", "title": "Chapter Two", "tag": "", "cCount": 477, "wCount": 70, "pCount": 1, "synopsis": "Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue."}
},
"references": {
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
}
},
"eb103bc70c90c": {
"level": "H3",
"headings": {
"T000001": {"level": "H3", "title": "Scene Three", "tag": "", "cCount": 3006, "wCount": 439, "pCount": 4, "synopsis": "Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos."}
},
"references": {
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
}
},
"f8c0562e50f1b": {
"level": "H3",
"headings": {
"T000001": {"level": "H3", "title": "Scene Four", "tag": "", "cCount": 3839, "wCount": 563, "pCount": 6, "synopsis": "Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo."}
},
"references": {
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
}
},
"47666c91c7ccf": {
"level": "H3",
"headings": {
"T000001": {"level": "H3", "title": "Scene Five", "tag": "", "cCount": 3644, "wCount": 543, "pCount": 5, "synopsis": "Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus."}
},
"references": {
"T000001": {"Bod": "@pov", "Main": "@plot", "Europe": "@location"}
}
},
"4c4f28287af27": {
"level": "H1",
"headings": {
"T000001": {"level": "H1", "title": "Nobody Owens", "tag": "Bod", "cCount": 1864, "wCount": 284, "pCount": 3, "synopsis": ""}
},
"references": {
"T000001": {"Main": "@plot"}
}
},
"2426c6f0ca922": {
"level": "H1",
"headings": {
"T000001": {"level": "H1", "title": "Main Plot", "tag": "Main", "cCount": 1369, "wCount": 195, "pCount": 2, "synopsis": ""}
}
},
"04468803b92e1": {
"level": "H1",
"headings": {
"T000001": {"level": "H1", "title": "Ancient Europe", "tag": "Europe", "cCount": 1770, "wCount": 259, "pCount": 3, "synopsis": ""}
}
}
} }
},
"fileIndex": {
"7a992350f3eb6": {
"T000001": {"level": "H1", "title": "Lorem Ipsum", "layout": "DOCUMENT", "cCount": 230, "wCount": 40, "pCount": 3, "synopsis": ""}
},
"8c58a65414c23": {
"T000000": {"level": "H0", "title": "", "layout": "DOCUMENT", "cCount": 1058, "wCount": 176, "pCount": 2, "synopsis": ""}
},
"88d59a277361b": {
"T000001": {"level": "H2", "title": "Prologue", "layout": "DOCUMENT", "cCount": 584, "wCount": 92, "pCount": 1, "synopsis": "Explanation from the lipsum.com website."}
},
"db7e733775d4d": {
"T000001": {"level": "H1", "title": "Act One", "layout": "DOCUMENT", "cCount": 35, "wCount": 6, "pCount": 1, "synopsis": ""}
},
"fb609cd8319dc": {
"T000001": {"level": "H2", "title": "Chapter One", "layout": "DOCUMENT", "cCount": 419, "wCount": 67, "pCount": 1, "synopsis": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam."}
},
"88243afbe5ed8": {
"T000001": {"level": "H3", "title": "Scene One", "layout": "DOCUMENT", "cCount": 1197, "wCount": 174, "pCount": 2, "synopsis": "Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur."},
"T000013": {"level": "H4", "title": "Scene One, Section Two", "layout": "DOCUMENT", "cCount": 1561, "wCount": 230, "pCount": 2, "synopsis": ""}
},
"f96ec11c6a3da": {
"T000001": {"level": "H3", "title": "Scene Two", "layout": "DOCUMENT", "cCount": 2034, "wCount": 299, "pCount": 3, "synopsis": "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci."},
"T000015": {"level": "H4", "title": "Scene Two, Section Two", "layout": "DOCUMENT", "cCount": 2009, "wCount": 301, "pCount": 3, "synopsis": ""}
},
"846352075de7d": {
"T000001": {"level": "H2", "title": "Why do we use it?", "layout": "DOCUMENT", "cCount": 631, "wCount": 109, "pCount": 3, "synopsis": ""}
},
"441420a886d82": {
"T000001": {"level": "H2", "title": "Chapter Two", "layout": "DOCUMENT", "cCount": 477, "wCount": 70, "pCount": 1, "synopsis": "Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue."}
},
"eb103bc70c90c": {
"T000001": {"level": "H3", "title": "Scene Three", "layout": "DOCUMENT", "cCount": 3006, "wCount": 439, "pCount": 4, "synopsis": "Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos."}
},
"f8c0562e50f1b": {
"T000001": {"level": "H3", "title": "Scene Four", "layout": "DOCUMENT", "cCount": 3839, "wCount": 563, "pCount": 6, "synopsis": "Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo."}
},
"47666c91c7ccf": {
"T000001": {"level": "H3", "title": "Scene Five", "layout": "DOCUMENT", "cCount": 3644, "wCount": 543, "pCount": 5, "synopsis": "Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus."}
},
"4c4f28287af27": {
"T000001": {"level": "H1", "title": "Nobody Owens", "layout": "NOTE", "cCount": 1864, "wCount": 284, "pCount": 3, "synopsis": ""}
},
"2426c6f0ca922": {
"T000001": {"level": "H1", "title": "Main Plot", "layout": "NOTE", "cCount": 1369, "wCount": 195, "pCount": 2, "synopsis": ""}
},
"04468803b92e1": {
"T000001": {"level": "H1", "title": "Ancient Europe", "layout": "NOTE", "cCount": 1770, "wCount": 259, "pCount": 3, "synopsis": ""}
}
},
"fileMeta": {
"7a992350f3eb6": ["H1", 230, 40, 3],
"8c58a65414c23": ["H0", 1058, 176, 2],
"88d59a277361b": ["H2", 584, 92, 1],
"db7e733775d4d": ["H1", 35, 6, 1],
"fb609cd8319dc": ["H2", 419, 67, 1],
"88243afbe5ed8": ["H3", 2758, 404, 4],
"f96ec11c6a3da": ["H3", 4043, 600, 6],
"846352075de7d": ["H2", 631, 109, 3],
"441420a886d82": ["H2", 477, 70, 1],
"eb103bc70c90c": ["H3", 3006, 439, 4],
"f8c0562e50f1b": ["H3", 3839, 563, 6],
"47666c91c7ccf": ["H3", 3644, 543, 5],
"4c4f28287af27": ["H1", 1864, 284, 3],
"2426c6f0ca922": ["H1", 1369, 195, 2],
"04468803b92e1": ["H1", 1770, 259, 3]
}
} }
+1 -1
View File
@@ -64,7 +64,7 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, nwMinimal):
assert theDoc.readDocument() == "### New Scene\n\n" assert theDoc.readDocument() == "### New Scene\n\n"
# Try to open a new (non-existent) file # Try to open a new (non-existent) file
nHandle = theProject.projTree.findRoot(nwItemClass.NOVEL) nHandle = theProject.tree.findRoot(nwItemClass.NOVEL)
assert nHandle is not None assert nHandle is not None
xHandle = theProject.newFile("New File", nHandle) xHandle = theProject.newFile("New File", nHandle)
theDoc = NWDoc(theProject, xHandle) theDoc = NWDoc(theProject, xHandle)
File diff suppressed because it is too large Load Diff
+25 -25
View File
@@ -634,17 +634,17 @@ def testCoreProject_AccessItems(nwMinimal, mockGUI):
"afb3043c7b2b3", # ROOT: Characters "afb3043c7b2b3", # ROOT: Characters
"9d5247ab588e0", # ROOT: World "9d5247ab588e0", # ROOT: World
] ]
assert theProject.projTree.handles() == oldOrder assert theProject.tree.handles() == oldOrder
assert theProject.setTreeOrder(newOrder) assert theProject.setTreeOrder(newOrder)
assert theProject.projTree.handles() == newOrder assert theProject.tree.handles() == newOrder
# Add a non-existing item # Add a non-existing item
theProject.projTree._treeOrder.append("01234567789abc") theProject.tree._treeOrder.append("01234567789abc")
# Add an item with a non-existent parent # Add an item with a non-existent parent
nHandle = theProject.newFile("Test File", "a6d311a93600a") nHandle = theProject.newFile("Test File", "a6d311a93600a")
theProject.projTree[nHandle].setParent("cba9876543210") theProject.tree[nHandle].setParent("cba9876543210")
assert theProject.projTree[nHandle].itemParent == "cba9876543210" assert theProject.tree[nHandle].itemParent == "cba9876543210"
retOrder = [] retOrder = []
for tItem in theProject.getProjectItems(): for tItem in theProject.getProjectItems():
@@ -661,7 +661,7 @@ def testCoreProject_AccessItems(nwMinimal, mockGUI):
"f5ab3e30151e1", # FILE: New Chapter "f5ab3e30151e1", # FILE: New Chapter
"8c659a11cd429", # FILE: New Scene "8c659a11cd429", # FILE: New Scene
] ]
assert theProject.projTree[nHandle].itemParent is None assert theProject.tree[nHandle].itemParent is None
# END Test testCoreProject_AccessItems # END Test testCoreProject_AccessItems
@@ -679,15 +679,15 @@ def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
# Change Status # Change Status
# ============= # =============
theProject.projTree["0000000000014"].setStatus("Finished") theProject.tree["0000000000014"].setStatus("Finished")
theProject.projTree["0000000000015"].setStatus("Draft") theProject.tree["0000000000015"].setStatus("Draft")
theProject.projTree["0000000000016"].setStatus("Note") theProject.tree["0000000000016"].setStatus("Note")
theProject.projTree["0000000000017"].setStatus("Finished") theProject.tree["0000000000017"].setStatus("Finished")
assert theProject.projTree["0000000000014"].itemStatus == statusKeys[3] assert theProject.tree["0000000000014"].itemStatus == statusKeys[3]
assert theProject.projTree["0000000000015"].itemStatus == statusKeys[2] assert theProject.tree["0000000000015"].itemStatus == statusKeys[2]
assert theProject.projTree["0000000000016"].itemStatus == statusKeys[1] assert theProject.tree["0000000000016"].itemStatus == statusKeys[1]
assert theProject.projTree["0000000000017"].itemStatus == statusKeys[3] assert theProject.tree["0000000000017"].itemStatus == statusKeys[3]
newList = [ newList = [
{"key": statusKeys[0], "name": "New", "cols": (1, 1, 1)}, {"key": statusKeys[0], "name": "New", "cols": (1, 1, 1)},
@@ -723,9 +723,9 @@ def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd):
# ================= # =================
fHandle = theProject.newFile("Jane Doe", "8b9d2e465e150") fHandle = theProject.newFile("Jane Doe", "8b9d2e465e150")
theProject.projTree[fHandle].setImport("Main") theProject.tree[fHandle].setImport("Main")
assert theProject.projTree[fHandle].itemImport == importKeys[3] assert theProject.tree[fHandle].itemImport == importKeys[3]
newList = [ newList = [
{"key": importKeys[0], "name": "New", "cols": (1, 1, 1)}, {"key": importKeys[0], "name": "New", "cols": (1, 1, 1)},
{"key": importKeys[1], "name": "Minor", "cols": (2, 2, 2)}, {"key": importKeys[1], "name": "Minor", "cols": (2, 2, 2)},
@@ -851,7 +851,7 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
# Trash folder # Trash folder
# Should create on first call, and just returned on later calls # Should create on first call, and just returned on later calls
hTrash = "0000000000018" hTrash = "0000000000018"
assert theProject.projTree[hTrash] is None assert theProject.tree[hTrash] is None
assert theProject.trashFolder() == hTrash assert theProject.trashFolder() == hTrash
assert theProject.trashFolder() == hTrash assert theProject.trashFolder() == hTrash
@@ -929,11 +929,11 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
"0000000000010", "0000000000011", "0000000000012", "0000000000010", "0000000000011", "0000000000012",
"0000000000016", "0000000000017", "0000000000016", "0000000000017",
] ]
assert theProject.projTree.handles() == oldOrder assert theProject.tree.handles() == oldOrder
assert theProject.setTreeOrder(newOrder) assert theProject.setTreeOrder(newOrder)
assert theProject.projTree.handles() == newOrder assert theProject.tree.handles() == newOrder
assert theProject.setTreeOrder(oldOrder) assert theProject.setTreeOrder(oldOrder)
assert theProject.projTree.handles() == oldOrder assert theProject.tree.handles() == oldOrder
# Session stats # Session stats
theProject.currWCount = 200 theProject.currWCount = 200
@@ -1003,7 +1003,7 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
theProject = NWProject(mockGUI) theProject = NWProject(mockGUI)
assert theProject.openProject(nwLipsum) is True assert theProject.openProject(nwLipsum) is True
assert theProject.projTree["636b6aa9b697b"] is None assert theProject.tree["636b6aa9b697b"] is None
# Add a file with non-existent parent # Add a file with non-existent parent
# This file will be renoved from the project on open # This file will be renoved from the project on open
@@ -1041,11 +1041,11 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
assert theProject.openProject(nwLipsum) assert theProject.openProject(nwLipsum)
assert theProject.projPath is not None assert theProject.projPath is not None
assert theProject.projTree["636b6aa9b697bb"] is None assert theProject.tree["636b6aa9b697bb"] is None
assert theProject.projTree["abcdefghijklm"] is None assert theProject.tree["abcdefghijklm"] is None
# First Item with Meta Data # First Item with Meta Data
oItem = theProject.projTree["636b6aa9b697b"] oItem = theProject.tree["636b6aa9b697b"]
assert oItem is not None assert oItem is not None
assert oItem.itemName == "[Recovered] Mars" assert oItem.itemName == "[Recovered] Mars"
assert oItem.itemHandle == "636b6aa9b697b" assert oItem.itemHandle == "636b6aa9b697b"
@@ -1055,7 +1055,7 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
assert oItem.itemLayout == nwItemLayout.NOTE assert oItem.itemLayout == nwItemLayout.NOTE
# Second Item without Meta Data # Second Item without Meta Data
oItem = theProject.projTree["736b6aa9b697b"] oItem = theProject.tree["736b6aa9b697b"]
assert oItem is not None assert oItem is not None
assert oItem.itemName == "Recovered File 1" assert oItem.itemName == "Recovered File 1"
assert oItem.itemHandle == "736b6aa9b697b" assert oItem.itemHandle == "736b6aa9b697b"
+2 -1
View File
@@ -24,7 +24,8 @@ import pytest
from tools import readFile from tools import readFile
from novelwriter.core import NWProject, NWIndex, ToHtml from novelwriter.core import NWProject, ToHtml
from novelwriter.core.index import NWIndex
@pytest.mark.core @pytest.mark.core
+2 -1
View File
@@ -24,7 +24,8 @@ import pytest
from tools import readFile from tools import readFile
from novelwriter.core import NWProject, NWIndex, ToMarkdown from novelwriter.core import NWProject, ToMarkdown
from novelwriter.core.index import NWIndex
@pytest.mark.core @pytest.mark.core
+2 -1
View File
@@ -28,7 +28,8 @@ from shutil import copyfile
from tools import cmpFiles from tools import cmpFiles
from novelwriter.core import NWProject, NWIndex, ToOdt from novelwriter.core import NWProject, ToOdt
from novelwriter.core.index import NWIndex
from novelwriter.core.toodt import ODTParagraphStyle, ODTTextStyle, XMLParagraph, _mkTag from novelwriter.core.toodt import ODTParagraphStyle, ODTTextStyle, XMLParagraph, _mkTag
XML_NS = [ XML_NS = [
+2 -2
View File
@@ -65,9 +65,9 @@ def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
assert nwGUI.editItem() is False assert nwGUI.editItem() is False
# Invalid Type # Invalid Type
nwGUI.theProject.projTree[tHandle]._type = nwItemType.NO_TYPE nwGUI.theProject.tree[tHandle]._type = nwItemType.NO_TYPE
assert nwGUI.editItem() is False assert nwGUI.editItem() is False
nwGUI.theProject.projTree[tHandle]._type = nwItemType.FILE nwGUI.theProject.tree[tHandle]._type = nwItemType.FILE
# Open Properly # Open Properly
assert nwGUI.editItem() is True assert nwGUI.editItem() is True
+9 -9
View File
@@ -185,10 +185,10 @@ def testGuiEditor_SaveText(qtbot, monkeypatch, caplog, nwGUI, nwMinimal, ipsumTe
assert "Could not save document." in caplog.text assert "Could not save document." in caplog.text
# Change header level # Change header level
assert nwGUI.theProject.projTree[sHandle].itemLayout == nwItemLayout.DOCUMENT assert nwGUI.theProject.tree[sHandle].itemLayout == nwItemLayout.DOCUMENT
nwGUI.docEditor.replaceText(longText[1:]) nwGUI.docEditor.replaceText(longText[1:])
assert nwGUI.docEditor.saveText() is True assert nwGUI.docEditor.saveText() is True
assert nwGUI.theProject.projTree[sHandle].itemLayout == nwItemLayout.DOCUMENT assert nwGUI.theProject.tree[sHandle].itemLayout == nwItemLayout.DOCUMENT
# Regular save # Regular save
assert nwGUI.docEditor.saveText() is True assert nwGUI.docEditor.saveText() is True
@@ -236,9 +236,9 @@ def testGuiEditor_MetaData(qtbot, monkeypatch, nwGUI, nwMinimal):
assert nwGUI.docEditor.setCursorPosition(None) is False assert nwGUI.docEditor.setCursorPosition(None) is False
assert nwGUI.docEditor.setCursorPosition(10) is True assert nwGUI.docEditor.setCursorPosition(10) is True
assert nwGUI.docEditor.getCursorPosition() == 10 assert nwGUI.docEditor.getCursorPosition() == 10
assert nwGUI.theProject.projTree[sHandle].cursorPos != 10 assert nwGUI.theProject.tree[sHandle].cursorPos != 10
nwGUI.docEditor.saveCursorPosition() nwGUI.docEditor.saveCursorPosition()
assert nwGUI.theProject.projTree[sHandle].cursorPos == 10 assert nwGUI.theProject.tree[sHandle].cursorPos == 10
assert nwGUI.docEditor.setCursorLine(None) is False assert nwGUI.docEditor.setCursorLine(None) is False
assert nwGUI.docEditor.setCursorLine(2) is True assert nwGUI.docEditor.setCursorLine(2) is True
@@ -1226,8 +1226,8 @@ def testGuiEditor_WordCounters(qtbot, monkeypatch, caplog, nwGUI, nwMinimal, ips
# Open a document and populate it # Open a document and populate it
sHandle = "8c659a11cd429" sHandle = "8c659a11cd429"
nwGUI.theProject.projTree[sHandle]._initCount = 0 # Clear item's count nwGUI.theProject.tree[sHandle]._initCount = 0 # Clear item's count
nwGUI.theProject.projTree[sHandle]._wordCount = 0 # Clear item's count nwGUI.theProject.tree[sHandle]._wordCount = 0 # Clear item's count
assert nwGUI.openDocument(sHandle) is True assert nwGUI.openDocument(sHandle) is True
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
@@ -1253,9 +1253,9 @@ def testGuiEditor_WordCounters(qtbot, monkeypatch, caplog, nwGUI, nwMinimal, ips
nwGUI.docEditor.wCounterDoc.run() nwGUI.docEditor.wCounterDoc.run()
# nwGUI.docEditor._updateDocCounts(cC, wC, pC) # nwGUI.docEditor._updateDocCounts(cC, wC, pC)
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
assert nwGUI.theProject.projTree[sHandle]._charCount == cC assert nwGUI.theProject.tree[sHandle]._charCount == cC
assert nwGUI.theProject.projTree[sHandle]._wordCount == wC assert nwGUI.theProject.tree[sHandle]._wordCount == wC
assert nwGUI.theProject.projTree[sHandle]._paraCount == pC assert nwGUI.theProject.tree[sHandle]._paraCount == pC
assert nwGUI.docEditor.docFooter.wordsText.text() == f"Words: {wC} (+{wC})" assert nwGUI.docEditor.docFooter.wordsText.text() == f"Words: {wC} (+{wC})"
# Select all text # Select all text
+3 -3
View File
@@ -47,8 +47,8 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
# Rebuild the index # Rebuild the index
nwGUI.mainMenu.aRebuildIndex.activate(QAction.Trigger) nwGUI.mainMenu.aRebuildIndex.activate(QAction.Trigger)
assert nwGUI.theIndex._tagIndex != {} assert nwGUI.theProject.index._tagsIndex._tags != {}
assert nwGUI.theIndex._refIndex != {} assert nwGUI.theProject.index._itemIndex._items != {}
# Select a document in the project tree # Select a document in the project tree
nwGUI.treeView.setSelectedHandle("88243afbe5ed8") nwGUI.treeView.setSelectedHandle("88243afbe5ed8")
@@ -140,7 +140,7 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
nwGUI.docViewer.reloadText() nwGUI.docViewer.reloadText()
# Change document title # Change document title
nwItem = nwGUI.theProject.projTree["4c4f28287af27"] nwItem = nwGUI.theProject.tree["4c4f28287af27"]
nwItem.setName("Test Title") nwItem.setName("Test Title")
assert nwItem.itemName == "Test Title" assert nwItem.itemName == "Test Title"
nwGUI.docViewer.updateDocInfo("4c4f28287af27") nwGUI.docViewer.updateDocInfo("4c4f28287af27")
+10 -10
View File
@@ -180,10 +180,10 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
assert nwGUI.saveProject() assert nwGUI.saveProject()
assert nwGUI.closeProject() assert nwGUI.closeProject()
assert len(nwGUI.theProject.projTree) == 0 assert len(nwGUI.theProject.tree) == 0
assert len(nwGUI.theProject.projTree._treeOrder) == 0 assert len(nwGUI.theProject.tree._treeOrder) == 0
assert len(nwGUI.theProject.projTree._treeRoots) == 0 assert len(nwGUI.theProject.tree._treeRoots) == 0
assert nwGUI.theProject.projTree.trashRoot() is None assert nwGUI.theProject.tree.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"
@@ -207,10 +207,10 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
qtbot.wait(stepDelay) qtbot.wait(stepDelay)
# Check that we loaded the data # Check that we loaded the data
assert len(nwGUI.theProject.projTree) == 8 assert len(nwGUI.theProject.tree) == 8
assert len(nwGUI.theProject.projTree._treeOrder) == 8 assert len(nwGUI.theProject.tree._treeOrder) == 8
assert len(nwGUI.theProject.projTree._treeRoots) == 4 assert len(nwGUI.theProject.tree._treeRoots) == 4
assert nwGUI.theProject.projTree.trashRoot() is None assert nwGUI.theProject.tree.trashRoot() is None
assert nwGUI.theProject.projPath == fncProj assert nwGUI.theProject.projPath == fncProj
assert nwGUI.theProject.projMeta == os.path.join(fncProj, "meta") assert nwGUI.theProject.projMeta == os.path.join(fncProj, "meta")
assert nwGUI.theProject.projFile == "nwProject.nwx" assert nwGUI.theProject.projFile == "nwProject.nwx"
@@ -463,11 +463,11 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
# Check a Quick Create and Delete # Check a Quick Create and Delete
assert nwGUI.treeView.newTreeItem(nwItemType.FILE, None) assert nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
newHandle = nwGUI.treeView.getSelectedHandle() newHandle = nwGUI.treeView.getSelectedHandle()
assert nwGUI.theProject.projTree["0000000000020"] is not None assert nwGUI.theProject.tree["0000000000020"] is not None
assert nwGUI.treeView.deleteItem() assert nwGUI.treeView.deleteItem()
assert nwGUI.treeView.setSelectedHandle(newHandle) assert nwGUI.treeView.setSelectedHandle(newHandle)
assert nwGUI.treeView.deleteItem() assert nwGUI.treeView.deleteItem()
assert nwGUI.theProject.projTree["0000000000024"] is not None # Trash assert nwGUI.theProject.tree["0000000000024"] is not None # Trash
assert nwGUI.saveProject() assert nwGUI.saveProject()
# Check the files # Check the files
+1 -1
View File
@@ -87,7 +87,7 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
assert outlineData.itemValue.text() == "Finished" assert outlineData.itemValue.text() == "Finished"
# Click POV Link # Click POV Link
assert outlineData.povKeyValue.text() == "<a href='#pov=Bod'>Bod</a>" assert outlineData.povKeyValue.text() == "<a href='Bod'>Bod</a>"
outlineData._tagClicked("#pov=Bod") outlineData._tagClicked("#pov=Bod")
assert nwGUI.docViewer.docHandle() == "4c4f28287af27" assert nwGUI.docViewer.docHandle() == "4c4f28287af27"
+25 -25
View File
@@ -63,7 +63,7 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd)
# Create root item # Create root item
assert nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.WORLD) is True assert nwTree.newTreeItem(nwItemType.ROOT, nwItemClass.WORLD) is True
assert "0000000000010" in nwGUI.theProject.projTree assert "0000000000010" in nwGUI.theProject.tree
# File/Folder Items # File/Folder Items
# ================= # =================
@@ -78,42 +78,42 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd)
# Create new folder as child of Novel folder # Create new folder as child of Novel folder
nwTree.setSelectedHandle("0000000000008") nwTree.setSelectedHandle("0000000000008")
assert nwTree.newTreeItem(nwItemType.FOLDER) is True assert nwTree.newTreeItem(nwItemType.FOLDER) is True
assert nwGUI.theProject.projTree["0000000000011"].itemParent == "0000000000008" assert nwGUI.theProject.tree["0000000000011"].itemParent == "0000000000008"
assert nwGUI.theProject.projTree["0000000000011"].itemRoot == "0000000000008" assert nwGUI.theProject.tree["0000000000011"].itemRoot == "0000000000008"
assert nwGUI.theProject.projTree["0000000000011"].itemClass == nwItemClass.NOVEL assert nwGUI.theProject.tree["0000000000011"].itemClass == nwItemClass.NOVEL
# Add a new file in the new folder # Add a new file in the new folder
nwTree.setSelectedHandle("0000000000011") nwTree.setSelectedHandle("0000000000011")
assert nwTree.newTreeItem(nwItemType.FILE) is True assert nwTree.newTreeItem(nwItemType.FILE) is True
assert nwGUI.theProject.projTree["0000000000012"].itemParent == "0000000000011" assert nwGUI.theProject.tree["0000000000012"].itemParent == "0000000000011"
assert nwGUI.theProject.projTree["0000000000012"].itemRoot == "0000000000008" assert nwGUI.theProject.tree["0000000000012"].itemRoot == "0000000000008"
assert nwGUI.theProject.projTree["0000000000012"].itemClass == nwItemClass.NOVEL assert nwGUI.theProject.tree["0000000000012"].itemClass == nwItemClass.NOVEL
# Add a new file next to the other new file # Add a new file next to the other new file
nwTree.setSelectedHandle("0000000000012") nwTree.setSelectedHandle("0000000000012")
assert nwTree.newTreeItem(nwItemType.FILE) is True assert nwTree.newTreeItem(nwItemType.FILE) is True
assert nwGUI.theProject.projTree["0000000000013"].itemParent == "0000000000011" assert nwGUI.theProject.tree["0000000000013"].itemParent == "0000000000011"
assert nwGUI.theProject.projTree["0000000000013"].itemRoot == "0000000000008" assert nwGUI.theProject.tree["0000000000013"].itemRoot == "0000000000008"
assert nwGUI.theProject.projTree["0000000000013"].itemClass == nwItemClass.NOVEL assert nwGUI.theProject.tree["0000000000013"].itemClass == nwItemClass.NOVEL
assert nwGUI.openDocument("0000000000013") assert nwGUI.openDocument("0000000000013")
assert nwGUI.docEditor.getText() == "### New Document\n\n" assert nwGUI.docEditor.getText() == "### New Document\n\n"
# Add a new file to the characters folder # Add a new file to the characters folder
nwTree.setSelectedHandle("000000000000a") nwTree.setSelectedHandle("000000000000a")
assert nwTree.newTreeItem(nwItemType.FILE) is True assert nwTree.newTreeItem(nwItemType.FILE) is True
assert nwGUI.theProject.projTree["0000000000014"].itemParent == "000000000000a" assert nwGUI.theProject.tree["0000000000014"].itemParent == "000000000000a"
assert nwGUI.theProject.projTree["0000000000014"].itemRoot == "000000000000a" assert nwGUI.theProject.tree["0000000000014"].itemRoot == "000000000000a"
assert nwGUI.theProject.projTree["0000000000014"].itemClass == nwItemClass.CHARACTER assert nwGUI.theProject.tree["0000000000014"].itemClass == nwItemClass.CHARACTER
assert nwGUI.openDocument("0000000000014") assert nwGUI.openDocument("0000000000014")
assert nwGUI.docEditor.getText() == "# New Note\n\n" assert nwGUI.docEditor.getText() == "# New Note\n\n"
# Make sure the sibling folder bug trap works # Make sure the sibling folder bug trap works
nwTree.setSelectedHandle("0000000000013") nwTree.setSelectedHandle("0000000000013")
nwGUI.theProject.projTree["0000000000013"].setParent(None) # This should not happen nwGUI.theProject.tree["0000000000013"].setParent(None) # This should not happen
caplog.clear() caplog.clear()
assert nwTree.newTreeItem(nwItemType.FILE) is False assert nwTree.newTreeItem(nwItemType.FILE) is False
assert "Internal error" in caplog.text assert "Internal error" in caplog.text
nwGUI.theProject.projTree["0000000000013"].setParent("0000000000011") nwGUI.theProject.tree["0000000000013"].setParent("0000000000011")
# Get the trash folder # Get the trash folder
nwTree._addTrashRoot() nwTree._addTrashRoot()
@@ -242,22 +242,22 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
# =========== # ===========
nwTree.setSelectedHandle("0000000000008") nwTree.setSelectedHandle("0000000000008")
assert nwGUI.theProject.projTree._treeOrder.index("0000000000008") == 0 assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0
# Move novel folder up # Move novel folder up
assert nwTree.moveTreeItem(-1) is False assert nwTree.moveTreeItem(-1) is False
nwTree.flushTreeOrder() nwTree.flushTreeOrder()
assert nwGUI.theProject.projTree._treeOrder.index("0000000000008") == 0 assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0
# Move novel folder down # Move novel folder down
assert nwTree.moveTreeItem(1) is True assert nwTree.moveTreeItem(1) is True
nwTree.flushTreeOrder() nwTree.flushTreeOrder()
assert nwGUI.theProject.projTree._treeOrder.index("0000000000008") == 1 assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 1
# Move novel folder up again # Move novel folder up again
assert nwTree.moveTreeItem(-1) is True assert nwTree.moveTreeItem(-1) is True
nwTree.flushTreeOrder() nwTree.flushTreeOrder()
assert nwGUI.theProject.projTree._treeOrder.index("0000000000008") == 0 assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0
# Clean up # Clean up
# qtbot.stopForInteraction() # qtbot.stopForInteraction()
@@ -341,7 +341,7 @@ def testGuiProjTree_DeleteItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockR
"000000000000d", "000000000000e", "000000000000f", "000000000000d", "000000000000e", "000000000000f",
"0000000000010" "0000000000010"
] ]
trashHandle = nwGUI.theProject.projTree.trashRoot() trashHandle = nwGUI.theProject.tree.trashRoot()
assert nwTree.getTreeFromHandle(trashHandle) == [ assert nwTree.getTreeFromHandle(trashHandle) == [
trashHandle, "0000000000012", "0000000000011" trashHandle, "0000000000012", "0000000000011"
] ]
@@ -349,30 +349,30 @@ def testGuiProjTree_DeleteItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockR
# Delete the first file again (permanent), and ask for permission # Delete the first file again (permanent), and ask for permission
# Also open the document in the editor, which should trigger a close # Also open the document in the editor, which should trigger a close
assert os.path.isfile(os.path.join(prjDir, "content", "0000000000012.nwd")) assert os.path.isfile(os.path.join(prjDir, "content", "0000000000012.nwd"))
assert "0000000000012" in nwGUI.theProject.projTree assert "0000000000012" in nwGUI.theProject.tree
assert nwGUI.docEditor.docHandle() is None assert nwGUI.docEditor.docHandle() is None
assert nwGUI.openDocument("0000000000012") is True assert nwGUI.openDocument("0000000000012") is True
assert nwGUI.docEditor.docHandle() == "0000000000012" assert nwGUI.docEditor.docHandle() == "0000000000012"
assert nwTree.deleteItem("0000000000012") is True assert nwTree.deleteItem("0000000000012") is True
assert nwGUI.docEditor.docHandle() is None assert nwGUI.docEditor.docHandle() is None
assert not os.path.isfile(os.path.join(prjDir, "content", "0000000000012.nwd")) assert not os.path.isfile(os.path.join(prjDir, "content", "0000000000012.nwd"))
assert "0000000000012" not in nwGUI.theProject.projTree assert "0000000000012" not in nwGUI.theProject.tree
assert nwTree.getTreeFromHandle(trashHandle) == [ assert nwTree.getTreeFromHandle(trashHandle) == [
trashHandle, "0000000000011" trashHandle, "0000000000011"
] ]
# Delete the second file, and skip asking for permission # Delete the second file, and skip asking for permission
assert os.path.isfile(os.path.join(prjDir, "content", "0000000000011.nwd")) assert os.path.isfile(os.path.join(prjDir, "content", "0000000000011.nwd"))
assert "0000000000011" in nwGUI.theProject.projTree assert "0000000000011" in nwGUI.theProject.tree
assert nwTree.deleteItem("0000000000011", alreadyAsked=True) is True assert nwTree.deleteItem("0000000000011", alreadyAsked=True) is True
assert not os.path.isfile(os.path.join(prjDir, "content", "0000000000011.nwd")) assert not os.path.isfile(os.path.join(prjDir, "content", "0000000000011.nwd"))
assert "0000000000011" not in nwGUI.theProject.projTree assert "0000000000011" not in nwGUI.theProject.tree
assert nwTree.getTreeFromHandle(trashHandle) == [trashHandle] assert nwTree.getTreeFromHandle(trashHandle) == [trashHandle]
# Delete Folder # Delete Folder
# ============= # =============
trashHandle = nwGUI.theProject.projTree.trashRoot() trashHandle = nwGUI.theProject.tree.trashRoot()
# Add a folder with two files # Add a folder with two files
nwTree.setSelectedHandle("0000000000009") nwTree.setSelectedHandle("0000000000009")