From 8bdd09400ad20290ac74ec3d273ff927c9db82b1 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 28 May 2022 14:11:58 +0200 Subject: [PATCH] Move the project index into the project class --- novelwriter/core/project.py | 16 +++++++++++++--- novelwriter/core/tohtml.py | 2 +- novelwriter/core/tomd.py | 2 +- novelwriter/core/toodt.py | 2 +- novelwriter/dialogs/projdetails.py | 9 ++++----- novelwriter/gui/custom.py | 10 +++++----- novelwriter/gui/doceditor.py | 13 ++++++------- novelwriter/gui/dochighlight.py | 7 ++++--- novelwriter/gui/docviewer.py | 4 ++-- novelwriter/gui/itemdetails.py | 2 +- novelwriter/gui/noveltree.py | 11 ++++++----- novelwriter/gui/outline.py | 9 ++++----- novelwriter/gui/outlinedetails.py | 6 +++--- novelwriter/gui/projtree.py | 17 +++++++++-------- novelwriter/guimain.py | 17 ++++++++--------- tests/mock.py | 1 - tests/test_gui/test_gui_docviewer.py | 4 ++-- 17 files changed, 70 insertions(+), 62 deletions(-) diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index b791f545..24a281b6 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -37,6 +37,7 @@ from PyQt5.QtCore import QCoreApplication from novelwriter.core.tree import NWTree from novelwriter.core.item import NWItem +from novelwriter.core.index import NWIndex from novelwriter.core.status import NWStatus from novelwriter.core.options import OptionState from novelwriter.core.document import NWDoc @@ -62,9 +63,10 @@ class NWProject(): self.mainConf = novelwriter.CONFIG # Core Elements - self.optState = OptionState(self) # Project-specific GUI options - self.projTree = NWTree(self) # The project tree - self.langData = {} # Localisation data + self.optState = OptionState(self) # Project-specific GUI options + self.projTree = NWTree(self) # The project tree + self._projIndex = NWIndex(self) # The projecty index + self.langData = {} # Localisation data # Project Status self.projOpened = 0 # The time stamp of when the project file was opened @@ -116,6 +118,14 @@ class NWProject(): return + ## + # Properties + ## + + @property + def index(self): + return self._projIndex + ## # Item Methods ## diff --git a/novelwriter/core/tohtml.py b/novelwriter/core/tohtml.py index baa5165d..86a21786 100644 --- a/novelwriter/core/tohtml.py +++ b/novelwriter/core/tohtml.py @@ -451,7 +451,7 @@ class ToHtml(Tokenizer): def _formatKeywords(self, tText): """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: return "" diff --git a/novelwriter/core/tomd.py b/novelwriter/core/tomd.py index bd468f55..48d23a35 100644 --- a/novelwriter/core/tomd.py +++ b/novelwriter/core/tomd.py @@ -193,7 +193,7 @@ class ToMarkdown(Tokenizer): def _formatKeywords(self, tText, tStyle): """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: return "" diff --git a/novelwriter/core/toodt.py b/novelwriter/core/toodt.py index c0b1daee..59eaf30f 100644 --- a/novelwriter/core/toodt.py +++ b/novelwriter/core/toodt.py @@ -550,7 +550,7 @@ class ToOdt(Tokenizer): def _formatKeywords(self, tText): """Apply formatting to keywords. """ - isValid, theBits, _ = self.theParent.theIndex.scanThis("@"+tText) + isValid, theBits, _ = self.theProject.index.scanThis("@"+tText) if not isValid or not theBits: return "" diff --git a/novelwriter/dialogs/projdetails.py b/novelwriter/dialogs/projdetails.py index 54b6c995..491df296 100644 --- a/novelwriter/dialogs/projdetails.py +++ b/novelwriter/dialogs/projdetails.py @@ -145,7 +145,6 @@ class GuiProjectDetailsMain(QWidget): self.theParent = theParent self.theProject = theProject self.theTheme = theParent.theTheme - self.theIndex = theParent.theIndex fPx = self.theTheme.fontPixelSize fPt = self.theTheme.fontPointSize @@ -245,8 +244,9 @@ class GuiProjectDetailsMain(QWidget): def updateValues(self): """Set all the values. """ - hCounts = self.theIndex.getNovelTitleCounts() - nwCount = self.theIndex.getNovelWordCount() + pIndex = self.theProject.index + hCounts = pIndex.getNovelTitleCounts() + nwCount = pIndex.getNovelWordCount() edTime = self.theProject.getCurrentEditTime() self.wordCountVal.setText(f"{nwCount:n}") @@ -277,7 +277,6 @@ class GuiProjectDetailsContents(QWidget): self.theParent = theParent self.theProject = theProject self.theTheme = theParent.theTheme - self.theIndex = theParent.theIndex self.optState = theProject.optState # Internal @@ -424,7 +423,7 @@ class GuiProjectDetailsContents(QWidget): """Extract the data for the tree. """ self._theToC = [] - self._theToC = self.theIndex.getTableOfContents(2) + self._theToC = self.theProject.index.getTableOfContents(2) self._theToC.append(("", 0, self.tr("END"), 0)) return diff --git a/novelwriter/gui/custom.py b/novelwriter/gui/custom.py index 16d26b40..62dd3c91 100644 --- a/novelwriter/gui/custom.py +++ b/novelwriter/gui/custom.py @@ -409,10 +409,10 @@ class PagedDialog(QDialog): return - def addTab(self, tabWidget, tabLabel): + def addTab(self, widget, label): """Forwards the adding of tabs to the QTabWidget. """ - self._tabBox.addTab(tabWidget, tabLabel) + self._tabBox.addTab(widget, label) return def addControls(self, buttonBar): @@ -431,15 +431,15 @@ class VerticalTabBar(QTabBar): self._mW = novelwriter.CONFIG.pxInt(150) return - def tabSizeHint(self, theIndex): + def tabSizeHint(self, index): """Returns a transposed size hint for the rotated bar. """ - tSize = QTabBar.tabSizeHint(self, theIndex) + tSize = QTabBar.tabSizeHint(self, index) tSize.transpose() tSize.setWidth(min(tSize.width(), self._mW)) return tSize - def paintEvent(self, theEvent): + def paintEvent(self, event): """Custom implementation of the label painter that rotates the label 90 degrees. """ diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 98648ab6..9cd99497 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -79,7 +79,6 @@ class GuiDocEditor(QTextEdit): self.mainConf = novelwriter.CONFIG self.theParent = theParent self.theTheme = theParent.theTheme - self.theIndex = theParent.theIndex self.theProject = theParent.theProject self._nwDocument = None @@ -401,7 +400,7 @@ class GuiDocEditor(QTextEdit): self.document().rootFrame().setFrameFormat(docFrame) self.docFooter.updateLineCount() - self._docHeaders = self.theIndex.getHandleHeaders(self._docHandle) + self._docHeaders = self.theProject.index.getHandleHeaders(self._docHandle) qApp.processEvents() self.document().clearUndoRedoStacks() @@ -506,9 +505,9 @@ class GuiDocEditor(QTextEdit): self.setDocumentChanged(False) - oldHeader = self.theIndex.getHandleHeaderLevel(tHandle) - self.theIndex.scanText(tHandle, docText) - newHeader = self.theIndex.getHandleHeaderLevel(tHandle) + oldHeader = self.theProject.index.getHandleHeaderLevel(tHandle) + self.theProject.index.scanText(tHandle, docText) + newHeader = self.theProject.index.getHandleHeaderLevel(tHandle) if self._updateHeaders(checkLevel=True): self.theParent.requestNovelTreeRefresh() @@ -2003,7 +2002,7 @@ class GuiDocEditor(QTextEdit): if self._docHandle is None: return False - newHeaders = self.theIndex.getHandleHeaders(self._docHandle) + newHeaders = self.theProject.index.getHandleHeaders(self._docHandle) if checkPos: newPos = [x[0] for x in newHeaders] oldPos = [x[0] for x in self._docHeaders] @@ -2943,7 +2942,7 @@ class GuiDocEditFooter(QWidget): else: theStatus, theIcon = self._theItem.getImportStatus() 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)}" self.statusIcon.setPixmap(sIcon) diff --git a/novelwriter/gui/dochighlight.py b/novelwriter/gui/dochighlight.py index eddc27c3..0133f91c 100644 --- a/novelwriter/gui/dochighlight.py +++ b/novelwriter/gui/dochighlight.py @@ -55,7 +55,7 @@ class GuiDocHighlighter(QSyntaxHighlighter): self.spEnchant = spEnchant self.theParent = theParent self.theTheme = theParent.theTheme - self.theIndex = theParent.theIndex + self.theProject = theParent.theProject self.theHandle = None self.spellCheck = False self.spellRx = None @@ -287,9 +287,10 @@ class GuiDocHighlighter(QSyntaxHighlighter): if theText.startswith("@"): # Keywords and commands self.setCurrentBlockState(self.BLOCK_META) + pIndex = self.theProject.index tItem = self.theParent.theProject.projTree[self.theHandle] - isValid, theBits, thePos = self.theIndex.scanThis(theText) - isGood = self.theIndex.checkThese(theBits, tItem) + isValid, theBits, thePos = pIndex.scanThis(theText) + isGood = pIndex.checkThese(theBits, tItem) if isValid: for n, theBit in enumerate(theBits): xPos = thePos[n] diff --git a/novelwriter/gui/docviewer.py b/novelwriter/gui/docviewer.py index 4c293da5..615f121c 100644 --- a/novelwriter/gui/docviewer.py +++ b/novelwriter/gui/docviewer.py @@ -245,7 +245,7 @@ class GuiDocViewer(QTextBrowser): index being up to date. """ logger.debug("Loading document from tag '%s'", theTag) - tHandle, _, sTitle = self.theParent.theIndex.getTagSource(theTag) + tHandle, _, sTitle = self.theProject.index.getTagSource(theTag) if tHandle is None: self.theParent.makeAlert(self.tr( "Could not find the reference for tag '{0}'. It either doesn't " @@ -1199,7 +1199,7 @@ class GuiDocViewDetails(QScrollArea): if self.theParent.docViewer.stickyRef: return - theRefs = self.theParent.theIndex.getBackReferenceList(tHandle) + theRefs = self.theProject.index.getBackReferenceList(tHandle) theList = [] for tHandle in theRefs: tItem = self.theProject.projTree[tHandle] diff --git a/novelwriter/gui/itemdetails.py b/novelwriter/gui/itemdetails.py index 8b42b752..88419395 100644 --- a/novelwriter/gui/itemdetails.py +++ b/novelwriter/gui/itemdetails.py @@ -269,7 +269,7 @@ class GuiItemDetails(QWidget): # Layout # ====== - hLevel = self.theParent.theIndex.getHandleHeaderLevel(tHandle) + hLevel = self.theProject.index.getHandleHeaderLevel(tHandle) usageIcon = self.theTheme.getItemIcon( nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel ) diff --git a/novelwriter/gui/noveltree.py b/novelwriter/gui/noveltree.py index d0732abe..91895c7a 100644 --- a/novelwriter/gui/noveltree.py +++ b/novelwriter/gui/noveltree.py @@ -54,7 +54,6 @@ class GuiNovelTree(QTreeWidget): self.theParent = theParent self.theTheme = theParent.theTheme self.theProject = theParent.theProject - self.theIndex = theParent.theIndex # Internal Variables self._treeMap = {} @@ -137,7 +136,7 @@ class GuiNovelTree(QTreeWidget): """ logger.verbose("Requesting refresh of the novel tree") 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): logger.verbose("No changes have been made to the novel index") return @@ -158,7 +157,7 @@ class GuiNovelTree(QTreeWidget): def updateWordCounts(self, tHandle): """Update the word count for a given handle. """ - tHeaders = self.theIndex.getHandleWordCounts(tHandle) + tHeaders = self.theProject.index.getHandleWordCounts(tHandle) for titleKey, wCount in tHeaders: if titleKey in self._treeMap: self._treeMap[titleKey].setText(self.C_WORDS, f"{wCount:n}") @@ -252,7 +251,9 @@ class GuiNovelTree(QTreeWidget): currChapter = None currScene = None - for tKey, tHandle, sTitle, novIdx in self.theIndex.novelStructure(skipExcluded=True): + for tKey, tHandle, sTitle, novIdx in self.theProject.index.novelStructure( + skipExcluded=True + ): tItem = self._createTreeItem(tHandle, sTitle, tKey, novIdx) self._treeMap[tKey] = tItem @@ -315,7 +316,7 @@ class GuiNovelTree(QTreeWidget): newItem.setText(self.C_WORDS, f"{wC:n}") 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])) return newItem diff --git a/novelwriter/gui/outline.py b/novelwriter/gui/outline.py index 4028ccf6..2b7a654b 100644 --- a/novelwriter/gui/outline.py +++ b/novelwriter/gui/outline.py @@ -91,7 +91,6 @@ class GuiOutline(QTreeWidget): self.theParent = theParent self.theProject = theParent.theProject self.theTheme = theParent.theTheme - self.theIndex = theParent.theIndex self.optState = theParent.theProject.optState self.headerMenu = GuiOutlineHeaderMenu(self) @@ -182,7 +181,7 @@ class GuiOutline(QTreeWidget): # If the novel index or novel tree has changed since the tree # 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 if doBuild or overRide: logger.debug("Rebuilding Project Outline") @@ -388,7 +387,7 @@ class GuiOutline(QTreeWidget): currChapter = None currScene = None - for tKey, tHandle, sTitle, novIdx in self.theIndex.novelStructure(skipExcluded=True): + for _, tHandle, sTitle, novIdx in self.theProject.index.novelStructure(skipExcluded=True): tItem = self._createTreeItem(tHandle, sTitle, novIdx) @@ -442,7 +441,7 @@ class GuiOutline(QTreeWidget): newItem = QTreeWidgetItem() 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) cC = int(novIdx["cCount"]) @@ -465,7 +464,7 @@ class GuiOutline(QTreeWidget): newItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], 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.FOCUS], ", ".join(theRefs[nwKeyWords.FOCUS_KEY])) newItem.setText(self._colIdx[nwOutline.CHAR], ", ".join(theRefs[nwKeyWords.CHAR_KEY])) diff --git a/novelwriter/gui/outlinedetails.py b/novelwriter/gui/outlinedetails.py index 00c20e44..92d41c3c 100644 --- a/novelwriter/gui/outlinedetails.py +++ b/novelwriter/gui/outlinedetails.py @@ -58,7 +58,6 @@ class GuiOutlineDetails(QScrollArea): self.theParent = theParent self.theProject = theParent.theProject self.theTheme = theParent.theTheme - self.theIndex = theParent.theIndex self.optState = theParent.theProject.optState # Sizes @@ -283,9 +282,10 @@ class GuiOutlineDetails(QScrollArea): """Update the content of the tree with the given handle and line number pointing to a header. """ + pIndex = self.theProject.index nwItem = self.theProject.projTree[tHandle] - novIdx = self.theIndex.getNovelData(tHandle, sTitle) - theRefs = self.theIndex.getReferences(tHandle, sTitle) + novIdx = pIndex.getNovelData(tHandle, sTitle) + theRefs = pIndex.getReferences(tHandle, sTitle) if nwItem is None or novIdx is None: return False diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index b134b901..fd9e21ce 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -61,7 +61,6 @@ class GuiProjectTree(QTreeWidget): self.theParent = theParent self.theTheme = theParent.theTheme self.theProject = theParent.theProject - self.theIndex = theParent.theIndex # Internal Variables self._treeMap = {} @@ -236,12 +235,14 @@ class GuiProjectTree(QTreeWidget): else: newText = f"# {nwItem.itemName}\n\n" + pIndex = self.theProject.index + # Save the text and index it newDoc.writeDocument(newText) - self.theIndex.scanText(tHandle, newText) + pIndex.scanText(tHandle, newText) # Get Word Counts - cC, wC, pC = self.theIndex.getCounts(tHandle) + cC, wC, pC = pIndex.getCounts(tHandle) nwItem.setCharCount(cC) nwItem.setWordCount(wC) nwItem.setParaCount(pC) @@ -542,7 +543,7 @@ class GuiProjectTree(QTreeWidget): expIcon = self.theTheme.getIcon("cross") itempStatus, statusIcon = nwItem.getImportStatus() - hLevel = self.theIndex.getHandleHeaderLevel(tHandle) + hLevel = self.theProject.index.getHandleHeaderLevel(tHandle) itemIcon = self.theTheme.getItemIcon( nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, hLevel ) @@ -598,7 +599,7 @@ class GuiProjectTree(QTreeWidget): if self.theProject.projTree.checkType(pHandle, nwItemType.FILE): # A file has an internal word count we need to account # 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) @@ -817,9 +818,9 @@ class GuiProjectTree(QTreeWidget): # Update the index if nwItemS.isInactive(): - self.theIndex.deleteHandle(mHandle) + self.theProject.index.deleteHandle(mHandle) else: - self.theIndex.reIndexHandle(mHandle) + self.theProject.index.reIndexHandle(mHandle) self.setTreeItemValues(mHandle) @@ -854,7 +855,7 @@ class GuiProjectTree(QTreeWidget): ], nwAlert.ERROR) return False - self.theIndex.deleteHandle(tHandle) + self.theProject.index.deleteHandle(tHandle) del self.theProject.projTree[tHandle] self._treeMap.pop(tHandle, None) diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index a759972a..34f9abcd 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -50,7 +50,7 @@ from novelwriter.dialogs import ( from novelwriter.tools import ( GuiBuildNovel, GuiLipsum, GuiProjectWizard, GuiWritingStats ) -from novelwriter.core import NWProject, NWIndex +from novelwriter.core import NWProject from novelwriter.enum import ( nwItemType, nwItemClass, nwAlert, nwWidget, nwState, nwView ) @@ -86,7 +86,6 @@ class GuiMain(QMainWindow): # Core Classes and Settings self.theTheme = GuiTheme() self.theProject = NWProject(self) - self.theIndex = NWIndex(self.theProject) self.hasProject = False self.isFocusMode = False self.idleRefTime = time() @@ -420,7 +419,7 @@ class GuiMain(QMainWindow): self.idleRefTime = time() self.idleTime = 0.0 - self.theIndex.clearIndex() + self.theProject.index.clearIndex() self.clearGUI() self.hasProject = False self._changeView(nwView.PROJECT) @@ -497,7 +496,7 @@ class GuiMain(QMainWindow): self.idleTime = 0.0 # Load the tag index - self.theIndex.loadIndex() + self.theProject.index.loadIndex() # Update GUI self._updateWindowTitle(self.theProject.projName) @@ -516,7 +515,7 @@ class GuiMain(QMainWindow): self.viewDocument(self.theProject.lastViewed) # Check if we need to rebuild the index - if self.theIndex.indexBroken: + if self.theProject.index.indexBroken: self.makeAlert(self.tr( "The project index is outdated or broken. Rebuilding index." ), nwAlert.INFO) @@ -540,7 +539,7 @@ class GuiMain(QMainWindow): self.treeView.saveTreeOrder() if self.theProject.saveProject(autoSave=autoSave): - self.theIndex.saveIndex() + self.theProject.index.saveIndex() return True @@ -863,7 +862,7 @@ class GuiMain(QMainWindow): tStart = time() self.treeView.saveTreeOrder() - self.theIndex.clearIndex() + self.theProject.index.clearIndex() for tItem in self.theProject.projTree: @@ -874,10 +873,10 @@ class GuiMain(QMainWindow): if tItem is not None and tItem.itemType == nwItemType.FILE: logger.verbose("Scanning '%s'", tItem.itemName) - self.theIndex.reIndexHandle(tItem.itemHandle) + self.theProject.index.reIndexHandle(tItem.itemHandle) # Get Word Counts - cC, wC, pC = self.theIndex.getCounts(tItem.itemHandle) + cC, wC, pC = self.theProject.index.getCounts(tItem.itemHandle) tItem.setCharCount(cC) tItem.setWordCount(wC) tItem.setParaCount(pC) diff --git a/tests/mock.py b/tests/mock.py index 4b272a17..23938d41 100644 --- a/tests/mock.py +++ b/tests/mock.py @@ -29,7 +29,6 @@ class MockGuiMain(): def __init__(self): self.mainConf = None self.hasProject = True - self.theIndex = None self.theProject = None self.statusBar = MockStatusBar() diff --git a/tests/test_gui/test_gui_docviewer.py b/tests/test_gui/test_gui_docviewer.py index 0a11bc3d..48f61eff 100644 --- a/tests/test_gui/test_gui_docviewer.py +++ b/tests/test_gui/test_gui_docviewer.py @@ -47,8 +47,8 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, nwLipsum): # Rebuild the index nwGUI.mainMenu.aRebuildIndex.activate(QAction.Trigger) - assert nwGUI.theIndex._tagIndex != {} - assert nwGUI.theIndex._refIndex != {} + assert nwGUI.theProject.index._tagIndex != {} + assert nwGUI.theProject.index._refIndex != {} # Select a document in the project tree nwGUI.treeView.setSelectedHandle("88243afbe5ed8")