Simplify editor scrolling features

This commit is contained in:
Veronica Berglyd Olsen
2023-09-06 20:05:13 +02:00
parent 0bfa3cb592
commit 0ef46ef0ea
7 changed files with 28 additions and 72 deletions
-3
View File
@@ -144,7 +144,6 @@ class Config:
self.doReplaceDash = True # Replace multiple hyphens with dashes self.doReplaceDash = True # Replace multiple hyphens with dashes
self.doReplaceDots = True # Replace three dots with ellipsis 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.autoScroll = False # Typewriter-like scrolling
self.autoScrollPos = 30 # Start point for typewriter-like scrolling self.autoScrollPos = 30 # Start point for typewriter-like scrolling
@@ -572,7 +571,6 @@ class Config:
self.doReplaceDQuote = conf.rdBool(sec, "repdquotes", self.doReplaceDQuote) self.doReplaceDQuote = conf.rdBool(sec, "repdquotes", self.doReplaceDQuote)
self.doReplaceDash = conf.rdBool(sec, "repdash", self.doReplaceDash) self.doReplaceDash = conf.rdBool(sec, "repdash", self.doReplaceDash)
self.doReplaceDots = conf.rdBool(sec, "repdots", self.doReplaceDots) 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.autoScroll = conf.rdBool(sec, "autoscroll", self.autoScroll)
self.autoScrollPos = conf.rdInt(sec, "autoscrollpos", self.autoScrollPos) self.autoScrollPos = conf.rdInt(sec, "autoscrollpos", self.autoScrollPos)
self.fmtSQuoteOpen = conf.rdStr(sec, "fmtsquoteopen", self.fmtSQuoteOpen) self.fmtSQuoteOpen = conf.rdStr(sec, "fmtsquoteopen", self.fmtSQuoteOpen)
@@ -695,7 +693,6 @@ class Config:
"repdquotes": str(self.doReplaceDQuote), "repdquotes": str(self.doReplaceDQuote),
"repdash": str(self.doReplaceDash), "repdash": str(self.doReplaceDash),
"repdots": str(self.doReplaceDots), "repdots": str(self.doReplaceDots),
"scrollpastend": str(self.scrollPastEnd),
"autoscroll": str(self.autoScroll), "autoscroll": str(self.autoScroll),
"autoscrollpos": str(self.autoScrollPos), "autoscrollpos": str(self.autoScrollPos),
"fmtsquoteopen": str(self.fmtSQuoteOpen), "fmtsquoteopen": str(self.fmtSQuoteOpen),
-14
View File
@@ -724,19 +724,6 @@ class GuiPreferencesEditor(QWidget):
# ================ # ================
self.mainForm.addGroupLabel(self.tr("Scroll Behaviour")) 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 # Typewriter Scrolling
self.autoScroll = NSwitch() self.autoScroll = NSwitch()
self.autoScroll.setChecked(CONFIG.autoScroll) self.autoScroll.setChecked(CONFIG.autoScroll)
@@ -775,7 +762,6 @@ class GuiPreferencesEditor(QWidget):
CONFIG.showLineEndings = self.showLineEndings.isChecked() CONFIG.showLineEndings = self.showLineEndings.isChecked()
# Scroll Behaviour # Scroll Behaviour
CONFIG.scrollPastEnd = self.scrollPastEnd.value()
CONFIG.autoScroll = self.autoScroll.isChecked() CONFIG.autoScroll = self.autoScroll.isChecked()
CONFIG.autoScrollPos = self.autoScrollPos.value() CONFIG.autoScrollPos = self.autoScrollPos.value()
+21 -44
View File
@@ -37,13 +37,12 @@ from time import time
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from PyQt5.QtCore import ( from PyQt5.QtCore import (
pyqtSignal, pyqtSlot, QObject, QPoint, QPropertyAnimation, QRegExp, pyqtSignal, pyqtSlot, QObject, QPoint, QRegExp, QRegularExpression,
QRegularExpression, QRunnable, QSize, Qt, QTimer QRunnable, QSize, Qt, QTimer
) )
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QColor, QCursor, QFont, QFontMetrics, QKeyEvent, QKeySequence, QMouseEvent, QColor, QCursor, QFont, QKeyEvent, QKeySequence, QMouseEvent, QPalette,
QPalette, QPixmap, QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QPixmap, QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption
QTextOption
) )
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAction, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu, QAction, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu,
@@ -142,6 +141,7 @@ class GuiDocEditor(QPlainTextEdit):
self.setMinimumWidth(CONFIG.pxInt(300)) self.setMinimumWidth(CONFIG.pxInt(300))
self.setAutoFillBackground(True) self.setAutoFillBackground(True)
self.setFrameStyle(QFrame.NoFrame) self.setFrameStyle(QFrame.NoFrame)
self.setCenterOnScroll(True)
# Custom Shortcuts # Custom Shortcuts
self.keyContext = QShortcut(self) self.keyContext = QShortcut(self)
@@ -311,7 +311,7 @@ class GuiDocEditor(QPlainTextEdit):
# Set default text margins # Set default text margins
# Due to cursor visibility, a part of the margin must be # Due to cursor visibility, a part of the margin must be
# allocated to the document itself. See issue #1112. # allocated to the document itself. See issue #1112.
cW = self.cursorWidth() cW = 2*self.cursorWidth()
qDoc = self.document() qDoc = self.document()
qDoc.setDocumentMargin(cW) qDoc.setDocumentMargin(cW)
self._vpMargin = max(CONFIG.getTextMargin() - cW, 0) self._vpMargin = max(CONFIG.getTextMargin() - cW, 0)
@@ -369,13 +369,13 @@ class GuiDocEditor(QPlainTextEdit):
self._nwDocument = SHARED.project.storage.getDocument(tHandle) self._nwDocument = SHARED.project.storage.getDocument(tHandle)
self._nwItem = self._nwDocument.nwItem self._nwItem = self._nwDocument.nwItem
theDoc = self._nwDocument.readDocument() docText = self._nwDocument.readDocument()
if theDoc is None: if docText is None:
# There was an io error # There was an io error
self.clearEditor() self.clearEditor()
return False return False
docSize = len(theDoc) docSize = len(docText)
if docSize > nwConst.MAX_DOCSIZE: if docSize > nwConst.MAX_DOCSIZE:
SHARED.error(self.tr( SHARED.error(self.tr(
"The document you are trying to open is too big. " "The document you are trying to open is too big. "
@@ -389,22 +389,20 @@ class GuiDocEditor(QPlainTextEdit):
return False return False
qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) qApp.setOverrideCursor(QCursor(Qt.WaitCursor))
self._docHandle = tHandle
self.highLight.setHandle(tHandle) self.highLight.setHandle(tHandle)
bfTime = time() tStart = time()
self._allowAutoReplace(False) self._allowAutoReplace(False)
self.setPlainText(theDoc) self.setPlainText(docText)
qApp.processEvents()
self._allowAutoReplace(True) self._allowAutoReplace(True)
afTime = time() logger.debug("Document text loaded in %.3f ms", 1000*(time() - tStart))
logger.debug("Document highlighted in %.3f ms", 1000*(afTime-bfTime)) qApp.processEvents()
self._lastEdit = time() self._lastEdit = time()
self._lastActive = time() self._lastActive = time()
self._runDocCounter() self._runDocCounter()
self.wcTimerDoc.start() self.wcTimerDoc.start()
self._docHandle = tHandle
self.setReadOnly(False) self.setReadOnly(False)
self.docHeader.setTitleFromHandle(self._docHandle) self.docHeader.setTitleFromHandle(self._docHandle)
@@ -416,12 +414,6 @@ class GuiDocEditor(QPlainTextEdit):
elif isinstance(tLine, int): elif isinstance(tLine, int):
self.setCursorLine(tLine) 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() self.docFooter.updateLineCount()
qApp.processEvents() qApp.processEvents()
@@ -636,19 +628,14 @@ class GuiDocEditor(QPlainTextEdit):
self._nwItem.setCursorPos(cursPos) self._nwItem.setCursorPos(cursPos)
return 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.""" """Move the cursor to a given line in the document."""
if not isinstance(line, int): if isinstance(line, int) and line > 0:
return False block = self.document().findBlockByNumber(line - 1)
lineIdx = line - 1 # Block index is 0 offset, lineNo is 1 offset
if lineIdx >= 0:
block = self.document().findBlockByNumber(lineIdx)
if block: if block:
self.setCursorPosition(block.position()) self.setCursorPosition(block.position())
logger.debug("Cursor moved to line %d", line) logger.debug("Cursor moved to line %d", line)
return
return True
## ##
# Spell Checking # Spell Checking
@@ -950,26 +937,16 @@ class GuiDocEditor(QPlainTextEdit):
return return
if CONFIG.autoScroll: if CONFIG.autoScroll:
cPos = self.cursorRect().topLeft().y()
cOld = self.cursorRect().center().y()
super().keyPressEvent(event) super().keyPressEvent(event)
kMod = event.modifiers() kMod = event.modifiers()
okMod = kMod == Qt.NoModifier or kMod == Qt.ShiftModifier okMod = kMod == Qt.NoModifier or kMod == Qt.ShiftModifier
okKey = event.key() not in self.MOVE_KEYS okKey = event.key() not in self.MOVE_KEYS
if okMod and okKey: if okMod and okKey:
cNew = self.cursorRect().center().y()
cMov = cNew - cOld
mPos = CONFIG.autoScrollPos*0.01 * self.viewport().height() mPos = CONFIG.autoScrollPos*0.01 * self.viewport().height()
if abs(cMov) > 0 and cOld > mPos: if cPos > mPos:
# Move the scroll bar
vBar = self.verticalScrollBar() vBar = self.verticalScrollBar()
doAnim = QPropertyAnimation(vBar, b"value", self) vBar.setValue(vBar.value() + 1)
doAnim.setDuration(120)
doAnim.setStartValue(vBar.value())
doAnim.setEndValue(vBar.value() + cMov)
doAnim.start()
else: else:
super().keyPressEvent(event) super().keyPressEvent(event)
@@ -43,7 +43,6 @@ repsquotes = True
repdquotes = True repdquotes = True
repdash = True repdash = True
repdots = True repdots = True
scrollpastend = 25
autoscroll = False autoscroll = False
autoscrollpos = 30 autoscrollpos = 30
fmtsquoteopen = fmtsquoteopen =
@@ -43,7 +43,6 @@ repsquotes = True
repdquotes = True repdquotes = True
repdash = True repdash = True
repdots = True repdots = True
scrollpastend = 0
autoscroll = True autoscroll = True
autoscrollpos = 30 autoscrollpos = 30
fmtsquoteopen = fmtsquoteopen =
@@ -156,9 +156,6 @@ def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, tstPaths):
qtbot.mouseClick(tabEditor.autoScroll, Qt.LeftButton) qtbot.mouseClick(tabEditor.autoScroll, Qt.LeftButton)
assert tabEditor.autoScroll.isChecked() assert tabEditor.autoScroll.isChecked()
qtbot.wait(KEY_DELAY)
tabEditor.scrollPastEnd.setValue(0)
# Syntax Settings # Syntax Settings
qtbot.wait(KEY_DELAY) qtbot.wait(KEY_DELAY)
tabSyntax = nwPrefs.tabSyntax tabSyntax = nwPrefs.tabSyntax
+7 -6
View File
@@ -200,8 +200,9 @@ def testGuiEditor_MetaData(qtbot, nwGUI, projPath, mockRnd):
nwGUI.docEditor.saveCursorPosition() nwGUI.docEditor.saveCursorPosition()
assert SHARED.project.tree[C.hSceneDoc].cursorPos == 10 assert SHARED.project.tree[C.hSceneDoc].cursorPos == 10
assert nwGUI.docEditor.setCursorLine(None) is False nwGUI.docEditor.setCursorLine(None)
assert nwGUI.docEditor.setCursorLine(3) is True assert nwGUI.docEditor.getCursorPosition() == 10
nwGUI.docEditor.setCursorLine(3)
assert nwGUI.docEditor.getCursorPosition() == 15 assert nwGUI.docEditor.getCursorPosition() == 15
# Document Changed Signal # Document Changed Signal
@@ -499,7 +500,7 @@ def testGuiEditor_Insert(qtbot, monkeypatch, nwGUI, projPath, ipsumText, mockRnd
theText = "### A Scene\n\n\n%s" % ipsumText[0] theText = "### A Scene\n\n\n%s" % ipsumText[0]
assert nwGUI.docEditor.replaceText(theText) is True assert nwGUI.docEditor.replaceText(theText) is True
assert nwGUI.docEditor.setCursorLine(3) nwGUI.docEditor.setCursorLine(3)
# Invalid Keyword # Invalid Keyword
assert nwGUI.docEditor.insertKeyWord("stuff") is False assert nwGUI.docEditor.insertKeyWord("stuff") is False
@@ -1039,7 +1040,7 @@ def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, projPath, ipsumText
# Third Line # Third Line
# This also needs to add a new block # This also needs to add a new block
assert nwGUI.docEditor.replaceText("#### Title\n\nThe Text\n\n") is True assert nwGUI.docEditor.replaceText("#### Title\n\nThe Text\n\n") is True
assert nwGUI.docEditor.setCursorLine(3) is True nwGUI.docEditor.setCursorLine(3)
assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_COM) is True assert nwGUI.docEditor._formatBlock(nwDocAction.BLOCK_COM) is True
assert nwGUI.docEditor.getText() == "#### Title\n\n% The Text\n\n" assert nwGUI.docEditor.getText() == "#### Title\n\n% The Text\n\n"
@@ -1072,11 +1073,11 @@ def testGuiEditor_Tags(qtbot, nwGUI, projPath, ipsumText, mockRnd):
assert nwGUI.openDocument(C.hSceneDoc) is True assert nwGUI.openDocument(C.hSceneDoc) is True
# Empty Block # Empty Block
assert nwGUI.docEditor.setCursorLine(2) is True nwGUI.docEditor.setCursorLine(2)
assert nwGUI.docEditor._followTag() is False assert nwGUI.docEditor._followTag() is False
# Not On Tag # Not On Tag
assert nwGUI.docEditor.setCursorLine(1) is True nwGUI.docEditor.setCursorLine(1)
assert nwGUI.docEditor._followTag() is False assert nwGUI.docEditor._followTag() is False
# On Tag Keyword # On Tag Keyword