Make the item class non-dynamic, and cache formatting vars in editor

This commit is contained in:
Veronica Berglyd Olsen
2022-11-11 17:09:03 +01:00
parent b05028e3c9
commit 612034f6be
5 changed files with 80 additions and 57 deletions
-3
View File
@@ -235,9 +235,6 @@ class Config:
# Packages # Packages
self.hasEnchant = False # The pyenchant package self.hasEnchant = False # The pyenchant package
# Recent Cache
self.recentProj = {}
return return
## ##
+21 -15
View File
@@ -36,10 +36,16 @@ logger = logging.getLogger(__name__)
class NWItem: class NWItem:
def __init__(self, theProject): __slots__ = (
"_project", "_name", "_handle", "_parent", "_root", "_order",
"_type", "_class", "_layout", "_status", "_import", "_active",
"_expanded", "_heading", "_charCount", "_wordCount",
"_paraCount", "_cursorPos", "_initCount",
)
self.theProject = theProject def __init__(self, project):
self._project = project
self._name = "" self._name = ""
self._handle = None self._handle = None
self._parent = None self._parent = None
@@ -267,11 +273,11 @@ class NWItem:
the current item based on its class. the current item based on its class.
""" """
if self.isNovelLike(): if self.isNovelLike():
stName = self.theProject.data.itemStatus.name(self._status) stName = self._project.data.itemStatus.name(self._status)
stIcon = self.theProject.data.itemStatus.icon(self._status) if incIcon else None stIcon = self._project.data.itemStatus.icon(self._status) if incIcon else None
else: else:
stName = self.theProject.data.itemImport.name(self._import) stName = self._project.data.itemImport.name(self._import)
stIcon = self.theProject.data.itemImport.icon(self._import) if incIcon else None stIcon = self._project.data.itemImport.icon(self._import) if incIcon else None
return stName, stIcon return stName, stIcon
## ##
@@ -443,32 +449,32 @@ class NWItem:
"""Set the item status by looking it up in the valid status """Set the item status by looking it up in the valid status
items of the current project. items of the current project.
""" """
self._status = self.theProject.data.itemStatus.check(value) self._status = self._project.data.itemStatus.check(value)
return return
def setImport(self, value): def setImport(self, value):
"""Set the item importance by looking it up in the valid import """Set the item importance by looking it up in the valid import
items of the current project. items of the current project.
""" """
self._import = self.theProject.data.itemImport.check(value) self._import = self._project.data.itemImport.check(value)
return return
def setActive(self, state): def setActive(self, state):
"""Set the export flag. """Set the active flag.
""" """
if isinstance(state, str): if isinstance(state, bool):
self._active = (state == str(True)) self._active = state
else: else:
self._active = (state is True) self._active = False
return return
def setExpanded(self, state): def setExpanded(self, state):
"""Set the expanded status of an item in the project tree. """Set the expanded status of an item in the project tree.
""" """
if isinstance(state, str): if isinstance(state, bool):
self._expanded = (state == str(True)) self._expanded = state
else: else:
self._expanded = (state is True) self._expanded = False
return return
## ##
+50 -30
View File
@@ -105,8 +105,18 @@ class GuiDocEditor(QTextEdit):
self._doReplace = False # Switch to temporarily disable auto-replace self._doReplace = False # Switch to temporarily disable auto-replace
self._queuePos = None # Used for delayed change of cursor position self._queuePos = None # Used for delayed change of cursor position
# Typography # Typography Cache
self._typPadChar = " " self._typPadChar = " "
self._typDQuoteO = '"'
self._typDQuoteC = '"'
self._typSQuoteO = "'"
self._typSQuoteC = "'"
self._typRepDQuote = False
self._typRepSQuote = False
self._typRepDash = False
self._typRepDots = False
self._typPadBefore = ""
self._typPadAfter = ""
# Core Elements and Signals # Core Elements and Signals
qDoc = self.document() qDoc = self.document()
@@ -243,7 +253,6 @@ class GuiDocEditor(QTextEdit):
f"{self.mainConf.fmtSQuoteOpen}{self.mainConf.fmtSQuoteClose}" f"{self.mainConf.fmtSQuoteOpen}{self.mainConf.fmtSQuoteClose}"
f"{self.mainConf.fmtDQuoteOpen}{self.mainConf.fmtDQuoteClose}" f"{self.mainConf.fmtDQuoteOpen}{self.mainConf.fmtDQuoteClose}"
) )
print(self._nonWord)
# Typography # Typography
if self.mainConf.fmtPadThin: if self.mainConf.fmtPadThin:
@@ -251,6 +260,17 @@ class GuiDocEditor(QTextEdit):
else: else:
self._typPadChar = nwUnicode.U_NBSP self._typPadChar = nwUnicode.U_NBSP
self._typSQuoteO = self.mainConf.fmtSQuoteOpen
self._typSQuoteC = self.mainConf.fmtSQuoteClose
self._typDQuoteO = self.mainConf.fmtDQuoteOpen
self._typDQuoteC = self.mainConf.fmtDQuoteClose
self._typRepDQuote = self.mainConf.doReplaceDQuote
self._typRepSQuote = self.mainConf.doReplaceSQuote
self._typRepDash = self.mainConf.doReplaceDash
self._typRepDots = self.mainConf.doReplaceDots
self._typPadBefore = self.mainConf.fmtPadBefore
self._typPadAfter = self.mainConf.fmtPadAfter
# Reload spell check and dictionaries # Reload spell check and dictionaries
self.setDictionaries() self.setDictionaries()
@@ -786,9 +806,9 @@ class GuiDocEditor(QTextEdit):
elif theAction == nwDocAction.STRIKE: elif theAction == nwDocAction.STRIKE:
self._toggleFormat(2, "~") self._toggleFormat(2, "~")
elif theAction == nwDocAction.S_QUOTE: elif theAction == nwDocAction.S_QUOTE:
self._wrapSelection(self.mainConf.fmtSQuoteOpen, self.mainConf.fmtSQuoteClose) self._wrapSelection(self._typSQuoteO, self._typSQuoteC)
elif theAction == nwDocAction.D_QUOTE: elif theAction == nwDocAction.D_QUOTE:
self._wrapSelection(self.mainConf.fmtDQuoteOpen, self.mainConf.fmtDQuoteClose) self._wrapSelection(self._typDQuoteO, self._typDQuoteC)
elif theAction == nwDocAction.SEL_ALL: elif theAction == nwDocAction.SEL_ALL:
self._makeSelection(QTextCursor.Document) self._makeSelection(QTextCursor.Document)
elif theAction == nwDocAction.SEL_PARA: elif theAction == nwDocAction.SEL_PARA:
@@ -810,9 +830,9 @@ class GuiDocEditor(QTextEdit):
elif theAction == nwDocAction.BLOCK_UNN: elif theAction == nwDocAction.BLOCK_UNN:
self._formatBlock(nwDocAction.BLOCK_UNN) self._formatBlock(nwDocAction.BLOCK_UNN)
elif theAction == nwDocAction.REPL_SNG: elif theAction == nwDocAction.REPL_SNG:
self._replaceQuotes("'", self.mainConf.fmtSQuoteOpen, self.mainConf.fmtSQuoteClose) self._replaceQuotes("'", self._typSQuoteO, self._typSQuoteC)
elif theAction == nwDocAction.REPL_DBL: elif theAction == nwDocAction.REPL_DBL:
self._replaceQuotes("\"", self.mainConf.fmtDQuoteOpen, self.mainConf.fmtDQuoteClose) self._replaceQuotes("\"", self._typDQuoteO, self._typDQuoteC)
elif theAction == nwDocAction.RM_BREAKS: elif theAction == nwDocAction.RM_BREAKS:
self._removeInParLineBreaks() self._removeInParLineBreaks()
elif theAction == nwDocAction.ALIGN_L: elif theAction == nwDocAction.ALIGN_L:
@@ -878,13 +898,13 @@ class GuiDocEditor(QTextEdit):
theText = theInsert theText = theInsert
elif isinstance(theInsert, nwDocInsert): elif isinstance(theInsert, nwDocInsert):
if theInsert == nwDocInsert.QUOTE_LS: if theInsert == nwDocInsert.QUOTE_LS:
theText = self.mainConf.fmtSQuoteOpen theText = self._typSQuoteO
elif theInsert == nwDocInsert.QUOTE_RS: elif theInsert == nwDocInsert.QUOTE_RS:
theText = self.mainConf.fmtSQuoteClose theText = self._typSQuoteC
elif theInsert == nwDocInsert.QUOTE_LD: elif theInsert == nwDocInsert.QUOTE_LD:
theText = self.mainConf.fmtDQuoteOpen theText = self._typDQuoteO
elif theInsert == nwDocInsert.QUOTE_RD: elif theInsert == nwDocInsert.QUOTE_RD:
theText = self.mainConf.fmtDQuoteClose theText = self._typDQuoteC
elif theInsert == nwDocInsert.SYNOPSIS: elif theInsert == nwDocInsert.SYNOPSIS:
theText = "% Synopsis: " theText = "% Synopsis: "
newBlock = True newBlock = True
@@ -1959,49 +1979,49 @@ class GuiDocEditor(QTextEdit):
nDelete = 0 nDelete = 0
tInsert = theOne tInsert = theOne
if self.mainConf.doReplaceDQuote and theTwo[:1].isspace() and theTwo.endswith('"'): if self._typRepDQuote and theTwo[:1].isspace() and theTwo.endswith('"'):
nDelete = 1 nDelete = 1
tInsert = self.mainConf.fmtDQuoteOpen tInsert = self._typDQuoteO
elif self.mainConf.doReplaceDQuote and theOne == '"': elif self._typRepDQuote and theOne == '"':
nDelete = 1 nDelete = 1
if thePos == 1: if thePos == 1:
tInsert = self.mainConf.fmtDQuoteOpen tInsert = self._typDQuoteO
elif thePos == 2 and theTwo == '>"': elif thePos == 2 and theTwo == '>"':
tInsert = self.mainConf.fmtDQuoteOpen tInsert = self._typDQuoteO
elif thePos == 3 and theThree == '>>"': elif thePos == 3 and theThree == '>>"':
tInsert = self.mainConf.fmtDQuoteOpen tInsert = self._typDQuoteO
else: else:
tInsert = self.mainConf.fmtDQuoteClose tInsert = self._typDQuoteC
elif self.mainConf.doReplaceSQuote and theTwo[:1].isspace() and theTwo.endswith("'"): elif self._typRepSQuote and theTwo[:1].isspace() and theTwo.endswith("'"):
nDelete = 1 nDelete = 1
tInsert = self.mainConf.fmtSQuoteOpen tInsert = self._typSQuoteO
elif self.mainConf.doReplaceSQuote and theOne == "'": elif self._typRepSQuote and theOne == "'":
nDelete = 1 nDelete = 1
if thePos == 1: if thePos == 1:
tInsert = self.mainConf.fmtSQuoteOpen tInsert = self._typSQuoteO
elif thePos == 2 and theTwo == ">'": elif thePos == 2 and theTwo == ">'":
tInsert = self.mainConf.fmtSQuoteOpen tInsert = self._typSQuoteO
elif thePos == 3 and theThree == ">>'": elif thePos == 3 and theThree == ">>'":
tInsert = self.mainConf.fmtSQuoteOpen tInsert = self._typSQuoteO
else: else:
tInsert = self.mainConf.fmtSQuoteClose tInsert = self._typSQuoteC
elif self.mainConf.doReplaceDash and theThree == "---": elif self._typRepDash and theThree == "---":
nDelete = 3 nDelete = 3
tInsert = nwUnicode.U_EMDASH tInsert = nwUnicode.U_EMDASH
elif self.mainConf.doReplaceDash and theTwo == "--": elif self._typRepDash and theTwo == "--":
nDelete = 2 nDelete = 2
tInsert = nwUnicode.U_ENDASH tInsert = nwUnicode.U_ENDASH
elif self.mainConf.doReplaceDash and theTwo == nwUnicode.U_ENDASH + "-": elif self._typRepDash and theTwo == nwUnicode.U_ENDASH + "-":
nDelete = 2 nDelete = 2
tInsert = nwUnicode.U_EMDASH tInsert = nwUnicode.U_EMDASH
elif self.mainConf.doReplaceDots and theThree == "...": elif self._typRepDots and theThree == "...":
nDelete = 3 nDelete = 3
tInsert = nwUnicode.U_HELLIP tInsert = nwUnicode.U_HELLIP
@@ -2011,7 +2031,7 @@ class GuiDocEditor(QTextEdit):
tInsert = nwUnicode.U_PSEP tInsert = nwUnicode.U_PSEP
tCheck = tInsert tCheck = tInsert
if self.mainConf.fmtPadBefore and tCheck in self.mainConf.fmtPadBefore: if self._typPadBefore and tCheck in self._typPadBefore:
if self._allowSpaceBeforeColon(theText, tCheck): if self._allowSpaceBeforeColon(theText, tCheck):
nDelete = max(nDelete, 1) nDelete = max(nDelete, 1)
chkPos = thePos - nDelete - 1 chkPos = thePos - nDelete - 1
@@ -2020,7 +2040,7 @@ class GuiDocEditor(QTextEdit):
nDelete += 1 nDelete += 1
tInsert = self._typPadChar + tInsert tInsert = self._typPadChar + tInsert
if self.mainConf.fmtPadAfter and tCheck in self.mainConf.fmtPadAfter: if self._typPadAfter and tCheck in self._typPadAfter:
if self._allowSpaceBeforeColon(theText, tCheck): if self._allowSpaceBeforeColon(theText, tCheck):
nDelete = max(nDelete, 1) nDelete = max(nDelete, 1)
tInsert = tInsert + self._typPadChar tInsert = tInsert + self._typPadChar
+3 -3
View File
@@ -133,11 +133,11 @@ def testCoreItem_Setters(mockGUI, mockRnd, fncPath):
theItem.setExpanded("What?") theItem.setExpanded("What?")
assert theItem.isExpanded is False assert theItem.isExpanded is False
theItem.setExpanded("True") theItem.setExpanded("True")
assert theItem.isExpanded is True assert theItem.isExpanded is False
theItem.setExpanded(True) theItem.setExpanded(True)
assert theItem.isExpanded is True assert theItem.isExpanded is True
# Exported # Active
theItem.setActive(8) theItem.setActive(8)
assert theItem.isActive is False assert theItem.isActive is False
theItem.setActive(None) theItem.setActive(None)
@@ -147,7 +147,7 @@ def testCoreItem_Setters(mockGUI, mockRnd, fncPath):
theItem.setActive("What?") theItem.setActive("What?")
assert theItem.isActive is False assert theItem.isActive is False
theItem.setActive("True") theItem.setActive("True")
assert theItem.isActive is True assert theItem.isActive is False
theItem.setActive(True) theItem.setActive(True)
assert theItem.isActive is True assert theItem.isActive is True
+6 -6
View File
@@ -432,19 +432,19 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY) qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY)
# Insert spaces before and after quotes # Insert spaces before and after quotes
nwGUI.mainConf.fmtPadBefore = "\u201d" nwGUI.docEditor._typPadBefore = "\u201d"
nwGUI.mainConf.fmtPadAfter = "\u201c" nwGUI.docEditor._typPadAfter = "\u201c"
for c in "Some \"double quoted text with spaces padded\".": for c in "Some \"double quoted text with spaces padded\".":
qtbot.keyClick(nwGUI.docEditor, c, delay=KEY_DELAY) qtbot.keyClick(nwGUI.docEditor, c, delay=KEY_DELAY)
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY) qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY)
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY) qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY)
nwGUI.mainConf.fmtPadBefore = "" nwGUI.docEditor._typPadBefore = ""
nwGUI.mainConf.fmtPadAfter = "" nwGUI.docEditor._typPadAfter = ""
# Insert spaces before colon, but ignore tags and synopsis # Insert spaces before colon, but ignore tags and synopsis
nwGUI.mainConf.fmtPadBefore = ":" nwGUI.docEditor._typPadBefore = ":"
for c in "@object: NoSpaceAdded": for c in "@object: NoSpaceAdded":
qtbot.keyClick(nwGUI.docEditor, c, delay=KEY_DELAY) qtbot.keyClick(nwGUI.docEditor, c, delay=KEY_DELAY)
@@ -466,7 +466,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY) qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY)
qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY) qtbot.keyClick(nwGUI.docEditor, Qt.Key_Return, delay=KEY_DELAY)
nwGUI.mainConf.fmtPadBefore = "" nwGUI.docEditor._typPadBefore = ""
# Indent and Align # Indent and Align
# ================ # ================