Add result count to search and rewrite scroll past end feature (#946)

* Restore colours to dark theme search-replace icon
* Implement a working search result counter
* Disable scroll past end feature and clean up search/replace and update test
* Re-implement scroll past end feature as a static distance
* Stop the search box from resizing on every search
This commit is contained in:
Veronica Berglyd Olsen
2022-01-01 19:36:04 +01:00
committed by GitHub
parent b0f939af32
commit 0401b8556d
9 changed files with 211 additions and 113 deletions
@@ -26,9 +26,14 @@
id="defs877" />
<path
id="path871"
style="fill:#aeaeae;fill-opacity:1;stroke-width:1.19007"
d="m 10.330622,1.9999997 c -4.5924663,0 -8.3306193,3.738153 -8.3306193,8.3306193 0,1.391929 0.3467825,2.702587 0.9532665,3.857242 0.084308,-0.108411 0.1590865,-0.228838 0.2534294,-0.323181 L 4.7482003,12.323178 C 4.5237338,11.697056 4.378519,11.032991 4.3785189,10.330619 c 0,-3.2810129 2.6710902,-5.949778 5.9521031,-5.949778 0.702303,0 1.36649,0.1429324 1.992559,0.3673563 L 14.141363,2.9300158 C 12.997884,2.3384803 11.704084,1.9999997 10.330622,1.9999997 Z m 5.635898,0.4766332 c -0.396657,0 -0.792437,0.1507259 -1.095095,0.4533829 L 3.57173,14.229712 c -0.3026571,0.302657 -0.5759103,0.751428 -0.7742385,1.227621 -0.1983282,0.47826 -0.3208556,0.99063 -0.3208556,1.418274 v 4.647756 h 4.6477558 c 0.427645,0 0.9376894,-0.122526 1.4159495,-0.320855 0.4782601,-0.198328 0.9272894,-0.471583 1.2299463,-0.774239 L 21.069984,9.1285734 c 0.302656,-0.302657 0.453382,-0.7017958 0.453382,-1.0974191 0,-0.3966562 -0.150726,-0.7924369 -0.453382,-1.0950939 L 17.063939,2.9300158 C 16.761281,2.6273588 16.362143,2.4766329 15.96652,2.4766329 Z m 0,2.2785396 3.275981,3.2759818 -1.334572,1.3368983 -3.275982,-3.2759819 z m 0,0.7300627 -0.60451,0.6045104 2.545919,2.5482442 0.460357,-0.4626829 C 18.332278,8.0413114 18.299136,7.9066594 18.256684,7.7754 Z M 13.901884,6.8221334 15.173682,8.0939305 6.6082326,16.661704 5.3364357,15.387582 Z m 2.004185,2.0041848 1.271796,1.2717968 -8.5654475,8.565448 -1.2741221,-1.271796 z m 0.353406,1.0834691 c 0.0083,0.1189097 0.01733,0.2373427 0.01861,0.3580557 l 0.169728,-0.169728 z m 2.059986,2.6993717 -5.710299,5.710299 c 0.105352,-0.03032 0.217183,-0.04484 0.320855,-0.07906 l 0.892816,0.89049 1.799581,1.797261 0.07208,0.07208 0.07672,0.06743 C 16.486443,21.66984 17.375591,22 18.275281,22 c 2.054056,0 3.724716,-1.671795 3.724716,-3.72704 0,-0.999657 -0.390465,-1.936781 -1.099745,-2.638921 l -1.129969,-1.174145 -0.639387,-0.639386 -0.890489,-0.892815 c 0.03403,-0.103138 0.04885,-0.213757 0.07906,-0.318531 z m -11.7600542,2.28784 -0.4929085,0.492908 0.5417343,0.541734 0.57196,-0.571959 C 6.960254,15.221393 6.7588057,15.062002 6.5594068,14.896999 Z m 2.7179722,1.285747 -1.209021,1.209021 0.5417345,0.541734 1.6577535,-1.655429 c -0.3372847,-0.0036 -0.668706,-0.03764 -0.990467,-0.09533 z m -4.5710293,0.06743 c 0.010333,-0.02065 3.0644031,3.034179 3.0644031,3.034179 C 7.43814,19.422771 7.2039295,19.456408 7.1243917,19.456408 H 5.5759147 L 4.5435968,18.424084 v -1.548477 c 0,-0.07953 0.033633,-0.315548 0.1627529,-0.625436 z" />
<g
id="g1022"
style="display:none;opacity:1;stroke:none;stroke-opacity:1" />
</svg>
style="display:inline;fill:#6699cc;fill-opacity:1;stroke-width:1.19007"
d="m 10.330622,1.9999997 c -4.5924663,0 -8.3306193,3.738153 -8.3306193,8.3306193 0,1.391929 0.3467825,2.702587 0.9532665,3.857242 0.084308,-0.108411 0.1590865,-0.228838 0.2534294,-0.323181 L 4.7482003,12.323178 C 4.5237338,11.697056 4.378519,11.032991 4.3785189,10.330619 c 0,-3.2810129 2.6710902,-5.949778 5.9521031,-5.949778 0.702303,0 1.36649,0.1429324 1.992559,0.3673563 L 14.141363,2.9300158 C 12.997884,2.3384803 11.704084,1.9999997 10.330622,1.9999997 Z m 5.635898,3.4852355 -0.60451,0.6045104 2.545919,2.5482442 0.460357,-0.4626829 C 18.332278,8.0413114 18.299136,7.9066594 18.256684,7.7754 Z m 0.292955,4.4245521 c 0.0083,0.1189097 0.01733,0.2373427 0.01861,0.3580557 l 0.169728,-0.169728 z m 2.059986,2.6993717 -5.710299,5.710299 c 0.105352,-0.03032 0.217183,-0.04484 0.320855,-0.07906 l 0.892816,0.89049 1.799581,1.797261 0.07208,0.07208 0.07672,0.06743 C 16.486443,21.66984 17.375591,22 18.275281,22 c 2.054056,0 3.724716,-1.671795 3.724716,-3.72704 0,-0.999657 -0.390465,-1.936781 -1.099745,-2.638921 l -1.129969,-1.174145 -0.639387,-0.639386 -0.890489,-0.892815 c 0.03403,-0.103138 0.04885,-0.213757 0.07906,-0.318531 z m -11.7600542,2.28784 -0.4929085,0.492908 0.5417343,0.541734 0.57196,-0.571959 C 6.960254,15.221393 6.7588057,15.062002 6.5594068,14.896999 Z m 2.7179722,1.285747 -1.209021,1.209021 0.5417345,0.541734 1.6577535,-1.655429 c -0.3372847,-0.0036 -0.668706,-0.03764 -0.990467,-0.09533 z" />
<path
d="m 15.96652,2.4766329 c -0.396657,0 -0.792437,0.1507259 -1.095095,0.4533829 L 3.57173,14.229712 c -0.3026571,0.302657 -0.5759103,0.751428 -0.7742385,1.227621 -0.1983282,0.47826 -0.3208556,0.99063 -0.3208556,1.418274 v 4.647756 h 4.6477558 c 0.427645,0 0.9376894,-0.122526 1.4159495,-0.320855 0.4782601,-0.198328 0.9272894,-0.471583 1.2299463,-0.774239 L 21.069984,9.1285734 c 0.302656,-0.302657 0.453382,-0.7017958 0.453382,-1.0974191 0,-0.3966562 -0.150726,-0.7924369 -0.453382,-1.0950939 L 17.063939,2.9300158 C 16.761281,2.6273588 16.362143,2.4766329 15.96652,2.4766329 Z m 0,2.2785396 3.275981,3.2759818 -1.334572,1.3368983 -3.275982,-3.2759819 z M 13.901884,6.8221334 15.173682,8.0939305 6.6082326,16.661704 5.3364357,15.387582 Z m 2.004185,2.0041848 1.271796,1.2717968 -8.5654475,8.565448 -1.2741221,-1.271796 z M 4.7063497,16.250176 c 0.010333,-0.02065 3.0644031,3.034179 3.0644031,3.034179 C 7.43814,19.422771 7.2039295,19.456408 7.1243917,19.456408 H 5.5759147 L 4.5435968,18.424084 v -1.548477 c 0,-0.07953 0.033633,-0.315548 0.1627529,-0.625436 z"
style="display:inline;fill:#99cc99;fill-opacity:1;stroke-width:1.19007"
id="path15590" />
<path
id="rect19553"
d="m 2.4766359,18.937425 v 2.585938 h 2.5605469 z"
style="display:inline;opacity:0.95;fill:#0a0a0a;fill-opacity:1;stroke:none;stroke-width:1.88249397;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

+2 -2
View File
@@ -137,7 +137,7 @@ class Config:
self.doReplaceDash = True # Replace multiple hyphens with dashes
self.doReplaceDots = True # Replace three dots with ellipsis
self.scrollPastEnd = True # Allow scrolling past end of document
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
@@ -479,7 +479,7 @@ class Config:
self.doReplaceDQuote = theConf.rdBool(cnfSec, "repdquotes", self.doReplaceDQuote)
self.doReplaceDash = theConf.rdBool(cnfSec, "repdash", self.doReplaceDash)
self.doReplaceDots = theConf.rdBool(cnfSec, "repdots", self.doReplaceDots)
self.scrollPastEnd = theConf.rdBool(cnfSec, "scrollpastend", self.scrollPastEnd)
self.scrollPastEnd = theConf.rdInt(cnfSec, "scrollpastend", self.scrollPastEnd)
self.autoScroll = theConf.rdBool(cnfSec, "autoscroll", self.autoScroll)
self.autoScrollPos = theConf.rdInt(cnfSec, "autoscrollpos", self.autoScrollPos)
self.fmtSingleQuotes = theConf.rdStrList(cnfSec, "fmtsinglequote", self.fmtSingleQuotes)
+8 -4
View File
@@ -761,12 +761,16 @@ class GuiPreferencesEditor(QWidget):
self.mainForm.addGroupLabel(self.tr("Scroll Behaviour"))
# Scroll Past End
self.scrollPastEnd = QSwitch()
self.scrollPastEnd.setChecked(self.mainConf.scrollPastEnd)
self.scrollPastEnd = QSpinBox(self)
self.scrollPastEnd.setMinimum(0)
self.scrollPastEnd.setMaximum(100)
self.scrollPastEnd.setSingleStep(1)
self.scrollPastEnd.setValue(int(self.mainConf.scrollPastEnd))
self.mainForm.addRow(
self.tr("Scroll past end of the document"),
self.scrollPastEnd,
self.tr("Also improves typewriter scrolling for short documents.")
self.tr("Set to 0 to disable this feature."),
theUnit=self.tr("lines")
)
# Typewriter Scrolling
@@ -809,7 +813,7 @@ class GuiPreferencesEditor(QWidget):
self.mainConf.showLineEndings = self.showLineEndings.isChecked()
# Scroll Behaviour
self.mainConf.scrollPastEnd = self.scrollPastEnd.isChecked()
self.mainConf.scrollPastEnd = self.scrollPastEnd.value()
self.mainConf.autoScroll = self.autoScroll.isChecked()
self.mainConf.autoScrollPos = self.autoScrollPos.value()
+121 -55
View File
@@ -29,6 +29,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import bisect
import logging
import novelwriter
@@ -39,8 +40,8 @@ from PyQt5.QtCore import (
QPointF, QObject, QRunnable, QPropertyAnimation
)
from PyQt5.QtGui import (
QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette,
QTextDocument, QCursor, QPixmap
QFontMetrics, QTextCursor, QTextOption, QKeySequence, QFont, QColor,
QPalette, QTextDocument, QCursor, QPixmap
)
from PyQt5.QtWidgets import (
qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox, QWidget, QLabel,
@@ -381,10 +382,17 @@ class GuiDocEditor(QTextEdit):
else:
self.setCursorLine(tLine)
if self.mainConf.scrollPastEnd > 0:
fSize = QFontMetrics(self.font()).lineSpacing()
docFrame = self.document().rootFrame().frameFormat()
docFrame.setBottomMargin(round(self.mainConf.scrollPastEnd * fSize))
self.document().rootFrame().setFrameFormat(docFrame)
self.docFooter.updateLineCount()
self._docHeaders = self.theIndex.getHandleHeaders(self._docHandle)
qApp.processEvents()
self.document().clearUndoRedoStacks()
self.setDocumentChanged(False)
qApp.restoreOverrideCursor()
@@ -546,17 +554,6 @@ class GuiDocEditor(QTextEdit):
lM = max(cM, fH)
self.setViewportMargins(tM, uM, tM, lM)
tmpDocChanged = self._docChanged
if self.mainConf.scrollPastEnd:
docFrame = self.document().rootFrame().frameFormat()
docFrame.setBottomMargin(max(0, 0.9*(wH - uM - lM - 4*tB)))
self.document().rootFrame().setFrameFormat(docFrame)
# This is needed as the setFrameFormat function itself will
# trigger the contetsChanged signal which sets _docChanged, so we
# set it back to whatever it was before.
self.setDocumentChanged(tmpDocChanged)
return
def updateDocInfo(self, tHandle):
@@ -1322,6 +1319,7 @@ class GuiDocEditor(QTextEdit):
self._queuePos = None
else:
logger.verbose("Denied cursor move to %d > %d", self._queuePos, thePos)
return
##
@@ -1329,75 +1327,123 @@ class GuiDocEditor(QTextEdit):
##
def beginSearch(self):
"""Sets the selected text as the search text for the search bar.
"""Set the selected text as the search text for the search bar.
"""
theCursor = self.textCursor()
if theCursor.hasSelection():
self.docSearch.setSearchText(theCursor.selectedText())
else:
self.docSearch.setSearchText(None)
self.updateDocMargins()
resS, _ = self.findAllOccurences()
self.docSearch.setResultCount(None, len(resS))
return
def beginReplace(self):
"""Opens the replace line of the search bar and sets the find
text if a selection has been made, and resets the replace text.
"""Initialise the search box and reset the replace text box.
"""
theCursor = self.textCursor()
if theCursor.hasSelection():
self.docSearch.setSearchText(theCursor.selectedText())
else:
self.docSearch.setSearchText(None)
self.beginSearch()
self.docSearch.setReplaceText("")
self.updateDocMargins()
return
def findNext(self, goBack=False):
"""Searches for the next or previous occurrence of the search
bar text in the document. Wraps around if not found and loop is
enabled, or continues to next file if next file is enabled.
"""Search for the next or previous occurrence of the search bar
text in the document. Wrap around if not found and loop is
enabled, or continue to next file if next file is enabled.
"""
if not self.anyFocus():
logger.debug("Editor does not have focus")
return False
return
if not self.docSearch.isVisible():
self.beginSearch()
return
findOpt = QTextDocument.FindFlag(0)
resS, resE = self.findAllOccurences()
if len(resS) == 0:
self.docSearch.setResultCount(0, 0)
self._lastFind = None
if self.docSearch.doNextFile and not goBack:
self.theParent.openNextDocument(
self._docHandle, wrapAround=self.docSearch.doLoop
)
self.beginSearch()
return
theCursor = self.textCursor()
resIdx = bisect.bisect_left(resS, theCursor.position())
doLoop = self.docSearch.doLoop
maxIdx = len(resS) - 1
if goBack:
findOpt |= QTextDocument.FindBackward
resIdx -= 2
if resIdx < 0:
resIdx = maxIdx if doLoop else 0
if resIdx > maxIdx:
if self.docSearch.doNextFile and not goBack:
self.theParent.openNextDocument(
self._docHandle, wrapAround=self.docSearch.doLoop
)
self.beginSearch()
return
else:
resIdx = 0 if doLoop else maxIdx
theCursor.setPosition(resS[resIdx], QTextCursor.MoveAnchor)
theCursor.setPosition(resE[resIdx], QTextCursor.KeepAnchor)
self.setTextCursor(theCursor)
self.docSearch.setResultCount(resIdx + 1, len(resS))
self._lastFind = (resS[resIdx], resE[resIdx])
return
def findAllOccurences(self):
"""Create a list of all search results of the current search in
the document.
"""
resS = []
resE = []
theCursor = self.textCursor()
hasSelection = theCursor.hasSelection()
if hasSelection:
origA = theCursor.selectionStart()
origB = theCursor.selectionEnd()
else:
origA = theCursor.position()
findOpt = QTextDocument.FindFlag(0)
if self.docSearch.isCaseSense:
findOpt |= QTextDocument.FindCaseSensitively
if self.docSearch.isWholeWord:
findOpt |= QTextDocument.FindWholeWords
searchFor = self.docSearch.getSearchObject()
wasFound = self.find(searchFor, findOpt)
if not wasFound:
if self.docSearch.doNextFile and not goBack:
self.theParent.openNextDocument(
self._docHandle, wrapAround=self.docSearch.doLoop
)
elif self.docSearch.doLoop:
theCursor = self.textCursor()
theCursor.movePosition(
QTextCursor.End if goBack else QTextCursor.Start
)
self.setTextCursor(theCursor)
wasFound = self.find(searchFor, findOpt)
theCursor.setPosition(0)
self.setTextCursor(theCursor)
if wasFound:
while self.find(searchFor, findOpt):
theCursor = self.textCursor()
self._lastFind = (theCursor.selectionStart(), theCursor.selectionEnd())
resS.append(theCursor.selectionStart())
resE.append(theCursor.selectionEnd())
return
if hasSelection:
theCursor.setPosition(origA, QTextCursor.MoveAnchor)
theCursor.setPosition(origB, QTextCursor.KeepAnchor)
else:
theCursor.setPosition(origA)
self.setTextCursor(theCursor)
return resS, resE
def replaceNext(self):
"""Searches for the next occurrence of the search bar text in
the document and replaces it with the replace text. Calls search
next automatically when done.
"""Search for the next occurrence of the search bar text in the
document and replace it with the replace text. Call search next
automatically when done.
"""
if not self.anyFocus():
logger.debug("Editor does not have focus")
@@ -2131,8 +2177,8 @@ class GuiDocEditSearch(QFrame):
mPx = self.mainConf.pxInt(6)
tPx = int(0.8*self.theTheme.fontPixelSize)
boxFont = self.theTheme.guiFont
boxFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
self.boxFont = self.theTheme.guiFont
self.boxFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
self.setContentsMargins(0, 0, 0, 0)
self.setAutoFillBackground(True)
@@ -2143,13 +2189,14 @@ class GuiDocEditSearch(QFrame):
# Text Boxes
# ==========
self.searchBox = QLineEdit(self)
self.searchBox.setFont(boxFont)
self.searchBox.setFont(self.boxFont)
self.searchBox.setPlaceholderText(self.tr("Search"))
self.searchBox.returnPressed.connect(self._doSearch)
self.replaceBox = QLineEdit(self)
self.replaceBox.setFont(boxFont)
self.replaceBox.setFont(self.boxFont)
self.replaceBox.setPlaceholderText(self.tr("Replace"))
self.replaceBox.returnPressed.connect(self._doReplace)
@@ -2160,9 +2207,13 @@ class GuiDocEditSearch(QFrame):
self.searchOpt.setStyleSheet("QToolBar {padding: 0;}")
self.searchLabel = QLabel(self.tr("Search"))
self.searchLabel.setFont(boxFont)
self.searchLabel.setFont(self.boxFont)
self.searchLabel.setIndent(self.mainConf.pxInt(6))
self.resultLabel = QLabel("?/?")
self.resultLabel.setFont(self.boxFont)
self.resultLabel.setMinimumWidth(self.theTheme.getTextWidth("?/?", self.boxFont))
self.toggleCase = QAction(self.tr("Case Sensitive"), self)
self.toggleCase.setToolTip(self.tr("Match case"))
self.toggleCase.setIcon(self.theTheme.getIcon("search_case"))
@@ -2223,6 +2274,7 @@ class GuiDocEditSearch(QFrame):
# Buttons
# =======
bPx = self.searchBox.sizeHint().height()
self.showReplace = QToolButton(self)
@@ -2243,18 +2295,20 @@ class GuiDocEditSearch(QFrame):
self.replaceButton.clicked.connect(self._doReplace)
self.mainBox.addWidget(self.searchLabel, 0, 0, 1, 2, Qt.AlignLeft)
self.mainBox.addWidget(self.searchOpt, 0, 2, 1, 2, Qt.AlignRight)
self.mainBox.addWidget(self.searchOpt, 0, 2, 1, 3, Qt.AlignRight)
self.mainBox.addWidget(self.showReplace, 1, 0, 1, 1)
self.mainBox.addWidget(self.searchBox, 1, 1, 1, 2)
self.mainBox.addWidget(self.searchButton, 1, 3, 1, 1)
self.mainBox.addWidget(self.resultLabel, 1, 4, 1, 1)
self.mainBox.addWidget(self.replaceBox, 2, 1, 1, 2)
self.mainBox.addWidget(self.replaceButton, 2, 3, 1, 1)
self.mainBox.setColumnStretch(0, 1)
self.mainBox.setColumnStretch(0, 0)
self.mainBox.setColumnStretch(1, 0)
self.mainBox.setColumnStretch(2, 0)
self.mainBox.setColumnStretch(2, 1)
self.mainBox.setColumnStretch(3, 0)
self.mainBox.setColumnStretch(4, 0)
self.mainBox.setColumnStretch(5, 0)
self.mainBox.setSpacing(self.mainConf.pxInt(2))
self.mainBox.setContentsMargins(mPx, mPx, mPx, mPx)
@@ -2349,6 +2403,18 @@ class GuiDocEditSearch(QFrame):
self.replaceBox.setText(theText)
return True
def setResultCount(self, currRes, resCount):
"""Set the count values for the current search.
"""
currRes = "?" if currRes is None else currRes
resCount = "?" if resCount is None else resCount
minWidth = self.theTheme.getTextWidth(f"{resCount}//{resCount}", self.boxFont)
self.resultLabel.setText(f"{currRes}/{resCount}")
self.resultLabel.setMinimumWidth(minWidth)
self.adjustSize()
self.docEditor.updateDocMargins()
return
def getSearchObject(self):
"""Return the current search text either as text or as a regular
expression object.
+1 -1
View File
@@ -42,7 +42,7 @@ repsquotes = True
repdquotes = True
repdash = True
repdots = True
scrollpastend = True
scrollpastend = 25
autoscroll = False
autoscrollpos = 30
fmtsinglequote = ,
@@ -42,7 +42,7 @@ repsquotes = True
repdquotes = True
repdash = True
repdots = True
scrollpastend = False
scrollpastend = 0
autoscroll = True
autoscrollpos = 30
fmtsinglequote = ,
+3 -5
View File
@@ -169,16 +169,14 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
qtbot.mouseClick(tabEditor.showLineEndings, Qt.LeftButton)
assert tabEditor.showLineEndings.isChecked()
qtbot.wait(keyDelay)
assert tabEditor.scrollPastEnd.isChecked()
qtbot.mouseClick(tabEditor.scrollPastEnd, Qt.LeftButton)
assert not tabEditor.scrollPastEnd.isChecked()
qtbot.wait(keyDelay)
assert not tabEditor.autoScroll.isChecked()
qtbot.mouseClick(tabEditor.autoScroll, Qt.LeftButton)
assert tabEditor.autoScroll.isChecked()
qtbot.wait(keyDelay)
tabEditor.scrollPastEnd.setValue(0)
qtbot.wait(keyDelay)
tabEditor.bigDocLimit.setValue(500)
+64 -38
View File
@@ -1297,135 +1297,151 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum):
theCursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == "est"
# Activate Search
# Activate search
nwGUI.mainMenu.aFind.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.isVisible()
assert nwGUI.docEditor.docSearch.getSearchText() == "est"
# Find Next by Enter
# Find next by enter key
monkeypatch.setattr(nwGUI.docEditor.docSearch.searchBox, "hasFocus", lambda: True)
qtbot.keyClick(nwGUI.docEditor.docSearch.searchBox, Qt.Key_Return, delay=keyDelay)
assert abs(nwGUI.docEditor.getCursorPosition() - 1284) < 3
# Find Next by Button
# Find next by button
qtbot.mouseClick(nwGUI.docEditor.docSearch.searchButton, Qt.LeftButton, delay=keyDelay)
assert abs(nwGUI.docEditor.getCursorPosition() - 1498) < 3
# Activate Loop Search
# Activate loop search
nwGUI.docEditor.docSearch.toggleLoop.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.toggleLoop.isChecked()
assert nwGUI.docEditor.docSearch.doLoop
assert nwGUI.docEditor.docSearch.doLoop is True
# Find Next by Menu Search > Find Next
# Find next by menu Search > Find Next
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 632) < 3
# Close Search
# Close search
nwGUI.docEditor.docSearch.cancelSearch.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.isVisible() is False
assert nwGUI.docEditor.setCursorPosition(15)
# Toggle Search Again with Header Button
# Toggle search again with header button
qtbot.mouseClick(nwGUI.docEditor.docHeader.searchButton, Qt.LeftButton, delay=keyDelay)
assert nwGUI.docEditor.docSearch.setSearchText("")
assert nwGUI.docEditor.docSearch.isVisible() is True
# Enable RegEx Search
# Search for non-existing
assert nwGUI.docEditor.setCursorPosition(0)
assert nwGUI.docEditor.docSearch.setSearchText("abcdef")
qtbot.mouseClick(nwGUI.docEditor.docSearch.searchButton, Qt.LeftButton, delay=keyDelay)
assert nwGUI.docEditor.getCursorPosition() < 3 # No result
# Enable RegEx search
nwGUI.docEditor.docSearch.toggleRegEx.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.toggleRegEx.isChecked()
assert nwGUI.docEditor.docSearch.isRegEx
assert nwGUI.docEditor.docSearch.isRegEx is True
# Set Invalid RegEx
# Set invalid RegEx
assert nwGUI.docEditor.setCursorPosition(0)
assert nwGUI.docEditor.docSearch.setSearchText(r"\bSus[")
qtbot.mouseClick(nwGUI.docEditor.docSearch.searchButton, Qt.LeftButton, delay=keyDelay)
assert nwGUI.docEditor.getCursorPosition() < 3 # No result
# Set Valid RegEx
# Set valid RegEx
assert nwGUI.docEditor.docSearch.setSearchText(r"\bSus")
qtbot.mouseClick(nwGUI.docEditor.docSearch.searchButton, Qt.LeftButton, delay=keyDelay)
assert abs(nwGUI.docEditor.getCursorPosition() - 208) < 3
# Find Next and then Prev
# Find next and then prev
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 309) < 3
nwGUI.mainMenu.aFindPrev.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 208) < 3
# Make RegEx Case Sensitive
# Make RegEx case sensitive
nwGUI.docEditor.docSearch.toggleCase.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.toggleCase.isChecked()
assert nwGUI.docEditor.docSearch.isCaseSense
assert nwGUI.docEditor.docSearch.isCaseSense is True
# Find Next (One Result)
# Find next/prev (one result)
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 611) < 3
nwGUI.mainMenu.aFindPrev.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 611) < 3
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 611) < 3
# Trigger Replace
# Trigger replace
nwGUI.mainMenu.aReplace.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.setReplaceText("foo")
# Disable RegEx Case Sensitive
# Disable RegEx case sensitive
nwGUI.docEditor.docSearch.toggleCase.activate(QAction.Trigger)
assert not nwGUI.docEditor.docSearch.toggleCase.isChecked()
assert not nwGUI.docEditor.docSearch.isCaseSense
assert nwGUI.docEditor.docSearch.isCaseSense is False
# Toggle Replace Preserve Case
# Toggle replace preserve case
nwGUI.docEditor.docSearch.toggleMatchCap.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.toggleMatchCap.isChecked()
assert nwGUI.docEditor.docSearch.doMatchCap
assert nwGUI.docEditor.docSearch.doMatchCap is True
# Replace "Sus" with "Foo" via Menu
# Replace "Sus" with "Foo" via menu
assert nwGUI.docEditor.setCursorPosition(590)
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
nwGUI.mainMenu.aReplaceNext.activate(QAction.Trigger)
assert nwGUI.docEditor.getText()[608:619] == "Foopendisse"
# Find Next to Loop File
# Find next/prev to loop file
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 208) < 3
nwGUI.mainMenu.aFindPrev.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 1790) < 3
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 208) < 3
# Replace "sus" with "foo" via Replace Button
# Replace "sus" with "foo" via replace button
qtbot.mouseClick(nwGUI.docEditor.docSearch.replaceButton, Qt.LeftButton, delay=keyDelay)
assert nwGUI.docEditor.getText()[205:213] == "foocipit"
# Revert Last Two Replaces
# Revert last two replaces
assert nwGUI.docEditor.docAction(nwDocAction.UNDO)
assert nwGUI.docEditor.docAction(nwDocAction.UNDO)
assert nwGUI.docEditor.getText() == origText
# Disable RegEx Search
# Disable RegEx search
nwGUI.docEditor.docSearch.toggleRegEx.activate(QAction.Trigger)
assert not nwGUI.docEditor.docSearch.toggleRegEx.isChecked()
assert not nwGUI.docEditor.docSearch.isRegEx
assert nwGUI.docEditor.docSearch.isRegEx is False
# Close Search and Select "est" Again
# Close search and select "est" again
nwGUI.docEditor.docSearch.cancelSearch.activate(QAction.Trigger)
assert nwGUI.docEditor.setCursorPosition(630)
nwGUI.docEditor._makeSelection(QTextCursor.WordUnderCursor)
theCursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == "est"
# Activate Search Again
# Activate search again
nwGUI.mainMenu.aFind.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.isVisible()
assert nwGUI.docEditor.docSearch.getSearchText() == "est"
# Enable Full Word Search
# Enable full word search
nwGUI.docEditor.docSearch.toggleWord.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.toggleWord.isChecked()
assert nwGUI.docEditor.docSearch.isWholeWord
assert nwGUI.docEditor.docSearch.isWholeWord is True
# Only One Match
# Only one match
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 632) < 3
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 632) < 3
# Enable Next Doc Search
# Enable next doc search
nwGUI.docEditor.docSearch.toggleProject.activate(QAction.Trigger)
assert nwGUI.docEditor.docSearch.toggleProject.isChecked()
assert nwGUI.docEditor.docSearch.doNextFile
assert nwGUI.docEditor.docSearch.doNextFile is True
# Next Match
# Next match
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert nwGUI.docEditor.docHandle() == "2426c6f0ca922" # Next document
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
@@ -1433,6 +1449,16 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum):
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert abs(nwGUI.docEditor.getCursorPosition() - 1127) < 3
# Next doc, no match
assert nwGUI.docEditor.docSearch.doNextFile is True
assert nwGUI.docEditor.docSearch.setSearchText("abcdef")
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert nwGUI.docEditor.docHandle() != "2426c6f0ca922"
assert nwGUI.docEditor.docHandle() == "04468803b92e1"
nwGUI.mainMenu.aFindNext.activate(QAction.Trigger)
assert nwGUI.docEditor.docHandle() != "04468803b92e1"
assert nwGUI.docEditor.docHandle() == "7a992350f3eb6"
# Toggle Replace
nwGUI.docEditor.beginReplace()
@@ -1441,16 +1467,16 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum):
monkeypatch.setattr(nwGUI.docEditor, "hasFocus", lambda: True)
monkeypatch.setattr(nwGUI.docEditor.docSearch.searchBox, "hasFocus", lambda: False)
monkeypatch.setattr(nwGUI.docEditor.docSearch.replaceBox, "hasFocus", lambda: False)
assert not nwGUI.docEditor.focusNextPrevChild(True)
assert nwGUI.docEditor.focusNextPrevChild(True) is False
monkeypatch.setattr(nwGUI.docEditor, "hasFocus", lambda: False)
monkeypatch.setattr(nwGUI.docEditor.docSearch.searchBox, "hasFocus", lambda: True)
monkeypatch.setattr(nwGUI.docEditor.docSearch.replaceBox, "hasFocus", lambda: False)
assert nwGUI.docEditor.focusNextPrevChild(True)
assert nwGUI.docEditor.focusNextPrevChild(True) is True
monkeypatch.setattr(nwGUI.docEditor.docSearch.searchBox, "hasFocus", lambda: False)
monkeypatch.setattr(nwGUI.docEditor.docSearch.replaceBox, "hasFocus", lambda: True)
assert nwGUI.docEditor.focusNextPrevChild(True)
assert nwGUI.docEditor.focusNextPrevChild(True) is True
# qtbot.stopForInteraction()
-1
View File
@@ -199,7 +199,6 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir):
# Change some settings
nwGUI.mainConf.hideHScroll = True
nwGUI.mainConf.hideVScroll = True
nwGUI.mainConf.scrollPastEnd = True
nwGUI.mainConf.autoScrollPos = 80
nwGUI.mainConf.autoScroll = True