Make the editor actually Plain Text (#1521)

This commit is contained in:
Veronica Berglyd Olsen
2023-09-06 20:10:09 +01:00
committed by GitHub
12 changed files with 259 additions and 487 deletions
-6
View File
@@ -144,12 +144,10 @@ class Config:
self.doReplaceDash = True # Replace multiple hyphens with dashes
self.doReplaceDots = True # Replace three dots with ellipsis
self.scrollPastEnd = 25 # Number of lines to scroll past end of document
self.autoScroll = False # Typewriter-like scrolling
self.autoScrollPos = 30 # Start point for typewriter-like scrolling
self.wordCountTimer = 5.0 # Interval for word count update in seconds
self.bigDocLimit = 800 # Size threshold for heavy editor features in kilobytes
self.incNotesWCount = True # The status bar word count includes notes
self.highlightQuotes = True # Highlight text in quotes
@@ -573,7 +571,6 @@ class Config:
self.doReplaceDQuote = conf.rdBool(sec, "repdquotes", self.doReplaceDQuote)
self.doReplaceDash = conf.rdBool(sec, "repdash", self.doReplaceDash)
self.doReplaceDots = conf.rdBool(sec, "repdots", self.doReplaceDots)
self.scrollPastEnd = conf.rdInt(sec, "scrollpastend", self.scrollPastEnd)
self.autoScroll = conf.rdBool(sec, "autoscroll", self.autoScroll)
self.autoScrollPos = conf.rdInt(sec, "autoscrollpos", self.autoScrollPos)
self.fmtSQuoteOpen = conf.rdStr(sec, "fmtsquoteopen", self.fmtSQuoteOpen)
@@ -588,7 +585,6 @@ class Config:
self.showLineEndings = conf.rdBool(sec, "showlineendings", self.showLineEndings)
self.showMultiSpaces = conf.rdBool(sec, "showmultispaces", self.showMultiSpaces)
self.wordCountTimer = conf.rdFlt(sec, "wordcounttimer", self.wordCountTimer)
self.bigDocLimit = conf.rdInt(sec, "bigdoclimit", self.bigDocLimit)
self.incNotesWCount = conf.rdBool(sec, "incnoteswcount", self.incNotesWCount)
self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath)
self.highlightQuotes = conf.rdBool(sec, "highlightquotes", self.highlightQuotes)
@@ -697,7 +693,6 @@ class Config:
"repdquotes": str(self.doReplaceDQuote),
"repdash": str(self.doReplaceDash),
"repdots": str(self.doReplaceDots),
"scrollpastend": str(self.scrollPastEnd),
"autoscroll": str(self.autoScroll),
"autoscrollpos": str(self.autoScrollPos),
"fmtsquoteopen": str(self.fmtSQuoteOpen),
@@ -712,7 +707,6 @@ class Config:
"showlineendings": str(self.showLineEndings),
"showmultispaces": str(self.showMultiSpaces),
"wordcounttimer": str(self.wordCountTimer),
"bigdoclimit": str(self.bigDocLimit),
"incnoteswcount": str(self.incNotesWCount),
"showfullpath": str(self.showFullPath),
"highlightquotes": str(self.highlightQuotes),
-4
View File
@@ -40,10 +40,6 @@ class nwConst:
FMT_FSTAMP = "%Y-%m-%d %H.%M.%S" # FileName safe format
FMT_DSTAMP = "%Y-%m-%d" # Date only format
# Various Hard Limits
MAX_DOCSIZE = 5000000 # Maximum size of a single document
MAX_BUILDSIZE = 10000000 # Maximum size of a project build
# URLs
URL_WEB = "https://novelwriter.io"
URL_DOCS = "https://docs.novelwriter.io"
+1 -9
View File
@@ -38,7 +38,7 @@ from PyQt5.QtCore import QCoreApplication, QRegularExpression
from novelwriter.enum import nwItemLayout
from novelwriter.common import formatTimeStamp, numberToRoman, checkInt
from novelwriter.constants import nwConst, nwHeadFmt, nwRegEx, nwUnicode
from novelwriter.constants import nwHeadFmt, nwRegEx, nwUnicode
from novelwriter.core.project import NWProject
logger = logging.getLogger(__name__)
@@ -349,14 +349,6 @@ class Tokenizer(ABC):
self._text = text
docSize = len(self._text)
if docSize > nwConst.MAX_DOCSIZE:
errVal = self.tr("Document '{0}' is too big ({1} MB). Skipping.").format(
self._nwItem.itemName, f"{docSize/1.0e6:.2f}"
)
self._text = "# {0}\n\n{1}\n\n".format(self.tr("ERROR"), errVal)
self._errData.append(errVal)
self._isNone = self._nwItem.itemLayout == nwItemLayout.NO_LAYOUT
self._isNovel = self._nwItem.itemLayout == nwItemLayout.DOCUMENT
self._isNote = self._nwItem.itemLayout == nwItemLayout.NOTE
+1 -30
View File
@@ -675,19 +675,6 @@ class GuiPreferencesEditor(QWidget):
self.tr("Available languages are determined by your system.")
)
# Big Document Size Limit
self.bigDocLimit = QSpinBox(self)
self.bigDocLimit.setMinimum(10)
self.bigDocLimit.setMaximum(10000)
self.bigDocLimit.setSingleStep(10)
self.bigDocLimit.setValue(CONFIG.bigDocLimit)
self.mainForm.addRow(
self.tr("Big document limit"),
self.bigDocLimit,
self.tr("Full spell checking is disabled above this limit."),
unit=self.tr("kB")
)
# Word Count
# ==========
self.mainForm.addGroupLabel(self.tr("Word Count"))
@@ -737,19 +724,6 @@ class GuiPreferencesEditor(QWidget):
# ================
self.mainForm.addGroupLabel(self.tr("Scroll Behaviour"))
# Scroll Past End
self.scrollPastEnd = QSpinBox(self)
self.scrollPastEnd.setMinimum(0)
self.scrollPastEnd.setMaximum(100)
self.scrollPastEnd.setSingleStep(1)
self.scrollPastEnd.setValue(int(CONFIG.scrollPastEnd))
self.mainForm.addRow(
self.tr("Scroll past end of the document"),
self.scrollPastEnd,
self.tr("Set to 0 to disable this feature."),
unit=self.tr("lines")
)
# Typewriter Scrolling
self.autoScroll = NSwitch()
self.autoScroll.setChecked(CONFIG.autoScroll)
@@ -775,11 +749,9 @@ class GuiPreferencesEditor(QWidget):
return
def saveValues(self):
"""Save the values set for this tab.
"""
"""Save the values set for this tab."""
# Spell Checking
CONFIG.spellLanguage = self.spellLanguage.currentData()
CONFIG.bigDocLimit = self.bigDocLimit.value()
# Word Count
CONFIG.wordCountTimer = self.wordCountTimer.value()
@@ -790,7 +762,6 @@ class GuiPreferencesEditor(QWidget):
CONFIG.showLineEndings = self.showLineEndings.isChecked()
# Scroll Behaviour
CONFIG.scrollPastEnd = self.scrollPastEnd.value()
CONFIG.autoScroll = self.autoScroll.isChecked()
CONFIG.autoScrollPos = self.autoScrollPos.value()
+47 -191
View File
@@ -37,22 +37,23 @@ from time import time
from typing import TYPE_CHECKING
from PyQt5.QtCore import (
pyqtSignal, pyqtSlot, QObject, QPoint, QPointF, QPropertyAnimation,
QRegExp, QRegularExpression, QRunnable, QSize, QSizeF, Qt, QTimer
pyqtSignal, pyqtSlot, QObject, QPoint, QRegExp, QRegularExpression,
QRunnable, QSize, Qt, QTimer
)
from PyQt5.QtGui import (
QColor, QCursor, QFont, QFontMetrics, QKeyEvent, QKeySequence, QMouseEvent,
QPalette, QPixmap, QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption
QColor, QCursor, QFont, QKeyEvent, QKeySequence, QMouseEvent, QPalette,
QPixmap, QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption
)
from PyQt5.QtWidgets import (
QAction, qApp, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu,
QPushButton, QShortcut, QTextEdit, QToolBar, QToolButton, QWidget
QAction, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu,
QPlainTextEdit, QPushButton, QShortcut, QToolBar, QToolButton, QWidget,
qApp
)
from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemClass
from novelwriter.common import minmax, transferCase
from novelwriter.constants import nwConst, nwKeyWords, nwUnicode
from novelwriter.constants import nwKeyWords, nwUnicode
from novelwriter.core.index import countWords
from novelwriter.gui.dochighlight import GuiDocHighlighter
from novelwriter.extensions.wheeleventfilter import WheelEventFilter
@@ -63,7 +64,7 @@ if TYPE_CHECKING: # pragma: no cover
logger = logging.getLogger(__name__)
class GuiDocEditor(QTextEdit):
class GuiDocEditor(QPlainTextEdit):
"""Gui Widget: Main Document Editor"""
MOVE_KEYS = (
@@ -104,9 +105,7 @@ class GuiDocEditor(QTextEdit):
self._lastEdit = 0 # Time stamp of last edit
self._lastActive = 0.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 Cache
self._typPadChar = " "
@@ -124,7 +123,6 @@ class GuiDocEditor(QTextEdit):
# Core Elements and Signals
qDoc = self.document()
qDoc.contentsChange.connect(self._docChange)
qDoc.documentLayout().documentSizeChanged.connect(self._docSizeChanged)
self.selectionChanged.connect(self._updateSelectedStatus)
# Document Title
@@ -141,9 +139,9 @@ class GuiDocEditor(QTextEdit):
# Editor Settings
self.setMinimumWidth(CONFIG.pxInt(300))
self.setAcceptRichText(False)
self.setAutoFillBackground(True)
self.setFrameStyle(QFrame.NoFrame)
self.setCenterOnScroll(True)
# Custom Shortcuts
self.keyContext = QShortcut(self)
@@ -237,9 +235,7 @@ class GuiDocEditor(QTextEdit):
self._lastEdit = 0
self._lastActive = 0.0
self._lastFind = None
self._bigDoc = False
self._doReplace = False
self._queuePos = None
self.setDocumentChanged(False)
self.docHeader.setTitleFromHandle(self._docHandle)
@@ -315,7 +311,7 @@ class GuiDocEditor(QTextEdit):
# Set default text margins
# Due to cursor visibility, a part of the margin must be
# allocated to the document itself. See issue #1112.
cW = self.cursorWidth()
cW = 2*self.cursorWidth()
qDoc = self.document()
qDoc.setDocumentMargin(cW)
self._vpMargin = max(CONFIG.getTextMargin() - cW, 0)
@@ -362,7 +358,7 @@ class GuiDocEditor(QTextEdit):
return
def loadText(self, tHandle, tLine=None) -> bool:
"""Load text from a document into the editor. If we have an io
"""Load text from a document into the editor. If we have an I/O
error, we must handle this and clear the editor so that we don't
risk overwriting the file if it exists. This can for instance
happen of the file contains binary elements or an encoding that
@@ -373,87 +369,51 @@ class GuiDocEditor(QTextEdit):
self._nwDocument = SHARED.project.storage.getDocument(tHandle)
self._nwItem = self._nwDocument.nwItem
theDoc = self._nwDocument.readDocument()
if theDoc is None:
# There was an io error
self.clearEditor()
return False
docSize = len(theDoc)
if docSize > nwConst.MAX_DOCSIZE:
SHARED.error(self.tr(
"The document you are trying to open is too big. "
"The document size is {0} MB. "
"The maximum size allowed is {1} MB."
).format(
f"{docSize/1.0e6:.2f}",
f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"
))
docText = self._nwDocument.readDocument()
if docText is None:
# There was an I/O error
self.clearEditor()
return False
qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
self._docHandle = tHandle
self.highLight.setHandle(tHandle)
# Check that the document is not too big for full, initial spell
# checking. If it is too big, we switch to only check as we type
self._checkDocSize(docSize)
spTemp = self.highLight.spellCheck
if self._bigDoc:
self.highLight.setSpellCheck(False)
bfTime = time()
tStart = time()
self._allowAutoReplace(False)
self.setPlainText(theDoc)
qApp.processEvents()
self.setPlainText(docText)
self._allowAutoReplace(True)
afTime = time()
logger.debug("Document highlighted in %.3f ms", 1000*(afTime-bfTime))
logger.debug("Document text loaded in %.3f ms", 1000*(time() - tStart))
qApp.processEvents()
self._lastEdit = time()
self._lastActive = time()
self._runDocCounter()
self.wcTimerDoc.start()
self._docHandle = tHandle
self.setReadOnly(False)
self.docHeader.setTitleFromHandle(self._docHandle)
self.docFooter.setHandle(self._docHandle)
self.updateDocMargins()
self.highLight.setSpellCheck(spTemp)
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
else:
self.setCursorPosition(self._nwItem.cursorPos)
self.setCursorPosition(self._nwItem.cursorPos)
elif isinstance(tLine, int):
self.setCursorLine(tLine)
if CONFIG.scrollPastEnd > 0:
fSize = QFontMetrics(self.font()).lineSpacing()
docFrame = self.document().rootFrame().frameFormat()
docFrame.setBottomMargin(round(CONFIG.scrollPastEnd * fSize))
self.document().rootFrame().setFrameFormat(docFrame)
self.docFooter.updateLineCount()
qApp.processEvents()
self.document().clearUndoRedoStacks()
self.setDocumentChanged(False)
qApp.restoreOverrideCursor()
# This is a hack to fix invisible cursor on an empty document
if self.document().characterCount() <= 1:
self.setPlainText("\n")
self.setPlainText("")
self.setCursorPosition(0)
qApp.processEvents()
self.document().clearUndoRedoStacks()
self.setDocumentChanged(False)
qApp.restoreOverrideCursor()
# Update the status bar
if self._nwItem is not None:
self.statusMessage.emit(self.tr("Opened Document: {0}").format(self._nwItem.itemName))
@@ -471,29 +431,16 @@ class GuiDocEditor(QTextEdit):
self.updateDocMargins()
return
def replaceText(self, text: str) -> bool:
def replaceText(self, text: str) -> None:
"""Replace the text of the current document with the provided
text. This also clears undo history.
"""
docSize = len(text)
if docSize > nwConst.MAX_DOCSIZE:
SHARED.error(self.tr(
"The text you are trying to add is too big. "
"The text size is {0} MB. "
"The maximum size allowed is {1} MB."
).format(
f"{docSize/1.0e6:.2f}",
f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"
))
return False
qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
self.setPlainText(text)
self.updateDocMargins()
self.setDocumentChanged(True)
qApp.restoreOverrideCursor()
return True
return
def saveText(self) -> bool:
"""Save the text currently in the editor to the NWDocument
@@ -637,32 +584,16 @@ class GuiDocEditor(QTextEdit):
self.editedStatusChanged.emit(self._docChanged)
return self._docChanged
def setCursorPosition(self, position: int) -> bool:
def setCursorPosition(self, position: int) -> None:
"""Move the cursor to a given position in the document."""
if not isinstance(position, int):
return False
nChars = self.document().characterCount()
if nChars > 1:
theCursor = self.textCursor()
theCursor.setPosition(minmax(position, 0, nChars-1))
self.setTextCursor(theCursor)
# By default, the editor scrolls so the cursor is on the
# last line, so we must correct it. The user setting for
# auto-scroll is used to determine the scroll distance. This
# makes it compatible with the typewriter scrolling feature
# when it is enabled. By default, it's 30% of viewport.
vPos = self.verticalScrollBar().value()
cPos = self.cursorRect().topLeft().y()
mPos = int(CONFIG.autoScrollPos*0.01 * self.viewport().height())
if cPos > mPos:
# Only scroll if the cursor is past the auto-scroll limit
self.verticalScrollBar().setValue(max(0, vPos + cPos - mPos))
if nChars > 1 and isinstance(position, int):
cursor = self.textCursor()
cursor.setPosition(minmax(position, 0, nChars-1))
self.setTextCursor(cursor)
self.centerCursor()
self.docFooter.updateLineCount()
return True
return
def saveCursorPosition(self) -> None:
"""Save the cursor position to the current project item."""
@@ -671,19 +602,14 @@ class GuiDocEditor(QTextEdit):
self._nwItem.setCursorPos(cursPos)
return
def setCursorLine(self, line: int | None) -> bool:
def setCursorLine(self, line: int | None) -> None:
"""Move the cursor to a given line in the document."""
if not isinstance(line, int):
return False
lineIdx = line - 1 # Block index is 0 offset, lineNo is 1 offset
if lineIdx >= 0:
theBlock = self.document().findBlockByLineNumber(lineIdx)
if theBlock:
self.setCursorPosition(theBlock.position())
if isinstance(line, int) and line > 0:
block = self.document().findBlockByNumber(line - 1)
if block:
self.setCursorPosition(block.position())
logger.debug("Cursor moved to line %d", line)
return True
return
##
# Spell Checking
@@ -713,8 +639,7 @@ class GuiDocEditor(QTextEdit):
self.mainGui.mainMenu.setSpellCheck(state)
SHARED.project.data.setSpellCheck(state)
self.highLight.setSpellCheck(state)
if not self._bigDoc or state is False:
# We don't run the spell checker automatically on big docs
if state is False:
self.spellCheckDocument()
logger.debug("Spell check is set to '%s'", str(state))
@@ -730,11 +655,7 @@ class GuiDocEditor(QTextEdit):
logger.debug("Running spell checker")
start = time()
qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
if self._bigDoc:
# This is much faster for large documents
self.setPlainText(self.getText())
else:
self.highLight.rehighlight()
self.highLight.rehighlight()
qApp.restoreOverrideCursor()
logger.debug("Document highlighted in %.3f ms", 1000*(time() - start))
self.statusMessage.emit(self.tr("Spell check complete"))
@@ -990,26 +911,16 @@ class GuiDocEditor(QTextEdit):
return
if CONFIG.autoScroll:
cOld = self.cursorRect().center().y()
cPos = self.cursorRect().topLeft().y()
super().keyPressEvent(event)
kMod = event.modifiers()
okMod = kMod == Qt.NoModifier or kMod == Qt.ShiftModifier
okKey = event.key() not in self.MOVE_KEYS
if okMod and okKey:
cNew = self.cursorRect().center().y()
cMov = cNew - cOld
mPos = CONFIG.autoScrollPos*0.01 * self.viewport().height()
if abs(cMov) > 0 and cOld > mPos:
# Move the scroll bar
if cPos > mPos:
vBar = self.verticalScrollBar()
doAnim = QPropertyAnimation(vBar, b"value", self)
doAnim.setDuration(120)
doAnim.setStartValue(vBar.value())
doAnim.setEndValue(vBar.value() + cMov)
doAnim.start()
vBar.setValue(vBar.value() + 1)
else:
super().keyPressEvent(event)
@@ -1076,16 +987,6 @@ class GuiDocEditor(QTextEdit):
self._lastEdit = time()
self._lastFind = None
if self.document().characterCount() > nwConst.MAX_DOCSIZE:
SHARED.error(self.tr(
"The document has grown too big and you cannot add more text to it. "
"The maximum size of a single novelWriter document is {0} MB."
).format(
f"{nwConst.MAX_DOCSIZE/1.0e6:.2f}"
))
self.undo()
return
if not self._docChanged:
self.setDocumentChanged(removed != 0 or added != 0)
@@ -1260,8 +1161,6 @@ class GuiDocEditor(QTextEdit):
# Must not be emitted if docHandle is None!
self.docCountsChanged.emit(self._docHandle, cCount, wCount, pCount)
self._checkDocSize(self.document().characterCount())
self.docFooter.updateCounts()
return
@@ -1299,8 +1198,7 @@ class GuiDocEditor(QTextEdit):
@pyqtSlot(int, int, int)
def _updateSelCounts(self, cCount: int, wCount: int, pCount: int) -> None:
"""Slot for the word counter's finished signal
"""
"""Update the counts on the counter's finished signal."""
if self._docHandle is None or self._nwItem is None:
return
@@ -1310,25 +1208,6 @@ class GuiDocEditor(QTextEdit):
return
@pyqtSlot("QSizeF")
def _docSizeChanged(self, size: QSizeF) -> None:
"""Called whenever the underlying document layout size changes.
This is used to queue the repositioning of the cursor for very
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.document().documentLayout().hitTest(
QPointF(size.width(), size.height()), Qt.FuzzyHit
)
if self._queuePos <= thePos:
logger.debug("Allowed cursor move to %d <= %d", self._queuePos, thePos)
self.setCursorPosition(self._queuePos)
self._queuePos = None
else:
logger.debug("Denied cursor move to %d > %d", self._queuePos, thePos)
return
##
# Search & Replace
##
@@ -2021,29 +1900,6 @@ class GuiDocEditor(QTextEdit):
return False
return True
def _checkDocSize(self, size: int) -> None:
"""Check if document size crosses the big document limit set in
config. If so, we will set the big document flag to True.
"""
bigLim = round(CONFIG.bigDocLimit*1000)
newState = size > bigLim
if newState != self._bigDoc:
if newState:
logger.info(
f"The document size is {size:n} > {bigLim:n}, "
f"big doc mode has been enabled"
)
else:
logger.info(
f"The document size is {size:n} <= {bigLim:n}, "
f"big doc mode has been disabled"
)
self._bigDoc = newState
return
def _autoSelect(self) -> QTextCursor:
"""Return a cursor which may or may not have a selection based
on user settings and document action.
+3
View File
@@ -340,6 +340,7 @@ class GuiMain(QMainWindow):
def postLaunchTasks(self, cmdOpen: str | None) -> None:
"""Process tasks after the main window has been created."""
if cmdOpen:
qApp.processEvents()
logger.info("Command line path: %s", cmdOpen)
self.openProject(cmdOpen)
@@ -513,10 +514,12 @@ class GuiMain(QMainWindow):
break
if lastEdited is not None:
qApp.processEvents()
self.openDocument(lastEdited, doScroll=True)
lastViewed = SHARED.project.data.getLastHandle("viewer")
if lastViewed is not None:
qApp.processEvents()
self.viewDocument(lastViewed)
# Check if we need to rebuild the index
@@ -43,7 +43,6 @@ repsquotes = True
repdquotes = True
repdash = True
repdots = True
scrollpastend = 25
autoscroll = False
autoscrollpos = 30
fmtsquoteopen =
@@ -58,7 +57,6 @@ showtabsnspaces = False
showlineendings = False
showmultispaces = True
wordcounttimer = 5.0
bigdoclimit = 800
incnoteswcount = True
showfullpath = True
highlightquotes = True
@@ -43,7 +43,6 @@ repsquotes = True
repdquotes = True
repdash = True
repdots = True
scrollpastend = 0
autoscroll = True
autoscrollpos = 30
fmtsquoteopen =
@@ -58,7 +57,6 @@ showtabsnspaces = True
showlineendings = True
showmultispaces = True
wordcounttimer = 5.0
bigdoclimit = 500
incnoteswcount = True
showfullpath = False
highlightquotes = False
-8
View File
@@ -183,14 +183,6 @@ def testCoreToken_TextOps(monkeypatch, mockGUI, mockRnd, fncPath):
assert theToken.setText(C.hSceneDoc) is True
assert theToken._text == docText
with monkeypatch.context() as mp:
mp.setattr("novelwriter.constants.nwConst.MAX_DOCSIZE", 100)
assert theToken.setText(C.hSceneDoc, docText) is True
assert theToken._text == (
"# ERROR\n\n"
"Document 'New Scene' is too big (0.00 MB). Skipping.\n\n"
)
assert theToken.setText(C.hSceneDoc, docText) is True
assert theToken._text == docText
@@ -156,12 +156,6 @@ def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, tstPaths):
qtbot.mouseClick(tabEditor.autoScroll, Qt.LeftButton)
assert tabEditor.autoScroll.isChecked()
qtbot.wait(KEY_DELAY)
tabEditor.scrollPastEnd.setValue(0)
qtbot.wait(KEY_DELAY)
tabEditor.bigDocLimit.setValue(500)
# Syntax Settings
qtbot.wait(KEY_DELAY)
tabSyntax = nwPrefs.tabSyntax
+176 -197
View File
@@ -44,7 +44,7 @@ def testGuiEditor_Init(qtbot, nwGUI, projPath, ipsumText, mockRnd):
buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc)
nwGUI.docEditor.setText("### Lorem Ipsum\n\n%s" % ipsumText[0])
nwGUI.docEditor.setPlainText("### Lorem Ipsum\n\n%s" % ipsumText[0])
assert nwGUI.saveDocument()
# Check Defaults
@@ -96,26 +96,8 @@ def testGuiEditor_LoadText(qtbot, monkeypatch, caplog, nwGUI, projPath, ipsumTex
# Invalid handle
assert nwGUI.docEditor.loadText("abcdefghijklm") is False
# Document too big
with monkeypatch.context() as mp:
mp.setattr("novelwriter.constants.nwConst.MAX_DOCSIZE", 100)
assert nwGUI.docEditor.loadText(C.hSceneDoc) is False
assert "The document you are trying to open is too big." in caplog.text
# Regular open
assert nwGUI.docEditor.loadText(C.hSceneDoc) is True
assert nwGUI.docEditor._bigDoc is False
# Reload too big text
with monkeypatch.context() as mp:
mp.setattr("novelwriter.constants.nwConst.MAX_DOCSIZE", 100)
assert nwGUI.docEditor.replaceText(longText) is False
assert "The document you are trying to open is too big." in caplog.text
# Big doc handling
CONFIG.bigDocLimit = 50
assert nwGUI.docEditor.loadText(C.hSceneDoc) is True
assert nwGUI.docEditor._bigDoc is True
# Regular open, with line number (1 indexed)
assert nwGUI.docEditor.loadText(C.hSceneDoc, tLine=4) is True
@@ -190,7 +172,7 @@ def testGuiEditor_MetaData(qtbot, nwGUI, projPath, mockRnd):
"Some\u2028text.\u2029"
"More\u00a0text.\u2029"
)
assert nwGUI.docEditor.replaceText(newText)
nwGUI.docEditor.replaceText(newText)
assert nwGUI.docEditor.getText() == "### New Scene\n\nSome\ntext.\nMore\u00a0text.\n"
# Check Propertoes
@@ -200,15 +182,15 @@ def testGuiEditor_MetaData(qtbot, nwGUI, projPath, mockRnd):
assert nwGUI.docEditor.isEmpty is False
# Cursor Position
assert nwGUI.docEditor.setCursorPosition(None) is False
assert nwGUI.docEditor.setCursorPosition(10) is True
nwGUI.docEditor.setCursorPosition(10)
assert nwGUI.docEditor.getCursorPosition() == 10
assert SHARED.project.tree[C.hSceneDoc].cursorPos != 10
nwGUI.docEditor.saveCursorPosition()
assert SHARED.project.tree[C.hSceneDoc].cursorPos == 10
assert nwGUI.docEditor.setCursorLine(None) is False
assert nwGUI.docEditor.setCursorLine(3) is True
nwGUI.docEditor.setCursorLine(None)
assert nwGUI.docEditor.getCursorPosition() == 10
nwGUI.docEditor.setCursorLine(3)
assert nwGUI.docEditor.getCursorPosition() == 15
# Document Changed Signal
@@ -233,7 +215,7 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
assert nwGUI.openDocument(C.hSceneDoc) is True
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText)
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
theDoc = nwGUI.docEditor.document()
@@ -250,15 +232,15 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
theCursor.clearSelection()
# Select Paragraph
assert nwGUI.docEditor.setCursorPosition(1000) is True
nwGUI.docEditor.setCursorPosition(1000)
assert nwGUI.docEditor.getCursorPosition() == 1000
assert nwGUI.docEditor.docAction(nwDocAction.SEL_PARA) is True
theCursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == ipsumText[1]
# Cut Selected Text
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(1000) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(1000)
assert nwGUI.docEditor.docAction(nwDocAction.SEL_PARA) is True
assert nwGUI.docEditor.docAction(nwDocAction.CUT) is True
@@ -275,13 +257,13 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
assert nwGUI.docEditor.getText() == theText
# Copy Next Paragraph
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(1500) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(1500)
assert nwGUI.docEditor.docAction(nwDocAction.SEL_PARA) is True
assert nwGUI.docEditor.docAction(nwDocAction.COPY) is True
# Paste at End
assert nwGUI.docEditor.setCursorPosition(theDoc.characterCount()) is True
nwGUI.docEditor.setCursorPosition(theDoc.characterCount())
theCursor = nwGUI.docEditor.textCursor()
theCursor.insertBlock()
theCursor.insertBlock()
@@ -298,24 +280,24 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
# ==================
theText = "### A Scene\n\n%s" % ipsumText[0]
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
# Emphasis
assert nwGUI.docEditor.setCursorPosition(50) is True
nwGUI.docEditor.setCursorPosition(50)
assert nwGUI.docEditor.docAction(nwDocAction.EMPH) is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "_consectetur_")
assert nwGUI.docEditor.docAction(nwDocAction.UNDO) is True
assert nwGUI.docEditor.getText() == theText
# Strong
assert nwGUI.docEditor.setCursorPosition(50) is True
nwGUI.docEditor.setCursorPosition(50)
assert nwGUI.docEditor.docAction(nwDocAction.STRONG) is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "**consectetur**")
assert nwGUI.docEditor.docAction(nwDocAction.UNDO) is True
assert nwGUI.docEditor.getText() == theText
# Strikeout
assert nwGUI.docEditor.setCursorPosition(50) is True
nwGUI.docEditor.setCursorPosition(50)
assert nwGUI.docEditor.docAction(nwDocAction.STRIKE) is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "~~consectetur~~")
assert nwGUI.docEditor.docAction(nwDocAction.UNDO) is True
@@ -331,17 +313,17 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
# ======
theText = "### A Scene\n\n%s" % ipsumText[0]
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
# Add Single Quotes
assert nwGUI.docEditor.setCursorPosition(50) is True
nwGUI.docEditor.setCursorPosition(50)
assert nwGUI.docEditor.docAction(nwDocAction.S_QUOTE) is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "\u2018consectetur\u2019")
assert nwGUI.docEditor.docAction(nwDocAction.UNDO) is True
assert nwGUI.docEditor.getText() == theText
# Add Double Quotes
assert nwGUI.docEditor.setCursorPosition(50) is True
nwGUI.docEditor.setCursorPosition(50)
assert nwGUI.docEditor.docAction(nwDocAction.D_QUOTE) is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "\u201cconsectetur\u201d")
assert nwGUI.docEditor.docAction(nwDocAction.UNDO) is True
@@ -349,14 +331,14 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
# Replace Single Quotes
repText = theText.replace("consectetur", "'consectetur'")
assert nwGUI.docEditor.replaceText(repText) is True
nwGUI.docEditor.replaceText(repText)
assert nwGUI.docEditor.docAction(nwDocAction.SEL_ALL) is True
assert nwGUI.docEditor.docAction(nwDocAction.REPL_SNG) is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "\u2018consectetur\u2019")
# Replace Double Quotes
repText = theText.replace("consectetur", "\"consectetur\"")
assert nwGUI.docEditor.replaceText(repText) is True
nwGUI.docEditor.replaceText(repText)
assert nwGUI.docEditor.docAction(nwDocAction.SEL_ALL) is True
assert nwGUI.docEditor.docAction(nwDocAction.REPL_DBL) is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "\u201cconsectetur\u201d")
@@ -366,7 +348,7 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
theText = "### A Scene\n\n%s" % ipsumText[0]
repText = theText[:100] + theText[100:].replace(" ", "\n", 3)
assert nwGUI.docEditor.replaceText(repText) is True
nwGUI.docEditor.replaceText(repText)
assert nwGUI.docEditor.docAction(nwDocAction.RM_BREAKS) is True
assert nwGUI.docEditor.getText().strip() == theText.strip()
@@ -374,65 +356,65 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
# ============
theText = "## Scene Title\n\nScene text.\n\n"
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
# Header 1
assert nwGUI.docEditor.setCursorPosition(0) is True
nwGUI.docEditor.setCursorPosition(0)
assert nwGUI.docEditor.docAction(nwDocAction.BLOCK_H1) is True
assert nwGUI.docEditor.getText() == "# Scene Title\n\nScene text.\n\n"
# Header 2
assert nwGUI.docEditor.setCursorPosition(0) is True
nwGUI.docEditor.setCursorPosition(0)
assert nwGUI.docEditor.docAction(nwDocAction.BLOCK_H2) is True
assert nwGUI.docEditor.getText() == "## Scene Title\n\nScene text.\n\n"
# Header 3
assert nwGUI.docEditor.setCursorPosition(0) is True
nwGUI.docEditor.setCursorPosition(0)
assert nwGUI.docEditor.docAction(nwDocAction.BLOCK_H3) is True
assert nwGUI.docEditor.getText() == "### Scene Title\n\nScene text.\n\n"
# Header 4
assert nwGUI.docEditor.setCursorPosition(0) is True
nwGUI.docEditor.setCursorPosition(0)
assert nwGUI.docEditor.docAction(nwDocAction.BLOCK_H4) is True
assert nwGUI.docEditor.getText() == "#### Scene Title\n\nScene text.\n\n"
# Comment
assert nwGUI.docEditor.setCursorPosition(20) is True
nwGUI.docEditor.setCursorPosition(20)
assert nwGUI.docEditor.docAction(nwDocAction.BLOCK_COM) is True
assert nwGUI.docEditor.getText() == "#### Scene Title\n\n% Scene text.\n\n"
# Text
assert nwGUI.docEditor.setCursorPosition(20) is True
nwGUI.docEditor.setCursorPosition(20)
assert nwGUI.docEditor.docAction(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "#### Scene Title\n\nScene text.\n\n"
# Align Left
assert nwGUI.docEditor.setCursorPosition(20) is True
nwGUI.docEditor.setCursorPosition(20)
assert nwGUI.docEditor.docAction(nwDocAction.ALIGN_L) is True
assert nwGUI.docEditor.getText() == "#### Scene Title\n\nScene text. <<\n\n"
# Align Right
assert nwGUI.docEditor.setCursorPosition(20) is True
nwGUI.docEditor.setCursorPosition(20)
assert nwGUI.docEditor.docAction(nwDocAction.ALIGN_R) is True
assert nwGUI.docEditor.getText() == "#### Scene Title\n\n>> Scene text.\n\n"
# Align Centre
assert nwGUI.docEditor.setCursorPosition(20) is True
nwGUI.docEditor.setCursorPosition(20)
assert nwGUI.docEditor.docAction(nwDocAction.ALIGN_C) is True
assert nwGUI.docEditor.getText() == "#### Scene Title\n\n>> Scene text. <<\n\n"
# Indent Left
assert nwGUI.docEditor.setCursorPosition(20) is True
nwGUI.docEditor.setCursorPosition(20)
assert nwGUI.docEditor.docAction(nwDocAction.INDENT_L) is True
assert nwGUI.docEditor.getText() == "#### Scene Title\n\n> Scene text.\n\n"
# Indent Right
assert nwGUI.docEditor.setCursorPosition(20) is True
nwGUI.docEditor.setCursorPosition(20)
assert nwGUI.docEditor.docAction(nwDocAction.INDENT_R) is True
assert nwGUI.docEditor.getText() == "#### Scene Title\n\n> Scene text. <\n\n"
# Text (Reset)
assert nwGUI.docEditor.setCursorPosition(20) is True
nwGUI.docEditor.setCursorPosition(20)
assert nwGUI.docEditor.docAction(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "#### Scene Title\n\nScene text.\n\n"
@@ -462,38 +444,38 @@ def testGuiEditor_Insert(qtbot, monkeypatch, nwGUI, projPath, ipsumText, mockRnd
assert nwGUI.openDocument(C.hSceneDoc) is True
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText)
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
# Insert Text
# ===========
theText = "### A Scene\n\n%s" % ipsumText[0]
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
# No Document Handle
nwGUI.docEditor._docHandle = None
assert nwGUI.docEditor.setCursorPosition(24) is True
nwGUI.docEditor.setCursorPosition(24)
assert nwGUI.docEditor.insertText("Stuff") is False
nwGUI.docEditor._docHandle = C.hSceneDoc
# Insert String
assert nwGUI.docEditor.setCursorPosition(24) is True
nwGUI.docEditor.setCursorPosition(24)
assert nwGUI.docEditor.insertText(", ipsumer,") is True
assert nwGUI.docEditor.getText() == theText[:24] + ", ipsumer," + theText[24:]
# Single Quotes
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(41) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(41)
assert nwGUI.docEditor.insertText(nwDocInsert.QUOTE_LS) is True
assert nwGUI.docEditor.setCursorPosition(53) is True
nwGUI.docEditor.setCursorPosition(53)
assert nwGUI.docEditor.insertText(nwDocInsert.QUOTE_RS) is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "\u2018consectetur\u2019")
# Double Quotes
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(41) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(41)
assert nwGUI.docEditor.insertText(nwDocInsert.QUOTE_LD) is True
assert nwGUI.docEditor.setCursorPosition(53) is True
nwGUI.docEditor.setCursorPosition(53)
assert nwGUI.docEditor.insertText(nwDocInsert.QUOTE_RD) is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "\u201cconsectetur\u201d")
@@ -505,8 +487,8 @@ def testGuiEditor_Insert(qtbot, monkeypatch, nwGUI, projPath, ipsumText, mockRnd
# ===============
theText = "### A Scene\n\n\n%s" % ipsumText[0]
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorLine(3)
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorLine(3)
# Invalid Keyword
assert nwGUI.docEditor.insertKeyWord("stuff") is False
@@ -525,7 +507,7 @@ def testGuiEditor_Insert(qtbot, monkeypatch, nwGUI, projPath, ipsumText, mockRnd
assert nwGUI.docEditor.insertKeyWord(nwKeyWords.POV_KEY) is False
# Insert In-Block
assert nwGUI.docEditor.setCursorPosition(20) is True
nwGUI.docEditor.setCursorPosition(20)
assert nwGUI.docEditor.insertKeyWord(nwKeyWords.CHAR_KEY) is True
assert nwGUI.docEditor.insertText("John")
assert nwGUI.docEditor.getText() == theText.replace(
@@ -544,23 +526,23 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
assert nwGUI.openDocument(C.hSceneDoc) is True
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText)
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
# Clear Surrounding
# =================
# No Selection
theText = "### A Scene\n\n%s" % ipsumText[0]
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
theCursor = nwGUI.docEditor.textCursor()
assert nwGUI.docEditor._clearSurrounding(theCursor, 1) is False
# Clear Characters, 1 Layer
repText = theText.replace("consectetur", "=consectetur=")
assert nwGUI.docEditor.replaceText(repText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(repText)
nwGUI.docEditor.setCursorPosition(45)
theCursor = nwGUI.docEditor.textCursor()
theCursor.select(QTextCursor.WordUnderCursor)
@@ -569,8 +551,8 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
# Clear Characters, 2 Layers
repText = theText.replace("consectetur", "==consectetur==")
assert nwGUI.docEditor.replaceText(repText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(repText)
nwGUI.docEditor.setCursorPosition(45)
theCursor = nwGUI.docEditor.textCursor()
theCursor.select(QTextCursor.WordUnderCursor)
@@ -581,8 +563,8 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
# ==============
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText[0:2])
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
# No Selection
with monkeypatch.context() as mp:
@@ -590,19 +572,19 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
assert nwGUI.docEditor._wrapSelection("=", "=") is False
# Wrap Equal
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._wrapSelection("=") is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "=consectetur=")
# Wrap Unequal
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._wrapSelection("=", "*") is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "=consectetur*")
# Past Paragraph
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
theCursor = nwGUI.docEditor.textCursor()
theCursor.setPosition(13, QTextCursor.MoveAnchor)
theCursor.setPosition(1000, QTextCursor.KeepAnchor)
@@ -618,8 +600,8 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
# =============
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText[0:2])
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
# No Selection
with monkeypatch.context() as mp:
@@ -627,13 +609,13 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
assert nwGUI.docEditor._toggleFormat(2, "=") is False
# Wrap Single Equal
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(1, "=") is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "=consectetur=")
# Past Paragraph
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
theCursor = nwGUI.docEditor.textCursor()
theCursor.setPosition(13, QTextCursor.MoveAnchor)
theCursor.setPosition(1000, QTextCursor.KeepAnchor)
@@ -646,29 +628,29 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
assert newPara[2] == ipsumText[1]
# Wrap Double Equal
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(2, "=") is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "==consectetur==")
# Toggle Double Equal
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(2, "=") is True
assert nwGUI.docEditor._toggleFormat(2, "=") is True
assert nwGUI.docEditor.getText() == theText
# Toggle Triple+Double Equal
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(3, "=") is True
assert nwGUI.docEditor._toggleFormat(2, "=") is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "=consectetur=")
# Toggle Unequal
repText = theText.replace("consectetur", "=consectetur==")
assert nwGUI.docEditor.replaceText(repText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(repText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(1, "=") is True
assert nwGUI.docEditor.getText() == theText.replace("consectetur", "consectetur=")
assert nwGUI.docEditor._toggleFormat(1, "=") is True
@@ -679,15 +661,15 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
# No Selection
theText = "### A Scene\n\n%s" % ipsumText[0].replace("consectetur", "=consectetur=")
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._replaceQuotes("=", "<", ">") is False
# First Paragraph Selected
# This should not replace anything in second paragraph
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText[0:2]).replace("ipsum", "=ipsum=")
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor.docAction(nwDocAction.SEL_PARA)
assert nwGUI.docEditor._replaceQuotes("=", "<", ">") is True
@@ -698,8 +680,8 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
# Edge of Document
theText = ipsumText[0].replace("Lorem", "=Lorem=")
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor.docAction(nwDocAction.SEL_ALL)
assert nwGUI.docEditor._replaceQuotes("=", "<", ">") is True
assert nwGUI.docEditor.getText() == theText.replace("=Lorem=", "<Lorem>")
@@ -712,15 +694,15 @@ def testGuiEditor_TextManipulation(qtbot, monkeypatch, nwGUI, projPath, ipsumTex
# Remove All
theText = "### A Scene\n\n%s\n\n%s" % (parOne, parTwo)
assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorPosition(45) is True
nwGUI.docEditor.replaceText(theText)
nwGUI.docEditor.setCursorPosition(45)
nwGUI.docEditor._removeInParLineBreaks()
assert nwGUI.docEditor.getText() == "### A Scene\n\n%s\n" % "\n\n".join(ipsumText[0:2])
# Remove First Paragraph
# Second paragraphs should remain unchanged
theText = "### A Scene\n\n%s\n\n%s" % (parOne, parTwo)
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
theCursor = nwGUI.docEditor.textCursor()
theCursor.setPosition(16, QTextCursor.MoveAnchor)
theCursor.setPosition(680, QTextCursor.KeepAnchor)
@@ -749,123 +731,120 @@ def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, projPath, ipsumText
buildTestProject(nwGUI, projPath)
assert nwGUI.openDocument(C.hSceneDoc) is True
theText = "### A Scene\n\n%s" % "\n\n".join(ipsumText)
assert nwGUI.docEditor.replaceText(theText) is True
# Invalid and Generic
# ===================
theText = "### A Scene\n\n%s" % ipsumText[0]
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
# Invalid Block
assert nwGUI.docEditor.setCursorPosition(0) is True
nwGUI.docEditor.setCursorPosition(0)
with monkeypatch.context() as mp:
mp.setattr(QTextBlock, "isValid", lambda *a, **k: False)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is False
# Keyword
assert nwGUI.docEditor.replaceText("@pov: Jane\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("@pov: Jane\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is False
assert nwGUI.docEditor.getText() == "@pov: Jane\n\n"
assert nwGUI.docEditor.getCursorPosition() == 5
# Unsupported Format
assert nwGUI.docEditor.replaceText("% Comment\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("% Comment\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.NO_ACTION) is False
# Block Stripping : Left Side
# ===========================
# Strip Comment w/Space
assert nwGUI.docEditor.replaceText("% Comment\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("% Comment\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Comment\n\n"
assert nwGUI.docEditor.getCursorPosition() == 3
# Strip Comment wo/Space
assert nwGUI.docEditor.replaceText("%Comment\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("%Comment\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Comment\n\n"
assert nwGUI.docEditor.getCursorPosition() == 4
# Strip Header 1
assert nwGUI.docEditor.replaceText("# Title\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("# Title\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Title\n\n"
assert nwGUI.docEditor.getCursorPosition() == 3
# Strip Header 2
assert nwGUI.docEditor.replaceText("## Title\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("## Title\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Title\n\n"
assert nwGUI.docEditor.getCursorPosition() == 2
# Strip Header 3
assert nwGUI.docEditor.replaceText("### Title\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("### Title\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Title\n\n"
assert nwGUI.docEditor.getCursorPosition() == 1
# Strip Header 4
assert nwGUI.docEditor.replaceText("#### Title\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("#### Title\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Title\n\n"
assert nwGUI.docEditor.getCursorPosition() == 0
# Strip Novel Title
assert nwGUI.docEditor.replaceText("#! Title\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("#! Title\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Title\n\n"
assert nwGUI.docEditor.getCursorPosition() == 2
# Strip Unnumbered CHapter
assert nwGUI.docEditor.replaceText("##! Title\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("##! Title\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Title\n\n"
assert nwGUI.docEditor.getCursorPosition() == 1
# Strip Text
assert nwGUI.docEditor.replaceText("Generic text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Generic text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Generic text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 5
# Strip Left Angle Brackets : Double w/Space
assert nwGUI.docEditor.replaceText(">> Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText(">> Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 2
# Strip Left Angle Brackets : Single w/Space
assert nwGUI.docEditor.replaceText("> Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("> Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 3
# Strip Left Angle Brackets : Double wo/Space
assert nwGUI.docEditor.replaceText(">>Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText(">>Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 3
# Strip Left Angle Brackets : Single wo/Space
assert nwGUI.docEditor.replaceText(">Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText(">Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 4
@@ -874,29 +853,29 @@ def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, projPath, ipsumText
# ============================
# Strip Right Angle Brackets : Double w/Space
assert nwGUI.docEditor.replaceText("Some text <<\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text <<\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 5
# Strip Right Angle Brackets : Single w/Space
assert nwGUI.docEditor.replaceText("Some text <\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text <\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 5
# Strip Right Angle Brackets : Double wo/Space
assert nwGUI.docEditor.replaceText("Some text<<\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text<<\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 5
# Strip Right Angle Brackets : Single wo/Space
assert nwGUI.docEditor.replaceText("Some text<\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text<\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 5
@@ -904,15 +883,15 @@ def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, projPath, ipsumText
# Block Stripping : Both Sides
# ============================
assert nwGUI.docEditor.replaceText(">> Some text <<\n\n") is True
nwGUI.docEditor.replaceText(">> Some text <<\n\n")
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.replaceText(">Some text <<\n\n") is True
nwGUI.docEditor.replaceText(">Some text <<\n\n")
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.replaceText(">Some text<\n\n") is True
nwGUI.docEditor.replaceText(">Some text<\n\n")
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
@@ -920,114 +899,114 @@ def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, projPath, ipsumText
# ===========
# Comment
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_COM) is True
assert nwGUI.docEditor.getText() == "% Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 7
# Toggle Comment w/Space
assert nwGUI.docEditor.replaceText("% Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("% Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_COM) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 3
# Toggle Comment wo/Space
assert nwGUI.docEditor.replaceText("%Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("%Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_COM) is True
assert nwGUI.docEditor.getText() == "Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 4
# Header 1
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_H1) is True
assert nwGUI.docEditor.getText() == "# Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 7
# Header 2
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_H2) is True
assert nwGUI.docEditor.getText() == "## Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 8
# Header 3
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_H3) is True
assert nwGUI.docEditor.getText() == "### Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 9
# Header 4
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_H4) is True
assert nwGUI.docEditor.getText() == "#### Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 10
# Novel Title
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TTL) is True
assert nwGUI.docEditor.getText() == "#! Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 8
# Unnumbered Chapter
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_UNN) is True
assert nwGUI.docEditor.getText() == "##! Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 9
# Left Indent
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.INDENT_L) is True
assert nwGUI.docEditor.getText() == "> Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 7
# Right Indent
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.INDENT_R) is True
assert nwGUI.docEditor.getText() == "Some text <\n\n"
assert nwGUI.docEditor.getCursorPosition() == 5
# Right/Left Indent
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.INDENT_L) is True
assert nwGUI.docEditor._formatBlock(nwDocAction.INDENT_R) is True
assert nwGUI.docEditor.getText() == "> Some text <\n\n"
assert nwGUI.docEditor.getCursorPosition() == 7
# Left Align
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.ALIGN_L) is True
assert nwGUI.docEditor.getText() == "Some text <<\n\n"
assert nwGUI.docEditor.getCursorPosition() == 5
# Right Align
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.ALIGN_R) is True
assert nwGUI.docEditor.getText() == ">> Some text\n\n"
assert nwGUI.docEditor.getCursorPosition() == 8
# Centre Align
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.ALIGN_C) is True
assert nwGUI.docEditor.getText() == ">> Some text <<\n\n"
assert nwGUI.docEditor.getCursorPosition() == 8
# Left/Right Align (Overrides)
assert nwGUI.docEditor.replaceText("Some text\n\n") is True
assert nwGUI.docEditor.setCursorPosition(5) is True
nwGUI.docEditor.replaceText("Some text\n\n")
nwGUI.docEditor.setCursorPosition(5)
assert nwGUI.docEditor._formatBlock(nwDocAction.ALIGN_L) is True
assert nwGUI.docEditor._formatBlock(nwDocAction.ALIGN_R) is True
assert nwGUI.docEditor.getText() == ">> Some text\n\n"
@@ -1037,16 +1016,16 @@ def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, projPath, ipsumText
# ============
# Final Cursor Position Out of Range
assert nwGUI.docEditor.replaceText("#### Title\n\n") is True
assert nwGUI.docEditor.setCursorPosition(3) is True
nwGUI.docEditor.replaceText("#### Title\n\n")
nwGUI.docEditor.setCursorPosition(3)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT) is True
assert nwGUI.docEditor.getText() == "Title\n\n"
assert nwGUI.docEditor.getCursorPosition() == 5
# Third Line
# This also needs to add a new block
assert nwGUI.docEditor.replaceText("#### Title\n\nThe Text\n\n") is True
assert nwGUI.docEditor.setCursorLine(3) is True
nwGUI.docEditor.replaceText("#### Title\n\nThe Text\n\n")
nwGUI.docEditor.setCursorLine(3)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_COM) is True
assert nwGUI.docEditor.getText() == "#### Title\n\n% The Text\n\n"
@@ -1063,13 +1042,13 @@ def testGuiEditor_Tags(qtbot, nwGUI, projPath, ipsumText, mockRnd):
# Create Scene
theText = "### A Scene\n\n@char: Jane, John\n\n" + ipsumText[0] + "\n\n"
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
# Create Character
theText = "### Jane Doe\n\n@tag: Jane\n\n" + ipsumText[1] + "\n\n"
cHandle = SHARED.project.newFile("Jane Doe", C.hCharRoot)
assert nwGUI.openDocument(cHandle) is True
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
assert nwGUI.saveDocument() is True
assert nwGUI.projView.projTree.revealNewTreeItem(cHandle)
nwGUI.docEditor.updateTagHighLighting()
@@ -1079,29 +1058,29 @@ def testGuiEditor_Tags(qtbot, nwGUI, projPath, ipsumText, mockRnd):
assert nwGUI.openDocument(C.hSceneDoc) is True
# Empty Block
assert nwGUI.docEditor.setCursorLine(2) is True
nwGUI.docEditor.setCursorLine(2)
assert nwGUI.docEditor._followTag() is False
# Not On Tag
assert nwGUI.docEditor.setCursorLine(1) is True
nwGUI.docEditor.setCursorLine(1)
assert nwGUI.docEditor._followTag() is False
# On Tag Keyword
assert nwGUI.docEditor.setCursorPosition(15) is True
nwGUI.docEditor.setCursorPosition(15)
assert nwGUI.docEditor._followTag() is False
# On Unknown Tag
assert nwGUI.docEditor.setCursorPosition(28) is True
nwGUI.docEditor.setCursorPosition(28)
assert nwGUI.docEditor._followTag() is True
assert nwGUI.docViewer._docHandle is None
# On Known Tag, No Follow
assert nwGUI.docEditor.setCursorPosition(22) is True
nwGUI.docEditor.setCursorPosition(22)
assert nwGUI.docEditor._followTag(loadTag=False) is True
assert nwGUI.docViewer._docHandle is None
# On Known Tag, Follow
assert nwGUI.docEditor.setCursorPosition(22) is True
nwGUI.docEditor.setCursorPosition(22)
assert nwGUI.docViewer._docHandle is None
assert nwGUI.docEditor._followTag(loadTag=True) is True
assert nwGUI.docViewer._docHandle == cHandle
@@ -1151,7 +1130,7 @@ def testGuiEditor_WordCounters(qtbot, monkeypatch, nwGUI, projPath, ipsumText, m
theText = "\n\n".join(ipsumText)
cC, wC, pC = countWords(theText)
assert nwGUI.docEditor.replaceText(theText) is True
nwGUI.docEditor.replaceText(theText)
# Check that a busy counter is blocked
with monkeypatch.context() as mp:
@@ -1234,7 +1213,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, prjLipsum):
# Close search
nwGUI.docEditor.docSearch.cancelSearch.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.isVisible() is False
assert nwGUI.docEditor.setCursorPosition(15)
nwGUI.docEditor.setCursorPosition(15)
# Toggle search again with header button
qtbot.mouseClick(nwGUI.docEditor.docHeader.searchButton, Qt.LeftButton, delay=KEY_DELAY)
@@ -1304,7 +1283,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, prjLipsum):
assert nwGUI.docEditor.docSearch.doMatchCap is True
# Replace "Sus" with "Foo" via menu
assert nwGUI.docEditor.setCursorPosition(590)
nwGUI.docEditor.setCursorPosition(590)
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
nwGUI.mainMenu.aReplaceNext.activate(QAction.Trigger)
assert nwGUI.docEditor.getText()[608:619] == "Foopendisse"
@@ -1333,7 +1312,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, prjLipsum):
# Close search and select "est" again
nwGUI.docEditor.docSearch.cancelSearch.activate(QAction.Trigger)
assert nwGUI.docEditor.setCursorPosition(630)
nwGUI.docEditor.setCursorPosition(630)
nwGUI.docEditor._makeSelection(QTextCursor.WordUnderCursor)
theCursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == "est"
+31 -32
View File
@@ -46,8 +46,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
# Split By Chapter
assert nwGUI.openDocument("4c4f28287af27") is True
assert nwGUI.docEditor.setCursorPosition(42) is True
nwGUI.docEditor.setCursorPosition(42)
cleanText = nwGUI.docEditor.getText()[39:86]
# Bold
@@ -95,7 +94,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
# Block Formats
# =============
# cSpell:ignore Pellentesque erat nulla posuere commodo
assert nwGUI.docEditor.setCursorPosition(42)
nwGUI.docEditor.setCursorPosition(42)
# Header 1
nwGUI.mainMenu.aFmtHead1.activate(QAction.Trigger)
@@ -141,7 +140,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
assert nwGUI.docEditor.getText()[39:86] == cleanText
# Check comment with no space before text
assert nwGUI.docEditor.setCursorPosition(39)
nwGUI.docEditor.setCursorPosition(39)
assert nwGUI.docEditor.insertText("%")
fmtStr = "%Pellentesque nec erat ut nulla posuere commodo."
assert nwGUI.docEditor.getText()[39:87] == fmtStr
@@ -157,7 +156,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
assert nwGUI.docEditor.getText()[39:86] == cleanText
# Cut, Copy and Paste
assert nwGUI.docEditor.setCursorPosition(39)
nwGUI.docEditor.setCursorPosition(39)
nwGUI.docEditor._makeSelection(QTextCursor.WordUnderCursor)
nwGUI.mainMenu.aEditCut.activate(QAction.Trigger)
@@ -170,7 +169,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
"Pellentesque nec erat ut nulla posuere commodo. Cu"
)
assert nwGUI.docEditor.setCursorPosition(39)
nwGUI.docEditor.setCursorPosition(39)
nwGUI.docEditor._makeSelection(QTextCursor.WordUnderCursor)
nwGUI.mainMenu.aEditCopy.activate(QAction.Trigger)
@@ -178,7 +177,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
"Pellentesque nec erat ut nulla posuere commodo. Cu"
)
assert nwGUI.docEditor.setCursorPosition(39)
nwGUI.docEditor.setCursorPosition(39)
nwGUI.mainMenu.aEditPaste.activate(QAction.Trigger)
assert nwGUI.docEditor.getText()[39:89] == (
"PellentesquePellentesque nec erat ut nulla posuere"
@@ -186,7 +185,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
nwGUI.mainMenu.aEditUndo.activate(QAction.Trigger)
# Select Paragraph/All
assert nwGUI.docEditor.setCursorPosition(42)
nwGUI.docEditor.setCursorPosition(42)
nwGUI.mainMenu.aSelectPar.activate(QAction.Trigger)
theCursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == (
@@ -199,7 +198,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
"nunc lacus, imperdiet nec posuere ac, interdum non lectus."
)
assert nwGUI.docEditor.setCursorPosition(42)
nwGUI.docEditor.setCursorPosition(42)
nwGUI.mainMenu.aSelectAll.activate(QAction.Trigger)
theCursor = nwGUI.docEditor.textCursor()
assert len(theCursor.selectedText()) == 1895
@@ -212,8 +211,8 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
# ==================
cleanText = "A single, short paragraph.\n\n"
nwGUI.docEditor.setText(cleanText)
assert nwGUI.docEditor.setCursorPosition(0)
nwGUI.docEditor.setPlainText(cleanText)
nwGUI.docEditor.setCursorPosition(0)
# Left Align
nwGUI.mainMenu.aFmtAlignLeft.activate(QAction.Trigger)
@@ -247,7 +246,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
# Other Checks
# Replace Quotes
nwGUI.docEditor.setText((
nwGUI.docEditor.setPlainText((
"### New Text\n\n"
"Text with 'single' quotes and 'tricky stuff's'.\n\n"
"Also text with \"double\" quotes which are \"less tricky\".\n\n"
@@ -270,7 +269,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
)
# Remove in-paragraph line breaks
nwGUI.docEditor.setText((
nwGUI.docEditor.setPlainText((
"### New Text\n\n"
"@char: Someone\n"
"@location: Somewhere\n\n"
@@ -288,7 +287,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
"With another paragraph here.\n"
)
nwGUI.docEditor.setText((
nwGUI.docEditor.setPlainText((
"### New Text\n\n"
"@char: Someone\n"
"@location: Somewhere\n\n"
@@ -314,7 +313,7 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
assert not nwGUI.docEditor.docAction(nwDocAction.NO_ACTION)
# Test Invalid Formats
nwGUI.docEditor.setText((
nwGUI.docEditor.setPlainText((
"### New Text\n\n"
"@tag: Bod\n\n"
"Text with 'single' quotes and 'tricky stuff's'.\n\n"
@@ -322,11 +321,11 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
))
# Cannot Format Tag
assert nwGUI.docEditor.setCursorPosition(17)
nwGUI.docEditor.setCursorPosition(17)
assert not nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_TXT)
# Invalid Action
assert nwGUI.docEditor.setCursorPosition(30)
nwGUI.docEditor.setCursorPosition(30)
assert not nwGUI.docEditor._formatBlock(nwDocAction.NO_ACTION)
# Ensure No Changes
@@ -541,43 +540,43 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
# Insert Keywords
# ===============
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.TAG_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.TAG_KEY
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.POV_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.POV_KEY
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.FOCUS_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.FOCUS_KEY
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.CHAR_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.CHAR_KEY
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.PLOT_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.PLOT_KEY
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.TIME_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.TIME_KEY
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.WORLD_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.WORLD_KEY
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.OBJECT_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.OBJECT_KEY
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.ENTITY_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.ENTITY_KEY
nwGUI.docEditor.setText("Stuff")
nwGUI.docEditor.setPlainText("Stuff")
nwGUI.mainMenu.mInsKWItems[nwKeyWords.CUSTOM_KEY][0].activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n%s: " % nwKeyWords.CUSTOM_KEY
@@ -592,22 +591,22 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
# Insert Special Comments
# =======================
nwGUI.docEditor.setText("Stuff\n")
nwGUI.docEditor.setPlainText("Stuff\n")
nwGUI.mainMenu.aInsSynopsis.activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "Stuff\n% Synopsis: \n"
# Insert Break or Space
# =====================
nwGUI.docEditor.setText("### Stuff\n")
nwGUI.docEditor.setPlainText("### Stuff\n")
nwGUI.mainMenu.aInsNewPage.activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "[NEW PAGE]\n### Stuff\n"
nwGUI.docEditor.setText("### Stuff\n")
nwGUI.docEditor.setPlainText("### Stuff\n")
nwGUI.mainMenu.aInsVSpaceS.activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "[VSPACE]\n### Stuff\n"
nwGUI.docEditor.setText("### Stuff\n")
nwGUI.docEditor.setPlainText("### Stuff\n")
nwGUI.mainMenu.aInsVSpaceM.activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == "[VSPACE:2]\n### Stuff\n"
@@ -637,7 +636,7 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
# Open the document from before, and add some text to it
nwGUI.openDocument(C.hSceneDoc)
nwGUI.docEditor.setText("Bar")
nwGUI.docEditor.setPlainText("Bar")
assert nwGUI.docEditor.getText() == "Bar"
# The document isn't empty, so the message box should pop