From ba5e5f4bb57e7c2d38289abe10b7a396f040cf00 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 15 May 2021 23:57:31 +0200 Subject: [PATCH 1/8] Make GuiDocEditor variables private --- nw/gui/doceditor.py | 454 ++++++++++++++------------- nw/gui/docviewer.py | 2 +- nw/gui/projtree.py | 2 +- nw/guimain.py | 16 +- tests/test_gui/test_gui_doceditor.py | 6 +- tests/test_gui/test_gui_noveltree.py | 4 +- 6 files changed, 254 insertions(+), 230 deletions(-) diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index ebcd16f1..6736accb 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -76,39 +76,39 @@ class GuiDocEditor(QTextEdit): self.theIndex = theParent.theIndex self.theProject = theParent.theProject - self.nwDocument = None - self.nwItem = None + self._nwDocument = None + self._nwItem = None - self.docChanged = False # Flag for changed status of document - self.spellCheck = False # Flag for spell checking enabled - self.theHandle = None # The handle of the open file - self.theHeaders = [] # Record of headers in the file - self.theDict = None # The current spell check dictionary - self.nonWord = "\"'" # Characters to not include in spell checking + self._docChanged = False # Flag for changed status of document + self._docHandle = None # The handle of the open file + self._docHeaders = [] # Record of headers in the file + + self._spellCheck = False # Flag for spell checking enabled + self.theDict = None # The current spell check dictionary + self._nonWord = "\"'" # Characters to not include in spell checking # Document Variables - self.charCount = 0 # Character count - self.wordCount = 0 # Word count - self.paraCount = 0 # Paragraph count - self.lastEdit = 0 # Time stamp of last edit - self.lastActive = 0 # Time stamp of last activity - self.lastFind = None # Position of the last found search word - self.bigDoc = False # Flag for very large document size - self.doReplace = False # Switch to temporarily disable auto-replace - self.queuePos = None # Used for delayed change of cursor position + self._charCount = 0 # Character count + self._wordCount = 0 # Word count + self._paraCount = 0 # Paragraph count + self._lastEdit = 0 # Time stamp of last edit + self._lastActive = 0 # Time stamp of last activity + self._lastFind = None # Position of the last found search word + self._bigDoc = False # Flag for very large document size + self._doReplace = False # Switch to temporarily disable auto-replace + self._queuePos = None # Used for delayed change of cursor position # Typography - self.typDQOpen = '"' - self.typDQClose = '"' - self.typSQOpen = "'" - self.typSQClose = "'" - self.typPadChar = " " - self.addPadding = False + self._typDQOpen = '"' + self._typDQClose = '"' + self._typSQOpen = "'" + self._typSQClose = "'" + self._typPadChar = " " # Core Elements and Signals - self.qDocument = self.document() - self.qDocument.contentsChange.connect(self._docChange) - self.qDocument.documentLayout().documentSizeChanged.connect(self._docSizeChanged) + self._qDocument = self.document() + self._qDocument.contentsChange.connect(self._docChange) + self._qDocument.documentLayout().documentSizeChanged.connect(self._docSizeChanged) # Document Title self.docHeader = GuiDocEditHeader(self) @@ -116,7 +116,7 @@ class GuiDocEditor(QTextEdit): self.docSearch = GuiDocEditSearch(self) # Syntax - self.hLight = GuiDocHighlighter(self.qDocument, self.theParent) + self.hLight = GuiDocHighlighter(self._qDocument, self.theParent) # Context Menu self.setContextMenuPolicy(Qt.CustomContextMenu) @@ -167,25 +167,25 @@ class GuiDocEditor(QTextEdit): """Clear the current document and reset all document related flags and counters. """ - self.nwDocument = None + self._nwDocument = None self.setReadOnly(True) self.clear() self.wcTimer.stop() - self.theHandle = None - self.charCount = 0 - self.wordCount = 0 - self.paraCount = 0 - self.lastEdit = 0 - self.lastActive = 0 - self.lastFind = None - self.bigDoc = False - self.doReplace = False - self.queuePos = None + self._docHandle = None + self._charCount = 0 + self._wordCount = 0 + self._paraCount = 0 + self._lastEdit = 0 + self._lastActive = 0 + self._lastFind = None + self._bigDoc = False + self._doReplace = False + self._queuePos = None self.setDocumentChanged(False) - self.docHeader.setTitleFromHandle(self.theHandle) - self.docFooter.setHandle(self.theHandle) + self.docHeader.setTitleFromHandle(self._docHandle) + self.docFooter.setHandle(self._docHandle) return True @@ -195,20 +195,20 @@ class GuiDocEditor(QTextEdit): created, and when the user changes the main editor preferences. """ # Some Constants - self.nonWord = "\"'" - self.nonWord += "".join(self.mainConf.fmtDoubleQuotes) - self.nonWord += "".join(self.mainConf.fmtSingleQuotes) + self._nonWord = "\"'" + self._nonWord += "".join(self.mainConf.fmtDoubleQuotes) + self._nonWord += "".join(self.mainConf.fmtSingleQuotes) # Typography if self.mainConf.fmtPadThin: - self.typPadChar = nwUnicode.U_THNBSP + self._typPadChar = nwUnicode.U_THNBSP else: - self.typPadChar = nwUnicode.U_NBSP + self._typPadChar = nwUnicode.U_NBSP - self.typSQOpen = self.mainConf.fmtSingleQuotes[0] - self.typSQClose = self.mainConf.fmtSingleQuotes[1] - self.typDQOpen = self.mainConf.fmtDoubleQuotes[0] - self.typDQClose = self.mainConf.fmtDoubleQuotes[1] + self._typDQOpen = self.mainConf.fmtDoubleQuotes[0] + self._typDQClose = self.mainConf.fmtDoubleQuotes[1] + self._typSQOpen = self.mainConf.fmtSingleQuotes[0] + self._typSQClose = self.mainConf.fmtSingleQuotes[1] # Reload spell check and dictionaries self._setupSpellChecking() @@ -218,7 +218,7 @@ class GuiDocEditor(QTextEdit): theFont = QFont() if self.mainConf.textFont is None: # If none is defined, set the default back to config - self.mainConf.textFont = self.qDocument.defaultFont().family() + self.mainConf.textFont = self._qDocument.defaultFont().family() theFont.setFamily(self.mainConf.textFont) theFont.setPointSize(self.mainConf.textSize) @@ -241,7 +241,7 @@ class GuiDocEditor(QTextEdit): # Set default text margins cM = self.mainConf.getTextMargin() - self.qDocument.setDocumentMargin(0) + self._qDocument.setDocumentMargin(0) self.setViewportMargins(cM, cM, cM, cM) # Also set the document text options for the document text flow @@ -254,7 +254,7 @@ class GuiDocEditor(QTextEdit): if self.mainConf.showLineEndings: theOpt.setFlags(theOpt.flags() | QTextOption.ShowLineAndParagraphSeparators) - self.qDocument.setDefaultTextOption(theOpt) + self._qDocument.setDefaultTextOption(theOpt) # Scroll bars if self.mainConf.hideVScroll: @@ -283,7 +283,7 @@ class GuiDocEditor(QTextEdit): # If we have a document open, we should reload it in case the # font changed, otherwise we just clear the editor entirely, # which makes it read only. - if self.theHandle is None: + if self._docHandle is None: self.clearEditor() else: self.redrawText() @@ -299,10 +299,10 @@ class GuiDocEditor(QTextEdit): document is new (empty string), we set up the editor for editing the file. """ - self.nwDocument = NWDoc(self.theProject, tHandle) - self.nwItem = self.nwDocument.getCurrentItem() + self._nwDocument = NWDoc(self.theProject, tHandle) + self._nwItem = self._nwDocument.getCurrentItem() - theDoc = self.nwDocument.readDocument() + theDoc = self._nwDocument.readDocument() if theDoc is None: # There was an io error self.clearEditor() @@ -331,7 +331,7 @@ class GuiDocEditor(QTextEdit): # checking. If it is too big, we switch to only check as we type self._checkDocSize(docSize) spTemp = self.hLight.spellCheck - if self.bigDoc: + if self._bigDoc: self.hLight.spellCheck = False bfTime = time() @@ -343,48 +343,48 @@ class GuiDocEditor(QTextEdit): afTime = time() logger.debug("Document highlighted in %.3f ms" % (1000*(afTime-bfTime))) - self.lastEdit = time() - self.lastActive = time() + self._lastEdit = time() + self._lastActive = time() self._runCounter() self.wcTimer.start() - self.theHandle = tHandle + self._docHandle = tHandle self.setReadOnly(False) - self.docHeader.setTitleFromHandle(self.theHandle) - self.docFooter.setHandle(self.theHandle) + self.docHeader.setTitleFromHandle(self._docHandle) + self.docFooter.setHandle(self._docHandle) self.updateDocMargins() self.hLight.spellCheck = spTemp - if tLine is None and self.nwItem is not None: + if tLine is None and self._nwItem is not None: # For large documents we queue the repositioning until the # document layout has grown past the point we want to move # the cursor to. This makes the loading significantly # faster. if docSize > 50000: - self.queuePos = self.nwItem.cursorPos + self._queuePos = self._nwItem.cursorPos else: - self.setCursorPosition(self.nwItem.cursorPos) + self.setCursorPosition(self._nwItem.cursorPos) else: self.setCursorLine(tLine) self.docFooter.updateLineCount() - self.lengthLast = self.qDocument.characterCount() - self.theHeaders = self.theIndex.getHandleHeaders(self.theHandle) + self.lengthLast = self._qDocument.characterCount() + self._docHeaders = self.theIndex.getHandleHeaders(self._docHandle) qApp.processEvents() self.setDocumentChanged(False) qApp.restoreOverrideCursor() # This is a hack to fix invisble cursor on an empty document - if self.qDocument.characterCount() <= 1: + if self._qDocument.characterCount() <= 1: self.setPlainText("\n") self.setPlainText("") self.setCursorPosition(0) # Update the status bar - if self.nwItem is not None: + if self._nwItem is not None: self.theParent.setStatus( - self.tr("Opened Document: {0}").format(self.nwItem.itemName) + self.tr("Opened Document: {0}").format(self._nwItem.itemName) ) return True @@ -398,7 +398,7 @@ class GuiDocEditor(QTextEdit): def redrawText(self): """Redraw the text by marking the document content as "dirty". """ - self.qDocument.markContentsDirty(0, self.qDocument.characterCount()) + self._qDocument.markContentsDirty(0, self._qDocument.characterCount()) self.updateDocMargins() return @@ -433,14 +433,14 @@ class GuiDocEditor(QTextEdit): """Save the text currently in the editor to the NWDoc object, and update the NWItem meta data. """ - if self.nwItem is None or self.nwDocument is None: + if self._nwItem is None or self._nwDocument is None: logger.error("Cannot save text as no document is open") return False - tHandle = self.nwItem.itemHandle - if self.theHandle != tHandle: + tHandle = self._nwItem.itemHandle + if self._docHandle != tHandle: logger.error("Editor handle %s and item handle %s do not match" % ( - self.theHandle, tHandle + self._docHandle, tHandle )) return False @@ -449,14 +449,14 @@ class GuiDocEditor(QTextEdit): cC, wC, pC = countWords(docText) self._updateCounts(cC, wC, pC) - self.nwItem.setCharCount(self.charCount) - self.nwItem.setWordCount(self.wordCount) - self.nwItem.setParaCount(self.paraCount) + self._nwItem.setCharCount(self._charCount) + self._nwItem.setWordCount(self._wordCount) + self._nwItem.setParaCount(self._paraCount) self.saveCursorPosition() - if not self.nwDocument.writeDocument(docText): + if not self._nwDocument.writeDocument(docText): self.theParent.makeAlert([ - self.tr("Could not save document."), self.nwDocument.getError() + self.tr("Could not save document."), self._nwDocument.getError() ], nwAlert.ERROR) return False @@ -470,17 +470,17 @@ class GuiDocEditor(QTextEdit): self.theParent.novelView.updateWordCounts(tHandle) hLevel = "H0" - if self.theHeaders: - hLevel = self.theHeaders[0][1] + if self._docHeaders: + hLevel = self._docHeaders[0][1] if self.theProject.projTree.updateItemLayout(tHandle, hLevel): self.theParent.treeView.setTreeItemValues(tHandle) - self.nwDocument.writeDocument(docText) + self._nwDocument.writeDocument(docText) self.docFooter.updateInfo() # Update the status bar self.theParent.setStatus( - self.tr("Saved Document: {0}").format(self.nwItem.itemName) + self.tr("Saved Document: {0}").format(self._nwItem.itemName) ) return True @@ -531,16 +531,16 @@ class GuiDocEditor(QTextEdit): lM = max(cM, fH) self.setViewportMargins(tM, uM, tM, lM) - docChanged = self.docChanged + tmpDocChanged = self._docChanged if self.mainConf.scrollPastEnd: - docFrame = self.qDocument.rootFrame().frameFormat() + docFrame = self._qDocument.rootFrame().frameFormat() docFrame.setBottomMargin(max(0, 0.9*(wH - uM - lM - 4*tB))) - self.qDocument.rootFrame().setFrameFormat(docFrame) + self._qDocument.rootFrame().setFrameFormat(docFrame) # This is needed as the setFrameFormat function itself will - # trigger the contetsChanged signal which sets docChanged, so we + # trigger the contetsChanged signal which sets _docChanged, so we # set it back to whatever it was before. - self.setDocumentChanged(docChanged) + self.setDocumentChanged(tmpDocChanged) return @@ -548,14 +548,65 @@ class GuiDocEditor(QTextEdit): """Called when an item label is changed to check if the document title bar needs updating, """ - if tHandle == self.theHandle: - self.docHeader.setTitleFromHandle(self.theHandle) + if tHandle == self._docHandle: + self.docHeader.setTitleFromHandle(self._docHandle) self.docFooter.updateInfo() self.updateDocMargins() return ## - # Setters and Getters + # Properties + ## + + def docChanged(self): + """Return the changed status of the document in the editor. + """ + return self._docChanged + + def docHandle(self): + """Return the handle of the currently open document. Returns + None if no document is open. + """ + return self._docHandle + + def lastActive(self): + """Eeturn the last active timestamp for the user. + """ + return self._lastActive + + def isEmpty(self): + """Wrapper function to check if the current document is empty. + """ + return self._qDocument.isEmpty() + + ## + # Getters + ## + + def getText(self): + """Get the text content of the current document. This method + uses QTextEdit->toPlainText for Qt versions lower than 5.9, and + the QTextDocument->toRawText for higher version. The latter + preserves non-breaking spaces, which the former does not. + We still want to get rid of page and line separators though. + See: https://doc.qt.io/qt-5/qtextdocument.html#toPlainText + """ + if self.mainConf.verQtValue >= 50900: + theText = self._qDocument.toRawText() + theText = theText.replace(nwUnicode.U_LSEP, "\n") # Line separators + theText = theText.replace(nwUnicode.U_PSEP, "\n") # Paragraph separators + else: + theText = self.toPlainText() + return theText + + def getCursorPosition(self): + """Find the cursor position in the document. If the editor has a + selection, return the position of the end of the selection. + """ + return self.textCursor().selectionEnd() + + ## + # Setters ## def setDocumentChanged(self, bValue): @@ -563,25 +614,9 @@ class GuiDocEditor(QTextEdit): that the corresponding icon on the status bar shows the same status. """ - self.docChanged = bValue - self.theParent.statusBar.setDocumentStatus(self.docChanged) - return self.docChanged - - def getText(self): - """Get the text content of the current document. This method - uses QTextEdit->toPlainText for Qt versions lower than 5.9, and - the QDocument->toRawText for higher version. The latter - preserves non-breaking spaces, which the former does not. - We still want to get rid of page and line separators though. - See: https://doc.qt.io/qt-5/qtextdocument.html#toPlainText - """ - if self.mainConf.verQtValue >= 50900: - theText = self.qDocument.toRawText() - theText = theText.replace(nwUnicode.U_LSEP, "\n") # Line separators - theText = theText.replace(nwUnicode.U_PSEP, "\n") # Paragraph separators - else: - theText = self.toPlainText() - return theText + self._docChanged = bValue + self.theParent.statusBar.setDocumentStatus(self._docChanged) + return self._docChanged def setCursorPosition(self, thePosition): """Move the cursor to a given position in the document. @@ -589,7 +624,7 @@ class GuiDocEditor(QTextEdit): if not isinstance(thePosition, int): return False - nChars = self.qDocument.characterCount() + nChars = self._qDocument.characterCount() if nChars > 1: theCursor = self.textCursor() theCursor.setPosition(min(max(thePosition, 0), nChars-1)) @@ -598,18 +633,12 @@ class GuiDocEditor(QTextEdit): return True - def getCursorPosition(self): - """Find the cursor position in the document. If the editor has a - selection, return the position of the end of the selection. - """ - return self.textCursor().selectionEnd() - def saveCursorPosition(self): """Save the cursor position to the current project item object. """ - if self.nwItem is not None: + if self._nwItem is not None: cursPos = self.getCursorPosition() - self.nwItem.setCursorPos(cursPos) + self._nwItem.setCursorPos(cursPos) return def setCursorLine(self, theLine): @@ -619,7 +648,7 @@ class GuiDocEditor(QTextEdit): return False if theLine >= 0: - theBlock = self.qDocument.findBlockByLineNumber(theLine) + theBlock = self._qDocument.findBlockByLineNumber(theLine) if theBlock: self.setCursorPosition(theBlock.position()) self.docFooter.updateLineCount() @@ -646,7 +675,7 @@ class GuiDocEditor(QTextEdit): self.theParent.statusBar.setLanguage(theLang, theProvider) - if not self.bigDoc: + if not self._bigDoc: self.spellCheckDocument() return True @@ -658,16 +687,16 @@ class GuiDocEditor(QTextEdit): toggle the current status saved in this class. """ if theMode is None: - theMode = not self.spellCheck + theMode = not self._spellCheck if self.theDict.spellLanguage is None: theMode = False - self.spellCheck = theMode + self._spellCheck = theMode self.theParent.mainMenu.setSpellCheck(theMode) self.theProject.setSpellCheck(theMode) self.hLight.setSpellCheck(theMode) - if not self.bigDoc: + if not self._bigDoc: self.spellCheckDocument() logger.verbose("Spell check is set to %s" % str(theMode)) @@ -680,10 +709,10 @@ class GuiDocEditor(QTextEdit): of Qt 5.13, is to clear the text and put it back. """ logger.verbose("Running spell checker") - if self.spellCheck: + if self._spellCheck: bfTime = time() qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) - if self.bigDoc: + if self._bigDoc: theText = self.getText() self.setPlainText(theText) else: @@ -707,7 +736,7 @@ class GuiDocEditor(QTextEdit): this class when calling these actions from other classes. """ logger.verbose("Requesting action: %s" % theAction.name) - if self.theHandle is None: + if self._docHandle is None: logger.error("No document open") return False @@ -729,9 +758,9 @@ class GuiDocEditor(QTextEdit): elif theAction == nwDocAction.STRIKE: self._toggleFormat(2, "~") elif theAction == nwDocAction.S_QUOTE: - self._wrapSelection(self.typSQOpen, self.typSQClose) + self._wrapSelection(self._typSQOpen, self._typSQClose) elif theAction == nwDocAction.D_QUOTE: - self._wrapSelection(self.typDQOpen, self.typDQClose) + self._wrapSelection(self._typDQOpen, self._typDQClose) elif theAction == nwDocAction.SEL_ALL: self._makeSelection(QTextCursor.Document) elif theAction == nwDocAction.SEL_PARA: @@ -749,24 +778,19 @@ class GuiDocEditor(QTextEdit): elif theAction == nwDocAction.BLOCK_TXT: self._formatBlock(nwDocAction.BLOCK_TXT) elif theAction == nwDocAction.REPL_SNG: - self._replaceQuotes("'", self.typSQOpen, self.typSQClose) + self._replaceQuotes("'", self._typSQOpen, self._typSQClose) elif theAction == nwDocAction.REPL_DBL: - self._replaceQuotes("\"", self.typDQOpen, self.typDQClose) + self._replaceQuotes("\"", self._typDQOpen, self._typDQClose) else: logger.debug("Unknown or unsupported document action %s" % str(theAction)) self._allowAutoReplace(True) return False self._allowAutoReplace(True) - self.lastActive = time() + self._lastActive = time() return True - def isEmpty(self): - """Wrapper function to check if the current document is empty. - """ - return self.qDocument.isEmpty() - def anyFocus(self): """Check if any widget or child widget has focus. """ @@ -780,7 +804,7 @@ class GuiDocEditor(QTextEdit): """Tell the user where on the file system the file in the editor is saved. """ - if self.nwDocument is None: + if self._nwDocument is None: logger.error("No document open") return False @@ -790,7 +814,7 @@ class GuiDocEditor(QTextEdit): self.tr("File Location"), "%s
%s" % ( self.tr("The currently open file is saved in:"), - self.nwDocument.getFileLocation() + self._nwDocument.getFileLocation() ), ) @@ -799,7 +823,7 @@ class GuiDocEditor(QTextEdit): def insertText(self, theInsert): """Insert a specific type of text at the cursor position. """ - if self.theHandle is None: + if self._docHandle is None: logger.error("No document open") return False @@ -809,13 +833,13 @@ class GuiDocEditor(QTextEdit): if theInsert == nwDocInsert.HARD_BREAK: theText = " \n" elif theInsert == nwDocInsert.QUOTE_LS: - theText = self.typSQOpen + theText = self._typSQOpen elif theInsert == nwDocInsert.QUOTE_RS: - theText = self.typSQClose + theText = self._typSQClose elif theInsert == nwDocInsert.QUOTE_LD: - theText = self.typDQOpen + theText = self._typDQOpen elif theInsert == nwDocInsert.QUOTE_RD: - theText = self.typDQClose + theText = self._typDQClose else: return False else: @@ -885,7 +909,7 @@ class GuiDocEditor(QTextEdit): * The undo/redo/select all sequences bypasses the docAction pathway from the menu, so we redirect them back from here. """ - self.lastActive = time() + self._lastActive = time() isReturn = keyEvent.key() == Qt.Key_Return isReturn |= keyEvent.key() == Qt.Key_Enter if isReturn and self.docSearch.anyFocus(): @@ -971,10 +995,10 @@ class GuiDocEditor(QTextEdit): """Triggered by QTextDocument->contentsChanged. This also triggers the syntax highlighter. """ - self.lastEdit = time() - self.lastFind = None + self._lastEdit = time() + self._lastFind = None - if self.qDocument.characterCount() > nwConst.MAX_DOCSIZE: + if self._qDocument.characterCount() > nwConst.MAX_DOCSIZE: self.theParent.makeAlert( self.tr( "The document has grown too big and you cannot add more text to it. " @@ -987,14 +1011,14 @@ class GuiDocEditor(QTextEdit): self.undo() return - if not self.docChanged: + if not self._docChanged: self.setDocumentChanged(chrRem != 0 or chrAdd != 0) if not self.wcTimer.isActive(): self.wcTimer.start() - if self.doReplace and chrAdd == 1: - self._docAutoReplace(self.qDocument.findBlock(thePos)) + if self._doReplace and chrAdd == 1: + self._docAutoReplace(self._qDocument.findBlock(thePos)) return @@ -1056,14 +1080,14 @@ class GuiDocEditor(QTextEdit): # ============== posCursor = self.cursorForPosition(thePos) - spellCheck = self.spellCheck + spellCheck = self._spellCheck if posCursor.block().text().startswith("@"): spellCheck = False if spellCheck: posCursor.select(QTextCursor.WordUnderCursor) - theWord = posCursor.selectedText().strip().strip(self.nonWord) + theWord = posCursor.selectedText().strip().strip(self._nonWord) spellCheck &= theWord != "" if spellCheck: @@ -1118,7 +1142,7 @@ class GuiDocEditor(QTextEdit): """Slot for the spell check context menu triggered when the user wants to add a word to the project dictionary. """ - theWord = theCursor.selectedText().strip().strip(self.nonWord) + theWord = theCursor.selectedText().strip().strip(self._nonWord) logger.debug("Added '%s' to project dictionary" % theWord) self.theDict.addWord(theWord) self.hLight.setDict(self.theDict) @@ -1130,14 +1154,14 @@ class GuiDocEditor(QTextEdit): """Decide whether to run the word counter, or not due to inactivity. """ - if self.theHandle is None: + if self._docHandle is None: return if self.wCounter.isRunning(): logger.verbose("Word counter is busy") return - if time() - self.lastEdit < 5 * self.wcInterval: + if time() - self._lastEdit < 5 * self.wcInterval: logger.verbose("Running word counter") self.theParent.threadPool.start(self.wCounter) @@ -1147,23 +1171,23 @@ class GuiDocEditor(QTextEdit): def _updateCounts(self, cCount, wCount, pCount): """Slot for the word counter's finished signal """ - if self.theHandle is None or self.nwItem is None: + if self._docHandle is None or self._nwItem is None: return logger.verbose("Updating word count") - self.charCount = cCount - self.wordCount = wCount - self.paraCount = pCount + self._charCount = cCount + self._wordCount = wCount + self._paraCount = pCount - self.nwItem.setCharCount(cCount) - self.nwItem.setWordCount(wCount) - self.nwItem.setParaCount(pCount) + self._nwItem.setCharCount(cCount) + self._nwItem.setWordCount(wCount) + self._nwItem.setParaCount(pCount) - self.theParent.treeView.propagateCount(self.theHandle, wCount) + self.theParent.treeView.propagateCount(self._docHandle, wCount) self.theParent.treeView.projectWordCount() - self.theParent.treeMeta.updateCounts(self.theHandle, cCount, wCount, pCount) - self._checkDocSize(self.qDocument.characterCount()) + self.theParent.treeMeta.updateCounts(self._docHandle, cCount, wCount, pCount) + self._checkDocSize(self._qDocument.characterCount()) self.docFooter.updateCounts() return @@ -1175,16 +1199,16 @@ class GuiDocEditor(QTextEdit): large documents to ensure the region where the cursor is being moved to has been drawn before the move is made. """ - if self.queuePos is not None: - thePos = self.qDocument.documentLayout().hitTest( + if self._queuePos is not None: + thePos = self._qDocument.documentLayout().hitTest( QPointF(theSize.width(), theSize.height()), Qt.FuzzyHit ) - if self.queuePos <= thePos: - logger.verbose("Allowed cursor move to %d <= %d" % (self.queuePos, thePos)) - self.setCursorPosition(self.queuePos) - self.queuePos = None + if self._queuePos <= thePos: + logger.verbose("Allowed cursor move to %d <= %d" % (self._queuePos, thePos)) + self.setCursorPosition(self._queuePos) + self._queuePos = None else: - logger.verbose("Denied cursor move to %d > %d" % (self.queuePos, thePos)) + logger.verbose("Denied cursor move to %d > %d" % (self._queuePos, thePos)) return ## @@ -1241,7 +1265,7 @@ class GuiDocEditor(QTextEdit): if not wasFound: if self.docSearch.doNextFile and not goBack: self.theParent.openNextDocument( - self.theHandle, wrapAround=self.docSearch.doLoop + self._docHandle, wrapAround=self.docSearch.doLoop ) elif self.docSearch.doLoop: theCursor = self.textCursor() @@ -1253,7 +1277,7 @@ class GuiDocEditor(QTextEdit): if wasFound: theCursor = self.textCursor() - self.lastFind = (theCursor.selectionStart(), theCursor.selectionEnd()) + self._lastFind = (theCursor.selectionStart(), theCursor.selectionEnd()) return @@ -1278,7 +1302,7 @@ class GuiDocEditor(QTextEdit): self.findNext() return - if self.lastFind is None and theCursor.hasSelection(): + if self._lastFind is None and theCursor.hasSelection(): # If we have a selection but no search, it may have been the # text we triggered the search with, in which case we search # again from the beginning of that selection to make sure we @@ -1290,7 +1314,7 @@ class GuiDocEditor(QTextEdit): self.findNext() theCursor = self.textCursor() - if self.lastFind is None: + if self._lastFind is None: # In case the above didn't find a result, we give up here. return @@ -1303,8 +1327,8 @@ class GuiDocEditor(QTextEdit): # Make sure the selected text was selected by an actual find # call, and not the user. try: - isFind = self.lastFind[0] == theCursor.selectionStart() - isFind &= self.lastFind[1] == theCursor.selectionEnd() + isFind = self._lastFind[0] == theCursor.selectionStart() + isFind &= self._lastFind[1] == theCursor.selectionEnd() except Exception: isFind = False @@ -1397,25 +1421,25 @@ class GuiDocEditor(QTextEdit): if self.mainConf.doReplaceDQuote and theTwo == ' "': nDelete = 1 - tInsert = self.typDQOpen + tInsert = self._typDQOpen elif self.mainConf.doReplaceDQuote and theOne == '"': nDelete = 1 if thePos == 1: - tInsert = self.typDQOpen + tInsert = self._typDQOpen else: - tInsert = self.typDQClose + tInsert = self._typDQClose elif self.mainConf.doReplaceSQuote and theTwo == " '": nDelete = 1 - tInsert = self.typSQOpen + tInsert = self._typSQOpen elif self.mainConf.doReplaceSQuote and theOne == "'": nDelete = 1 if thePos == 1: - tInsert = self.typSQOpen + tInsert = self._typSQOpen else: - tInsert = self.typSQClose + tInsert = self._typSQClose elif self.mainConf.doReplaceDash and theThree == "---": nDelete = 3 @@ -1436,11 +1460,11 @@ class GuiDocEditor(QTextEdit): tCheck = tInsert if tCheck in self.mainConf.fmtPadBefore: nDelete = max(nDelete, 1) - tInsert = self.typPadChar + tInsert + tInsert = self._typPadChar + tInsert if tCheck in self.mainConf.fmtPadAfter: nDelete = max(nDelete, 1) - tInsert = tInsert + self.typPadChar + tInsert = tInsert + self._typPadChar if nDelete > 0: theCursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, nDelete) @@ -1452,18 +1476,18 @@ class GuiDocEditor(QTextEdit): """Update the headers record and return True if anything changed, if a check flag was provided. """ - if self.theHandle is None: + if self._docHandle is None: return False - newHeaders = self.theIndex.getHandleHeaders(self.theHandle) + newHeaders = self.theIndex.getHandleHeaders(self._docHandle) if checkPos: newPos = [x[0] for x in newHeaders] - oldPos = [x[0] for x in self.theHeaders] + oldPos = [x[0] for x in self._docHeaders] if checkLevel: newLev = [x[1] for x in newHeaders] - oldLev = [x[1] for x in self.theHeaders] + oldLev = [x[1] for x in self._docHeaders] - self.theHeaders = newHeaders + self._docHeaders = newHeaders if checkPos: return newPos != oldPos @@ -1532,7 +1556,7 @@ class GuiDocEditor(QTextEdit): bigLim = self.mainConf.bigDocLimit*1000 newState = theSize > bigLim - if newState != self.bigDoc: + if newState != self._bigDoc: if newState: logger.info( f"The document size is {theSize:n} > {bigLim:n}, " @@ -1544,7 +1568,7 @@ class GuiDocEditor(QTextEdit): f"big doc mode has been disabled" ) - self.bigDoc = newState + self._bigDoc = newState return @@ -1562,8 +1586,8 @@ class GuiDocEditor(QTextEdit): posS = theCursor.selectionStart() posE = theCursor.selectionEnd() - blockS = self.qDocument.findBlock(posS) - blockE = self.qDocument.findBlock(posE) + blockS = self._qDocument.findBlock(posS) + blockE = self._qDocument.findBlock(posE) if blockS != blockE: posE = blockS.position() + blockS.length() - 1 @@ -1616,10 +1640,10 @@ class GuiDocEditor(QTextEdit): # Underscore counts as a part of the word, so check that the # selection isn't wrapped in italics markers. reSelect = False - if self.qDocument.characterAt(posS) == "_": + if self._qDocument.characterAt(posS) == "_": posS += 1 reSelect = True - if self.qDocument.characterAt(posE) == "_": + if self._qDocument.characterAt(posE) == "_": posE -= 1 reSelect = True if reSelect: @@ -1641,8 +1665,8 @@ class GuiDocEditor(QTextEdit): posS = theCursor.selectionStart() posE = theCursor.selectionEnd() - blockS = self.qDocument.findBlock(posS) - blockE = self.qDocument.findBlock(posE) + blockS = self._qDocument.findBlock(posS) + blockE = self._qDocument.findBlock(posE) if blockS != blockE: posE = blockS.position() + blockS.length() - 1 @@ -1653,14 +1677,14 @@ class GuiDocEditor(QTextEdit): numB = 0 for n in range(fLen): - if self.qDocument.characterAt(posS-n-1) == fChar: + if self._qDocument.characterAt(posS-n-1) == fChar: numB += 1 else: break numA = 0 for n in range(fLen): - if self.qDocument.characterAt(posE+n) == fChar: + if self._qDocument.characterAt(posE+n) == fChar: numA += 1 else: break @@ -1804,9 +1828,9 @@ class GuiDocEditor(QTextEdit): """used to enable/disable the auto-replace feature temporarily. """ if theState: - self.doReplace = self.mainConf.doReplace + self._doReplace = self.mainConf.doReplace else: - self.doReplace = False + self._doReplace = False return # END Class GuiDocEditor @@ -2242,7 +2266,7 @@ class GuiDocEditHeader(QWidget): self.theParent = docEditor.theParent self.theProject = docEditor.theProject self.theTheme = docEditor.theTheme - self.theHandle = None + self._docHandle = None fPx = int(0.9*self.theTheme.fontPixelSize) hSp = self.mainConf.pxInt(6) @@ -2360,7 +2384,7 @@ class GuiDocEditHeader(QWidget): """Sets the document title from the handle, or alternatively, set the whole document path. """ - self.theHandle = tHandle + self._docHandle = tHandle if tHandle is None: self.theTitle.setText("") self.editButton.setVisible(False) @@ -2409,7 +2433,7 @@ class GuiDocEditHeader(QWidget): def _editDocument(self): """Open the edit item dialog from the main GUI. """ - self.theParent.editItem(self.theHandle) + self.theParent.editItem(self._docHandle) return def _searchDocument(self): @@ -2442,7 +2466,7 @@ class GuiDocEditHeader(QWidget): """Capture a click on the title and ensure that the item is selected in the project tree. """ - self.theParent.treeView.setSelectedHandle(self.theHandle, doScroll=True) + self.theParent.treeView.setSelectedHandle(self._docHandle, doScroll=True) return # END Class GuiDocEditHeader @@ -2465,7 +2489,7 @@ class GuiDocEditFooter(QWidget): self.theProject = docEditor.theProject self.theTheme = docEditor.theTheme self.optState = docEditor.theProject.optState - self.theHandle = None + self._docHandle = None self.theItem = None self.sPx = int(round(0.9*self.theTheme.baseIconSize)) @@ -2579,12 +2603,12 @@ class GuiDocEditFooter(QWidget): def setHandle(self, tHandle): """Set the handle that will populate the footer's data. """ - self.theHandle = tHandle - if self.theHandle is None: + self._docHandle = tHandle + if self._docHandle is None: logger.verbose("No handle set, so clearing the editor footer") self.theItem = None else: - self.theItem = self.theProject.projTree[self.theHandle] + self.theItem = self.theProject.projTree[self._docHandle] self.updateInfo() self.updateCounts() @@ -2625,7 +2649,7 @@ class GuiDocEditFooter(QWidget): else: theCursor = self.docEditor.textCursor() iLine = theCursor.blockNumber() + 1 - iDist = 100*iLine/self.docEditor.qDocument.blockCount() + iDist = 100*iLine/self.docEditor._qDocument.blockCount() self.linesText.setText( self.tr("Line: {0} ({1})").format(f"{iLine:n}", f"{iDist:.0f} %") @@ -2647,7 +2671,7 @@ class GuiDocEditFooter(QWidget): self.tr("Words: {0} ({1})").format(f"{wCount:n}", f"{wDiff:+n}") ) - byteSize = self.docEditor.qDocument.characterCount() + byteSize = self.docEditor._qDocument.characterCount() self.wordsText.setToolTip( self.tr("Document size is {0} bytes").format(f"{byteSize:n}") ) diff --git a/nw/gui/docviewer.py b/nw/gui/docviewer.py index 22c0439a..3eb4cdb4 100644 --- a/nw/gui/docviewer.py +++ b/nw/gui/docviewer.py @@ -876,7 +876,7 @@ class GuiDocViewHeader(QWidget): def _refreshDocument(self): """Reload the content of the document. """ - if self.docViewer.theHandle == self.theParent.docEditor.theHandle: + if self.docViewer.theHandle == self.theParent.docEditor.docHandle(): self.theParent.saveDocument() self.docViewer.reloadText() return diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index 03f5c0c5..f4f3c7be 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -524,7 +524,7 @@ class GuiProjectTree(QTreeWidget): tIndex = trItemP.indexOfChild(trItemS) trItemC = trItemP.takeChild(tIndex) - if self.theParent.docEditor.theHandle == tHandle: + if self.theParent.docEditor.docHandle() == tHandle: self.theParent.closeDocument() delDoc = NWDoc(self.theProject, tHandle) diff --git a/nw/guimain.py b/nw/guimain.py index d9c1ce27..863553d9 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -407,7 +407,7 @@ class GuiMain(QMainWindow): if not msgYes: return False - if self.docEditor.docChanged: + if self.docEditor.docChanged(): self.saveDocument() if self.theProject.projAltered: @@ -576,7 +576,7 @@ class GuiMain(QMainWindow): self.toggleFocusMode() self.docEditor.saveCursorPosition() - if self.docEditor.docChanged: + if self.docEditor.docChanged(): self.saveDocument() self.docEditor.clearEditor() @@ -658,7 +658,7 @@ class GuiMain(QMainWindow): if self.docEditor.hasFocus(): logger.verbose("Trying editor document") - tHandle = self.docEditor.theHandle + tHandle = self.docEditor.docHandle() if tHandle is not None: self.saveDocument() @@ -727,7 +727,7 @@ class GuiMain(QMainWindow): ], nwAlert.ERROR) return False - if self.docEditor.theHandle is None: + if self.docEditor.docHandle() is None: self.makeAlert( self.tr("Please open a document to import the text file into."), nwAlert.ERROR @@ -822,7 +822,7 @@ class GuiMain(QMainWindow): if tHandle is None: if self.docEditor.anyFocus() or self.isFocusMode: - tHandle = self.docEditor.theHandle + tHandle = self.docEditor.docHandle() else: tHandle = self.treeView.getSelectedHandle() @@ -1218,7 +1218,7 @@ class GuiMain(QMainWindow): """Main GUI Focus Mode hides tree, view pane and optionally also statusbar and menu. """ - if self.docEditor.theHandle is None: + if self.docEditor.docHandle() is None: logger.error("No document open, so not activating Focus Mode") self.mainMenu.setFocusMode(self.isFocusMode) return False @@ -1385,7 +1385,7 @@ class GuiMain(QMainWindow): """Triggered by the auto-save document timer to save the document. """ - if self.hasProject and self.docEditor.docChanged: + if self.hasProject and self.docEditor.docChanged(): logger.debug("Autosaving document") self.saveDocument() return @@ -1477,7 +1477,7 @@ class GuiMain(QMainWindow): return currTime = time() - editIdle = currTime - self.docEditor.lastActive > self.mainConf.userIdleTime + editIdle = currTime - self.docEditor.lastActive() > self.mainConf.userIdleTime userIdle = qApp.applicationState() != Qt.ApplicationActive if editIdle or userIdle: diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py index 451f1f47..2afa6043 100644 --- a/tests/test_gui/test_gui_doceditor.py +++ b/tests/test_gui/test_gui_doceditor.py @@ -292,9 +292,9 @@ def testGuiEditor_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj, refDir, outDi qtbot.wait(stepDelay) # Save the document - assert nwGUI.docEditor.docChanged + assert nwGUI.docEditor.docChanged() assert nwGUI.saveDocument() - assert not nwGUI.docEditor.docChanged + assert not nwGUI.docEditor.docChanged() qtbot.wait(stepDelay) nwGUI.rebuildIndex() qtbot.wait(stepDelay) @@ -503,7 +503,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum): # Next Match nwGUI.mainMenu.aFindNext.activate(QAction.Trigger) - assert nwGUI.docEditor.theHandle == "2426c6f0ca922" # Next document + assert nwGUI.docEditor.docHandle() == "2426c6f0ca922" # Next document nwGUI.mainMenu.aFindNext.activate(QAction.Trigger) assert abs(nwGUI.docEditor.getCursorPosition() - 620) < 3 nwGUI.mainMenu.aFindNext.activate(QAction.Trigger) diff --git a/tests/test_gui/test_gui_noveltree.py b/tests/test_gui/test_gui_noveltree.py index 9bf3a7d8..b6618569 100644 --- a/tests/test_gui/test_gui_noveltree.py +++ b/tests/test_gui/test_gui_noveltree.py @@ -97,9 +97,9 @@ def testGuiNovelTree_TreeItems(qtbot, caplog, monkeypatch, nwGUI, nwMinimal): # Double-click item scItem.setSelected(True) assert scItem.isSelected() - assert nwGUI.docEditor.theHandle is None + assert nwGUI.docEditor.docHandle() is None nwTree._treeDoubleClick(scItem, 0) - assert nwGUI.docEditor.theHandle == "8c659a11cd429" + assert nwGUI.docEditor.docHandle() == "8c659a11cd429" # Open item with middle mouse button scItem.setSelected(True) From 24ab6f2d3beaad64aed46105e57556b8a4974aec Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 May 2021 00:19:40 +0200 Subject: [PATCH 2/8] Make the editor dictionary internal --- nw/core/spellcheck.py | 6 +++--- nw/dialogs/projsettings.py | 2 +- nw/gui/doceditor.py | 34 +++++++++++++++++++++------------- nw/gui/statusbar.py | 7 ++++--- nw/guimain.py | 3 +++ 5 files changed, 32 insertions(+), 20 deletions(-) diff --git a/nw/core/spellcheck.py b/nw/core/spellcheck.py index 6ea8bb92..8b148426 100644 --- a/nw/core/spellcheck.py +++ b/nw/core/spellcheck.py @@ -152,7 +152,7 @@ class NWSpellEnchant(NWSpellCheck): except Exception: logger.error("Failed to load enchant spell checking for language %s" % theLang) - self.theDict = NWSpellEnchantDummy() + self.theDict = FakeEnchant() self.spellLanguage = None self._readProjectDictionary(projectDict) @@ -208,7 +208,7 @@ class NWSpellEnchant(NWSpellCheck): # END Class NWSpellEnchant -class NWSpellEnchantDummy: +class FakeEnchant: """Fallback for when Enchant is selected, but not installed. """ def __init__(self): @@ -223,7 +223,7 @@ class NWSpellEnchantDummy: def add_to_session(self, theWord): return -# END Class NWSpellEnchantDummy +# END Class FakeEnchant # =============================================================================================== # # Fallback SpellChecking Using difflib diff --git a/nw/dialogs/projsettings.py b/nw/dialogs/projsettings.py index 38952eed..014fd32b 100644 --- a/nw/dialogs/projsettings.py +++ b/nw/dialogs/projsettings.py @@ -207,7 +207,7 @@ class GuiProjectEditMain(QWidget): self.spellLang = QComboBox(self) self.spellLang.setMaximumWidth(xW) - theDict = self.theParent.docEditor.theDict + theDict = self.theParent.docEditor.currentDictionary() self.spellLang.addItem(self.tr("Default"), "None") if theDict is not None: for spTag, spProv in theDict.listDictionaries(): diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index 6736accb..ef0e685f 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -64,6 +64,9 @@ class GuiDocEditor(QTextEdit): Qt.Key_PageUp, Qt.Key_PageDown ) + # Custom Signals + spellDictionaryChanged = pyqtSignal(str, str) + def __init__(self, theParent): QTextEdit.__init__(self, theParent) @@ -84,7 +87,7 @@ class GuiDocEditor(QTextEdit): self._docHeaders = [] # Record of headers in the file self._spellCheck = False # Flag for spell checking enabled - self.theDict = None # The current spell check dictionary + self._theDict = None # The current spell check dictionary self._nonWord = "\"'" # Characters to not include in spell checking # Document Variables @@ -579,6 +582,11 @@ class GuiDocEditor(QTextEdit): """ return self._qDocument.isEmpty() + def currentDictionary(self): + """Return the current dictionary object. + """ + return self._theDict + ## # Getters ## @@ -670,10 +678,10 @@ class GuiDocEditor(QTextEdit): else: theLang = self.theProject.projSpell - self.theDict.setLanguage(theLang, self.theProject.projDict) - theTag, theProvider = self.theDict.describeDict() + self._theDict.setLanguage(theLang, self.theProject.projDict) + _, theProvider = self._theDict.describeDict() - self.theParent.statusBar.setLanguage(theLang, theProvider) + self.spellDictionaryChanged.emit(theLang, theProvider) if not self._bigDoc: self.spellCheckDocument() @@ -689,7 +697,7 @@ class GuiDocEditor(QTextEdit): if theMode is None: theMode = not self._spellCheck - if self.theDict.spellLanguage is None: + if self._theDict.spellLanguage is None: theMode = False self._spellCheck = theMode @@ -987,7 +995,7 @@ class GuiDocEditor(QTextEdit): return ## - # Signals and Slots + # Slots ## @pyqtSlot(int, int, int) @@ -1092,14 +1100,14 @@ class GuiDocEditor(QTextEdit): if spellCheck: logger.verbose("Looking up '%s' in the dictionary" % theWord) - spellCheck &= not self.theDict.checkWord(theWord) + spellCheck &= not self._theDict.checkWord(theWord) if spellCheck: mnuContext.addSeparator() mnuHead = QAction(self.tr("Spelling Suggestion(s)"), mnuContext) mnuContext.addAction(mnuHead) - theSuggest = self.theDict.suggestWords(theWord)[:15] + theSuggest = self._theDict.suggestWords(theWord)[:15] if len(theSuggest) > 0: for aWord in theSuggest: mnuWord = QAction("%s %s" % (nwUnicode.U_ENDASH, aWord), mnuContext) @@ -1144,8 +1152,8 @@ class GuiDocEditor(QTextEdit): """ theWord = theCursor.selectedText().strip().strip(self._nonWord) logger.debug("Added '%s' to project dictionary" % theWord) - self.theDict.addWord(theWord) - self.hLight.setDict(self.theDict) + self._theDict.addWord(theWord) + self.hLight.setDict(self._theDict) self.hLight.rehighlightBlock(theCursor.block()) return @@ -1816,11 +1824,11 @@ class GuiDocEditor(QTextEdit): """ if self.mainConf.spellTool == nwConst.SP_ENCHANT: from nw.core.spellcheck import NWSpellEnchant - self.theDict = NWSpellEnchant() + self._theDict = NWSpellEnchant() else: - self.theDict = NWSpellSimple() + self._theDict = NWSpellSimple() - self.hLight.setDict(self.theDict) + self.hLight.setDict(self._theDict) return diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py index 4691202c..d3490bf4 100644 --- a/nw/gui/statusbar.py +++ b/nw/gui/statusbar.py @@ -29,7 +29,7 @@ import logging from time import time -from PyQt5.QtCore import QLocale +from PyQt5.QtCore import QLocale, pyqtSlot from PyQt5.QtGui import QColor, QPainter from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton @@ -123,7 +123,7 @@ class GuiMainStatus(QStatusBar): """Reset all widgets on the status bar to default values. """ self.setRefTime(None) - self.setLanguage(None) + self.setLanguage(None, "") self.setStats(0, 0) self.setProjectStatus(None) self.setDocumentStatus(None) @@ -147,7 +147,8 @@ class GuiMainStatus(QStatusBar): qApp.processEvents() return - def setLanguage(self, theLanguage, theProvider=""): + @pyqtSlot(str, str) + def setLanguage(self, theLanguage, theProvider): """Set the language code for the spell checker. """ if theLanguage is None: diff --git a/nw/guimain.py b/nw/guimain.py index 863553d9..491671bb 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -119,6 +119,9 @@ class GuiMain(QMainWindow): self.projMeta = GuiOutlineDetails(self) self.mainMenu = GuiMainMenu(self) + # Signals Between Main Elements + self.docEditor.spellDictionaryChanged.connect(self.statusBar.setLanguage) + # Minor GUI Elements self.statusIcons = [] self.importIcons = [] From 4ce8b38acd86adc75daa783febca7206a2427eda Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 May 2021 00:41:44 +0200 Subject: [PATCH 3/8] Add editorDocumentChanged signal in GuiDocEditor --- nw/gui/doceditor.py | 5 ++-- nw/gui/statusbar.py | 68 ++++++++++++++++++++++++--------------------- nw/guimain.py | 3 +- 3 files changed, 42 insertions(+), 34 deletions(-) diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index ef0e685f..9cf64a1d 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -66,6 +66,7 @@ class GuiDocEditor(QTextEdit): # Custom Signals spellDictionaryChanged = pyqtSignal(str, str) + editorDocumentChanged = pyqtSignal(bool) def __init__(self, theParent): QTextEdit.__init__(self, theParent) @@ -623,7 +624,7 @@ class GuiDocEditor(QTextEdit): status. """ self._docChanged = bValue - self.theParent.statusBar.setDocumentStatus(self._docChanged) + self.editorDocumentChanged.emit(self._docChanged) return self._docChanged def setCursorPosition(self, thePosition): @@ -728,7 +729,7 @@ class GuiDocEditor(QTextEdit): qApp.restoreOverrideCursor() afTime = time() logger.debug("Document highlighted in %.3f ms" % (1000*(afTime-bfTime))) - self.theParent.statusBar.showMessage(self.tr("Spell check complete")) + self.theParent.statusBar.setStatus(self.tr("Spell check complete")) return True diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py index d3490bf4..c7fc5aeb 100644 --- a/nw/gui/statusbar.py +++ b/nw/gui/statusbar.py @@ -126,7 +126,7 @@ class GuiMainStatus(QStatusBar): self.setLanguage(None, "") self.setStats(0, 0) self.setProjectStatus(None) - self.setDocumentStatus(None) + self.updateDocumentStatus(None) self.updateTime() return True @@ -147,36 +147,6 @@ class GuiMainStatus(QStatusBar): qApp.processEvents() return - @pyqtSlot(str, str) - def setLanguage(self, theLanguage, theProvider): - """Set the language code for the spell checker. - """ - if theLanguage is None: - self.langText.setText(self.tr("None")) - self.langText.setToolTip("") - else: - qLocal = QLocale(theLanguage) - spLang = qLocal.nativeLanguageName().title() - self.langText.setText(spLang) - if theProvider: - self.langText.setToolTip("%s (%s)" % (theLanguage, theProvider)) - else: - self.langText.setToolTip(theLanguage) - - return - - def setProjectStatus(self, isChanged): - """Set the project status colour icon. - """ - self.projIcon.setState(isChanged) - return - - def setDocumentStatus(self, isChanged): - """Set the document status colour icon. - """ - self.docIcon.setState(isChanged) - return - def setStats(self, pWC, sWC): """Set the current project statistics. """ @@ -213,6 +183,42 @@ class GuiMainStatus(QStatusBar): self.timeText.setText(formatTime(sessTime)) return + ## + # Slots + ## + + @pyqtSlot(str, str) + def setLanguage(self, theLanguage, theProvider): + """Set the language code for the spell checker. + """ + if theLanguage is None: + self.langText.setText(self.tr("None")) + self.langText.setToolTip("") + else: + qLocal = QLocale(theLanguage) + spLang = qLocal.nativeLanguageName().title() + self.langText.setText(spLang) + if theProvider: + self.langText.setToolTip("%s (%s)" % (theLanguage, theProvider)) + else: + self.langText.setToolTip(theLanguage) + + return + + @pyqtSlot(bool) + def setProjectStatus(self, isChanged): + """Set the project status colour icon. + """ + self.projIcon.setState(isChanged) + return + + @pyqtSlot(bool) + def updateDocumentStatus(self, isChanged): + """Set the document status colour icon. + """ + self.docIcon.setState(isChanged) + return + # END Class GuiMainStatus class StatusLED(QAbstractButton): diff --git a/nw/guimain.py b/nw/guimain.py index 491671bb..9d077b06 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -121,6 +121,7 @@ class GuiMain(QMainWindow): # Signals Between Main Elements self.docEditor.spellDictionaryChanged.connect(self.statusBar.setLanguage) + self.docEditor.editorDocumentChanged.connect(self.statusBar.updateDocumentStatus) # Minor GUI Elements self.statusIcons = [] @@ -381,7 +382,7 @@ class GuiMain(QMainWindow): self.rebuildIndex(beQuiet=True) self.statusBar.setRefTime(self.theProject.projOpened) self.statusBar.setProjectStatus(True) - self.statusBar.setDocumentStatus(None) + self.statusBar.updateDocumentStatus(None) self.statusBar.setStatus(self.tr("New project created ...")) self._updateWindowTitle(self.theProject.projName) else: From e9ef4fd091952c85218745d76cecce07e9947c58 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 May 2021 16:26:03 +0200 Subject: [PATCH 4/8] Make sure slots and signals are correct type --- nw/gui/doceditor.py | 6 +++--- nw/gui/statusbar.py | 28 ++++++++++++++++++++-------- nw/guimain.py | 4 ++-- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index 9cf64a1d..ecf8ce33 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -66,7 +66,7 @@ class GuiDocEditor(QTextEdit): # Custom Signals spellDictionaryChanged = pyqtSignal(str, str) - editorDocumentChanged = pyqtSignal(bool) + docEditedStatusChanged = pyqtSignal(bool) def __init__(self, theParent): QTextEdit.__init__(self, theParent) @@ -624,7 +624,7 @@ class GuiDocEditor(QTextEdit): status. """ self._docChanged = bValue - self.editorDocumentChanged.emit(self._docChanged) + self.docEditedStatusChanged.emit(self._docChanged) return self._docChanged def setCursorPosition(self, thePosition): @@ -682,7 +682,7 @@ class GuiDocEditor(QTextEdit): self._theDict.setLanguage(theLang, self.theProject.projDict) _, theProvider = self._theDict.describeDict() - self.spellDictionaryChanged.emit(theLang, theProvider) + self.spellDictionaryChanged.emit(str(theLang), str(theProvider)) if not self._bigDoc: self.spellCheckDocument() diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py index c7fc5aeb..afa59057 100644 --- a/nw/gui/statusbar.py +++ b/nw/gui/statusbar.py @@ -126,7 +126,7 @@ class GuiMainStatus(QStatusBar): self.setLanguage(None, "") self.setStats(0, 0) self.setProjectStatus(None) - self.updateDocumentStatus(None) + self.setDocumentStatus(None) self.updateTime() return True @@ -147,6 +147,18 @@ class GuiMainStatus(QStatusBar): qApp.processEvents() return + def setProjectStatus(self, isChanged): + """Set the project status colour icon. + """ + self.projIcon.setState(isChanged) + return + + def setDocumentStatus(self, isChanged): + """Set the document status colour icon. + """ + self.docIcon.setState(isChanged) + return + def setStats(self, pWC, sWC): """Set the current project statistics. """ @@ -191,7 +203,7 @@ class GuiMainStatus(QStatusBar): def setLanguage(self, theLanguage, theProvider): """Set the language code for the spell checker. """ - if theLanguage is None: + if theLanguage == "None": self.langText.setText(self.tr("None")) self.langText.setToolTip("") else: @@ -206,17 +218,17 @@ class GuiMainStatus(QStatusBar): return @pyqtSlot(bool) - def setProjectStatus(self, isChanged): - """Set the project status colour icon. + def doUpdateProjectStatus(self, isChanged): + """Slot for updating the project status. """ - self.projIcon.setState(isChanged) + self.setProjectStatus(isChanged) return @pyqtSlot(bool) - def updateDocumentStatus(self, isChanged): - """Set the document status colour icon. + def doUpdateDocumentStatus(self, isChanged): + """Slot for updating the document status. """ - self.docIcon.setState(isChanged) + self.setDocumentStatus(isChanged) return # END Class GuiMainStatus diff --git a/nw/guimain.py b/nw/guimain.py index 9d077b06..b82852e5 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -121,7 +121,7 @@ class GuiMain(QMainWindow): # Signals Between Main Elements self.docEditor.spellDictionaryChanged.connect(self.statusBar.setLanguage) - self.docEditor.editorDocumentChanged.connect(self.statusBar.updateDocumentStatus) + self.docEditor.docEditedStatusChanged.connect(self.statusBar.doUpdateDocumentStatus) # Minor GUI Elements self.statusIcons = [] @@ -382,7 +382,7 @@ class GuiMain(QMainWindow): self.rebuildIndex(beQuiet=True) self.statusBar.setRefTime(self.theProject.projOpened) self.statusBar.setProjectStatus(True) - self.statusBar.updateDocumentStatus(None) + self.statusBar.setDocumentStatus(None) self.statusBar.setStatus(self.tr("New project created ...")) self._updateWindowTitle(self.theProject.projName) else: From 0cad96fdca66d332255a74810f930aede6f8f31a Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 May 2021 16:43:44 +0200 Subject: [PATCH 5/8] Use an enum to pass values to the status bar LEDs --- nw/core/project.py | 2 +- nw/enum.py | 8 ++++++++ nw/gui/statusbar.py | 38 ++++++++++++++++++++------------------ nw/guimain.py | 6 +++--- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/nw/core/project.py b/nw/core/project.py index 7c95b997..c3dba7e6 100644 --- a/nw/core/project.py +++ b/nw/core/project.py @@ -1109,7 +1109,7 @@ class NWProject(): information to the GUI statusbar. """ self.projChanged = bValue - self.theParent.setProjectStatus(self.projChanged) + self.theParent.statusBar.doUpdateProjectStatus(bValue) if bValue: # If we've changed the project at all, this should be True self.projAltered = True diff --git a/nw/enum.py b/nw/enum.py index 7136377d..7b3c8aaa 100644 --- a/nw/enum.py +++ b/nw/enum.py @@ -112,6 +112,14 @@ class nwAlert(Enum): # END Enum nwAlert +class nwState(Enum): + + NONE = 0 + BAD = 1 + GOOD = 2 + +# END Enum nwState + class nwWidget(Enum): TREE = 1 diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py index afa59057..9092bc6b 100644 --- a/nw/gui/statusbar.py +++ b/nw/gui/statusbar.py @@ -34,6 +34,7 @@ from PyQt5.QtGui import QColor, QPainter from PyQt5.QtWidgets import qApp, QStatusBar, QLabel, QAbstractButton from nw.common import formatTime +from nw.enum import nwState logger = logging.getLogger(__name__) @@ -125,8 +126,8 @@ class GuiMainStatus(QStatusBar): self.setRefTime(None) self.setLanguage(None, "") self.setStats(0, 0) - self.setProjectStatus(None) - self.setDocumentStatus(None) + self.setProjectStatus(nwState.NONE) + self.setDocumentStatus(nwState.NONE) self.updateTime() return True @@ -147,16 +148,16 @@ class GuiMainStatus(QStatusBar): qApp.processEvents() return - def setProjectStatus(self, isChanged): + def setProjectStatus(self, theState): """Set the project status colour icon. """ - self.projIcon.setState(isChanged) + self.projIcon.setState(theState) return - def setDocumentStatus(self, isChanged): + def setDocumentStatus(self, theState): """Set the document status colour icon. """ - self.docIcon.setState(isChanged) + self.docIcon.setState(theState) return def setStats(self, pWC, sWC): @@ -221,26 +222,26 @@ class GuiMainStatus(QStatusBar): def doUpdateProjectStatus(self, isChanged): """Slot for updating the project status. """ - self.setProjectStatus(isChanged) + self.setProjectStatus(nwState.GOOD if isChanged else nwState.BAD) return @pyqtSlot(bool) def doUpdateDocumentStatus(self, isChanged): """Slot for updating the document status. """ - self.setDocumentStatus(isChanged) + self.setDocumentStatus(nwState.GOOD if isChanged else nwState.BAD) return # END Class GuiMainStatus class StatusLED(QAbstractButton): - def __init__(self, colNone, colTrue, colFalse, sW, sH, parent=None): + def __init__(self, colNone, colGood, colBad, sW, sH, parent=None): super().__init__(parent=parent) - self.colNone = colNone - self.colTrue = colTrue - self.colFalse = colFalse + self._colNone = colNone + self._colGood = colGood + self._colBad = colBad self._theCol = colNone self.setFixedWidth(sW) @@ -255,11 +256,12 @@ class StatusLED(QAbstractButton): def setState(self, theState): """Set the colour state. """ - self._theCol = self.colNone - if theState is True: - self._theCol = self.colTrue - elif theState is False: - self._theCol = self.colFalse + if theState == nwState.GOOD: + self._theCol = self._colGood + elif theState == nwState.BAD: + self._theCol = self._colBad + else: + self._theCol = self._colNone self.update() @@ -269,7 +271,7 @@ class StatusLED(QAbstractButton): # Events ## - def paintEvent(self, event): + def paintEvent(self, _): """Drawing the LED. """ qPalette = self.palette() diff --git a/nw/guimain.py b/nw/guimain.py index b82852e5..c1dc5ce0 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -49,7 +49,7 @@ from nw.dialogs import ( ) from nw.tools import GuiBuildNovel, GuiProjectWizard, GuiWritingStats from nw.core import NWProject, NWIndex -from nw.enum import nwItemType, nwItemClass, nwAlert, nwWidget +from nw.enum import nwItemType, nwItemClass, nwAlert, nwWidget, nwState from nw.common import getGuiItem, hexToInt from nw.constants import nwLists @@ -381,8 +381,8 @@ class GuiMain(QMainWindow): self.docEditor.setDictionaries() self.rebuildIndex(beQuiet=True) self.statusBar.setRefTime(self.theProject.projOpened) - self.statusBar.setProjectStatus(True) - self.statusBar.setDocumentStatus(None) + self.statusBar.setProjectStatus(nwState.GOOD) + self.statusBar.setDocumentStatus(nwState.NONE) self.statusBar.setStatus(self.tr("New project created ...")) self._updateWindowTitle(self.theProject.projName) else: From 872b8e790251a5c2af4fadafa668d4a7f38de7a9 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 May 2021 16:57:00 +0200 Subject: [PATCH 6/8] Fix broken tests --- tests/mock.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/mock.py b/tests/mock.py index 410d95ed..e5de4666 100644 --- a/tests/mock.py +++ b/tests/mock.py @@ -89,6 +89,9 @@ class MockStatusBar(): def setStatus(self, theText): return + def doUpdateProjectStatus(self, theStatus): + return + # END Class MockStatusBar class MockApp: From 1a5076438d2f04c9fc7ef94cd855a4dd23cda2b2 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 May 2021 17:31:12 +0200 Subject: [PATCH 7/8] Add a signal for updated word counts --- nw/gui/doceditor.py | 7 ++++--- nw/gui/itemdetails.py | 29 +++++++++++++++++------------ nw/gui/projtree.py | 25 +++++++++++++++++++++++-- nw/gui/statusbar.py | 17 +++++++++-------- nw/guimain.py | 16 ++++++++++------ 5 files changed, 63 insertions(+), 31 deletions(-) diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index ecf8ce33..9095dea0 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -67,6 +67,7 @@ class GuiDocEditor(QTextEdit): # Custom Signals spellDictionaryChanged = pyqtSignal(str, str) docEditedStatusChanged = pyqtSignal(bool) + docCountsChanged = pyqtSignal(str, int, int, int) def __init__(self, theParent): QTextEdit.__init__(self, theParent) @@ -1193,9 +1194,9 @@ class GuiDocEditor(QTextEdit): self._nwItem.setWordCount(wCount) self._nwItem.setParaCount(pCount) - self.theParent.treeView.propagateCount(self._docHandle, wCount) - self.theParent.treeView.projectWordCount() - self.theParent.treeMeta.updateCounts(self._docHandle, cCount, wCount, pCount) + # Must not be emitted if docHandle is None! + self.docCountsChanged.emit(self._docHandle, cCount, wCount, pCount) + self._checkDocSize(self._qDocument.characterCount()) self.docFooter.updateCounts() diff --git a/nw/gui/itemdetails.py b/nw/gui/itemdetails.py index 79162382..2e1a00a4 100644 --- a/nw/gui/itemdetails.py +++ b/nw/gui/itemdetails.py @@ -27,7 +27,7 @@ along with this program. If not, see . import nw import logging -from PyQt5.QtCore import Qt +from PyQt5.QtCore import Qt, pyqtSlot from PyQt5.QtGui import QFont, QPixmap from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel @@ -212,17 +212,6 @@ class GuiItemDetails(QWidget): return - def updateCounts(self, tHandle, cC, wC, pC): - """Update the counts if the handle is the same as the one we're - already showing. Otherwise, do nothing. - """ - if tHandle == self.theHandle: - self.cCountData.setText(f"{cC:n}") - self.wCountData.setText(f"{wC:n}") - self.pCountData.setText(f"{pC:n}") - - return - def updateViewBox(self, tHandle): """Populate the details box from a given handle. """ @@ -281,4 +270,20 @@ class GuiItemDetails(QWidget): return + ## + # Slots + ## + + @pyqtSlot(str, int, int, int) + def doUpdateCounts(self, tHandle, cC, wC, pC): + """Update the counts if the handle is the same as the one we're + already showing. Otherwise, do nothing. + """ + if tHandle == self.theHandle: + self.cCountData.setText(f"{cC:n}") + self.wCountData.setText(f"{wC:n}") + self.pCountData.setText(f"{pC:n}") + + return + # END Class GuiItemDetails diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index f4f3c7be..c9b82cbe 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -30,7 +30,7 @@ import logging from time import time -from PyQt5.QtCore import Qt, QSize, pyqtSignal +from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import ( QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction @@ -51,6 +51,7 @@ class GuiProjectTree(QTreeWidget): novelItemChanged = pyqtSignal() noteItemChanged = pyqtSignal() + projectWordCountChanged = pyqtSignal(int, int) def __init__(self, theParent): QTreeWidget.__init__(self, theParent) @@ -674,7 +675,8 @@ class GuiProjectTree(QTreeWidget): self.theProject.setProjectWordCount(nWords) sWords = self.theProject.getSessionWordCount() - self.theParent.statusBar.setStats(nWords, sWords) + + self.projectWordCountChanged.emit(nWords, sWords) return @@ -779,6 +781,7 @@ class GuiProjectTree(QTreeWidget): # Slots ## + @pyqtSlot("QPoint") def _rightClickMenu(self, clickPos): """The user right clicked an element in the project tree, so we open a context menu in-place. @@ -795,6 +798,14 @@ class GuiProjectTree(QTreeWidget): return + @pyqtSlot(str, int, int, int) + def doUpdateCounts(self, tHandle, cCount, wCount, pCount): + """Slot for updating the word count of a specific item. + """ + self.propagateCount(tHandle, wCount) + self.projectWordCount() + return + ## # Events ## @@ -1171,6 +1182,7 @@ class GuiProjectTreeMenu(QMenu): # Slots ## + @pyqtSlot() def _doOpenItem(self): """Forward the open document call to the main GUI window. """ @@ -1178,6 +1190,7 @@ class GuiProjectTreeMenu(QMenu): self.theTree.theParent.openDocument(self.theItem.itemHandle, doScroll=False) return + @pyqtSlot() def _doViewItem(self): """Forward the view document call to the main GUI window. """ @@ -1185,6 +1198,7 @@ class GuiProjectTreeMenu(QMenu): self.theTree.theParent.viewDocument(self.theItem.itemHandle) return + @pyqtSlot() def _doEditItem(self): """Forward the edit item call to the main GUI window. """ @@ -1192,6 +1206,7 @@ class GuiProjectTreeMenu(QMenu): self.theTree.theParent.editItem() return + @pyqtSlot() def _doMakeFile(self): """Forward the new file call to the project tree. """ @@ -1199,6 +1214,7 @@ class GuiProjectTreeMenu(QMenu): self.theTree.newTreeItem(nwItemType.FILE, None) return + @pyqtSlot() def _doMakeFolder(self): """Forward the new folder call to the project tree. """ @@ -1206,6 +1222,7 @@ class GuiProjectTreeMenu(QMenu): self.theTree.newTreeItem(nwItemType.FOLDER, None) return + @pyqtSlot() def _doToggleExported(self): """Flip the isExported flag of the current item. """ @@ -1214,6 +1231,7 @@ class GuiProjectTreeMenu(QMenu): self.theTree.setTreeItemValues(self.theItem.itemHandle) return + @pyqtSlot() def _doDeleteItem(self): """Forward the delete item call to the project tree. """ @@ -1221,18 +1239,21 @@ class GuiProjectTreeMenu(QMenu): self.theTree.deleteItem() return + @pyqtSlot() def _doEmptyTrash(self): """Forward the empty trash call to the project tree. """ self.theTree.emptyTrash() return + @pyqtSlot() def _doMoveUp(self): """Forward the move item call to the project tree. """ self.theTree.moveTreeItem(-1) return + @pyqtSlot() def _doMoveDown(self): """Forward the move item call to the project tree. """ diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py index 9092bc6b..85a9f58c 100644 --- a/nw/gui/statusbar.py +++ b/nw/gui/statusbar.py @@ -125,7 +125,7 @@ class GuiMainStatus(QStatusBar): """ self.setRefTime(None) self.setLanguage(None, "") - self.setStats(0, 0) + self.doUpdateProjectStats(0, 0) self.setProjectStatus(nwState.NONE) self.setDocumentStatus(nwState.NONE) self.updateTime() @@ -160,13 +160,6 @@ class GuiMainStatus(QStatusBar): self.docIcon.setState(theState) return - def setStats(self, pWC, sWC): - """Set the current project statistics. - """ - self.statsText.setText(self.tr("Words: {0} ({1})").format(f"{pWC:n}", f"{sWC:+n}")) - self.statsText.setToolTip(self.tr("Project word count (session change)")) - return - def setUserIdle(self, userIdle): """Change the idle status icon. """ @@ -218,6 +211,14 @@ class GuiMainStatus(QStatusBar): return + @pyqtSlot(int, int) + def doUpdateProjectStats(self, pWC, sWC): + """Update the current project statistics. + """ + self.statsText.setText(self.tr("Words: {0} ({1})").format(f"{pWC:n}", f"{sWC:+n}")) + self.statsText.setToolTip(self.tr("Project word count (session change)")) + return + @pyqtSlot(bool) def doUpdateProjectStatus(self, isChanged): """Slot for updating the project status. diff --git a/nw/guimain.py b/nw/guimain.py index c1dc5ce0..9ea300cb 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -119,9 +119,16 @@ class GuiMain(QMainWindow): self.projMeta = GuiOutlineDetails(self) self.mainMenu = GuiMainMenu(self) - # Signals Between Main Elements + # Connect Signals Between Main Elements self.docEditor.spellDictionaryChanged.connect(self.statusBar.setLanguage) self.docEditor.docEditedStatusChanged.connect(self.statusBar.doUpdateDocumentStatus) + self.docEditor.docCountsChanged.connect(self.treeMeta.doUpdateCounts) + self.docEditor.docCountsChanged.connect(self.treeView.doUpdateCounts) + + self.treeView.itemSelectionChanged.connect(self._treeSingleClick) + self.treeView.itemDoubleClicked.connect(self._treeDoubleClick) + self.treeView.novelItemChanged.connect(self._treeNovelItemChanged) + self.treeView.projectWordCountChanged.connect(self.statusBar.doUpdateProjectStats) # Minor GUI Elements self.statusIcons = [] @@ -231,9 +238,6 @@ class GuiMain(QMainWindow): self.docEditor.closeSearch() # Initialise the Project Tree - self.treeView.itemSelectionChanged.connect(self._treeSingleClick) - self.treeView.itemDoubleClicked.connect(self._treeDoubleClick) - self.treeView.novelItemChanged.connect(self._treeNovelItemChanged) self.rebuildTrees() # Set Main Window Elements @@ -524,7 +528,7 @@ class GuiMain(QMainWindow): self.docEditor.setSpellCheck(self.theProject.spellCheck) self.mainMenu.setAutoOutline(self.theProject.autoOutline) self.statusBar.setRefTime(self.theProject.projOpened) - self.statusBar.setStats(self.theProject.currWCount, 0) + self.statusBar.doUpdateProjectStats(self.theProject.currWCount, 0) # Restore previously open documents, if any if self.theProject.lastEdited is not None: @@ -882,7 +886,7 @@ class GuiMain(QMainWindow): self.treeView.saveTreeOrder() self.theIndex.clearIndex() - for nDone, tItem in enumerate(self.theProject.projTree): + for tItem in self.theProject.projTree: if tItem is not None: self.setStatus(self.tr("Indexing: '{0}'").format(tItem.itemName)) From 394f6adf8212b8fb3c0452cd14bd42e9e169b191 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 16 May 2021 17:35:33 +0200 Subject: [PATCH 8/8] Remove no longer needed forward function --- nw/guimain.py | 1 - tests/mock.py | 3 --- 2 files changed, 4 deletions(-) diff --git a/nw/guimain.py b/nw/guimain.py index 9ea300cb..f3f8ba7e 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -275,7 +275,6 @@ class GuiMain(QMainWindow): # Forward Functions self.setStatus = self.statusBar.setStatus - self.setProjectStatus = self.statusBar.setProjectStatus # Force a show of the GUI self.show() diff --git a/tests/mock.py b/tests/mock.py index e5de4666..05298ad3 100644 --- a/tests/mock.py +++ b/tests/mock.py @@ -54,9 +54,6 @@ class MockGuiMain(): def setStatus(self, theMessage): return - def setProjectStatus(self, isChanged): - return - def openProject(self, projPath): return