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