Merge branch 'main' into testing

This commit is contained in:
Veronica K. B. Olsen
2021-03-17 17:25:00 +01:00
6 changed files with 197 additions and 168 deletions
+8 -13
View File
@@ -81,19 +81,14 @@ class nwDocAction(Enum):
D_QUOTE = 10
SEL_ALL = 11
SEL_PARA = 12
FIND = 13
REPLACE = 14
GO_NEXT = 15
GO_PREV = 16
REPL_NEXT = 17
BLOCK_H1 = 18
BLOCK_H2 = 19
BLOCK_H3 = 20
BLOCK_H4 = 21
BLOCK_COM = 22
BLOCK_TXT = 23
REPL_SNG = 24
REPL_DBL = 25
BLOCK_H1 = 13
BLOCK_H2 = 14
BLOCK_H3 = 15
BLOCK_H4 = 16
BLOCK_COM = 17
BLOCK_TXT = 18
REPL_SNG = 19
REPL_DBL = 20
# END Enum nwDocAction
+151 -144
View File
@@ -684,10 +684,6 @@ class GuiDocEditor(QTextEdit):
this class when calling these actions from other classes.
"""
logger.verbose("Requesting action: %s" % theAction.name)
if not self.hasFocus():
logger.verbose("Editor does not have focus")
return False
if self.theHandle is None:
logger.error("No document open")
return False
@@ -717,16 +713,6 @@ class GuiDocEditor(QTextEdit):
self._makeSelection(QTextCursor.Document)
elif theAction == nwDocAction.SEL_PARA:
self._makeSelection(QTextCursor.BlockUnderCursor)
elif theAction == nwDocAction.FIND:
self._beginSearch()
elif theAction == nwDocAction.REPLACE:
self._beginReplace()
elif theAction == nwDocAction.GO_NEXT:
self._findNext()
elif theAction == nwDocAction.GO_PREV:
self._findNext(isBackward=True)
elif theAction == nwDocAction.REPL_NEXT:
self._replaceNext()
elif theAction == nwDocAction.BLOCK_H1:
self._formatBlock(nwDocAction.BLOCK_H1)
elif theAction == nwDocAction.BLOCK_H2:
@@ -758,6 +744,15 @@ class GuiDocEditor(QTextEdit):
"""
return self.qDocument.isEmpty()
def anyFocus(self):
"""Check if any widget or child widget has focus.
"""
if self.hasFocus():
return True
if self.isAncestorOf(qApp.focusWidget()):
return True
return False
def revealLocation(self):
"""Tell the user where on the file system the file in the editor
is saved.
@@ -851,7 +846,7 @@ class GuiDocEditor(QTextEdit):
if self.docSearch.isVisible():
self.docSearch.closeSearch()
else:
self._beginSearch()
self.beginSearch()
return
##
@@ -1169,6 +1164,144 @@ class GuiDocEditor(QTextEdit):
logger.verbose("Denied cursor move to %d > %d" % (self.queuePos, thePos))
return
##
# Search & Replace
##
def beginSearch(self):
"""Sets 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()
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.
"""
theCursor = self.textCursor()
if theCursor.hasSelection():
self.docSearch.setSearchText(theCursor.selectedText())
else:
self.docSearch.setSearchText(None)
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.
"""
if not self.anyFocus():
logger.debug("Editor does not have focus")
return False
if not self.docSearch.isVisible():
self.beginSearch()
return
findOpt = QTextDocument.FindFlag(0)
if goBack:
findOpt |= QTextDocument.FindBackward
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.theHandle, 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)
if wasFound:
theCursor = self.textCursor()
self.lastFind = (theCursor.selectionStart(), theCursor.selectionEnd())
return
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.
"""
if not self.anyFocus():
logger.debug("Editor does not have focus")
return False
if not self.docSearch.isVisible():
# The search tool is not active, so we activate it.
self.beginSearch()
return
theCursor = self.textCursor()
if not theCursor.hasSelection():
# We have no text selected at all, so just make this a
# regular find next call.
self.findNext()
return
if self.lastFind is None and theCursor.hasSelection():
# If we have a selection but no search, it may have been the
# text we triggered the search with, in which case we search
# again from the beginning of that selection to make sure we
# have a valid result.
sPos = theCursor.selectionStart()
theCursor.clearSelection()
theCursor.setPosition(sPos)
self.setTextCursor(theCursor)
self.findNext()
theCursor = self.textCursor()
if self.lastFind is None:
# In case the above didn't find a result, we give up here.
return
searchFor = self.docSearch.getSearchText()
replWith = self.docSearch.getReplaceText()
if self.docSearch.doMatchCap:
replWith = transferCase(theCursor.selectedText(), replWith)
# Make sure the selected text was selected by an actual find
# call, and not the user.
try:
isFind = self.lastFind[0] == theCursor.selectionStart()
isFind &= self.lastFind[1] == theCursor.selectionEnd()
except Exception:
isFind = False
if isFind:
theCursor.beginEditBlock()
theCursor.removeSelectedText()
theCursor.insertText(replWith)
theCursor.endEditBlock()
theCursor.setPosition(theCursor.selectionEnd())
self.setTextCursor(theCursor)
logger.verbose("Replaced occurrence of '%s' with '%s' on line %d" % (
searchFor, replWith, theCursor.blockNumber()
))
else:
logger.error("The selected text is not a search result, skipping replace")
self.findNext()
return
##
# Internal Functions
##
@@ -1630,132 +1763,6 @@ class GuiDocEditor(QTextEdit):
self._makeSelection(selMode)
return
def _beginSearch(self):
"""Sets 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()
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.
"""
theCursor = self.textCursor()
if theCursor.hasSelection():
self.docSearch.setSearchText(theCursor.selectedText())
else:
self.docSearch.setSearchText(None)
self.docSearch.setReplaceText("")
self.updateDocMargins()
return
def _findNext(self, isBackward=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.
"""
if not self.docSearch.isVisible():
self._beginSearch()
return
findOpt = QTextDocument.FindFlag(0)
if isBackward:
findOpt |= QTextDocument.FindBackward
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 isBackward:
self.theParent.openNextDocument(
self.theHandle, wrapAround=self.docSearch.doLoop
)
elif self.docSearch.doLoop:
theCursor = self.textCursor()
theCursor.movePosition(
QTextCursor.End if isBackward else QTextCursor.Start
)
self.setTextCursor(theCursor)
wasFound = self.find(searchFor, findOpt)
if wasFound:
theCursor = self.textCursor()
self.lastFind = (theCursor.selectionStart(), theCursor.selectionEnd())
return
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.
"""
if not self.docSearch.isVisible():
# The search tool is not active, so we activate it.
self._beginSearch()
return
theCursor = self.textCursor()
if not theCursor.hasSelection():
# We have no text selected at all, so just make this a
# regular find next call.
self._findNext()
return
if self.lastFind is None and theCursor.hasSelection():
# If we have a selection but no search, it may have been the
# text we triggered the search with, in which case we search
# again from the beginning of that selection to make sure we
# have a valid result.
sPos = theCursor.selectionStart()
theCursor.clearSelection()
theCursor.setPosition(sPos)
self.setTextCursor(theCursor)
self._findNext()
theCursor = self.textCursor()
if self.lastFind is None:
# In case the above didn't find a result, we give up here.
return
searchFor = self.docSearch.getSearchText()
replWith = self.docSearch.getReplaceText()
if self.docSearch.doMatchCap:
replWith = transferCase(theCursor.selectedText(), replWith)
# Make sure the selected text was selected by an actual find
# call, and not the user.
try:
isFind = self.lastFind[0] == theCursor.selectionStart()
isFind &= self.lastFind[1] == theCursor.selectionEnd()
except Exception:
isFind = False
if isFind:
theCursor.beginEditBlock()
theCursor.removeSelectedText()
theCursor.insertText(replWith)
theCursor.endEditBlock()
theCursor.setPosition(theCursor.selectionEnd())
self.setTextCursor(theCursor)
logger.verbose("Replaced occurrence of '%s' with '%s' on line %d" % (
searchFor, replWith, theCursor.blockNumber()
))
else:
logger.error("The selected text is not a search result, skipping replace")
self._findNext()
return
def _setupSpellChecking(self):
"""Create the spell checking object based on the spellTool
setting in config.
@@ -2119,15 +2126,15 @@ class GuiDocEditSearch(QFrame):
"""
modKey = qApp.keyboardModifiers()
if modKey == Qt.ShiftModifier:
self.docEditor.docAction(nwDocAction.GO_PREV)
self.docEditor.findNext(goBack=True)
else:
self.docEditor.docAction(nwDocAction.GO_NEXT)
self.docEditor.findNext()
return
def _doReplace(self):
"""Call the replace action function for the document editor.
"""
self.docEditor.docAction(nwDocAction.REPL_NEXT)
self.docEditor.replaceNext()
return
def _doToggleReplace(self, theState):
+5 -5
View File
@@ -762,7 +762,7 @@ class GuiMainMenu(QMenuBar):
self.aFind = QAction(self.tr("Find"), self)
self.aFind.setStatusTip(self.tr("Find text in document"))
self.aFind.setShortcut("Ctrl+F")
self.aFind.triggered.connect(lambda: self._docAction(nwDocAction.FIND))
self.aFind.triggered.connect(lambda: self.theParent.docEditor.beginSearch())
self.srcMenu.addAction(self.aFind)
# Search > Replace
@@ -772,7 +772,7 @@ class GuiMainMenu(QMenuBar):
self.aReplace.setShortcut("Ctrl+=")
else:
self.aReplace.setShortcut("Ctrl+H")
self.aReplace.triggered.connect(lambda: self._docAction(nwDocAction.REPLACE))
self.aReplace.triggered.connect(lambda: self.theParent.docEditor.beginReplace())
self.srcMenu.addAction(self.aReplace)
# Search > Find Next
@@ -782,7 +782,7 @@ class GuiMainMenu(QMenuBar):
self.aFindNext.setShortcuts(["Ctrl+G", "F3"])
else:
self.aFindNext.setShortcuts(["F3", "Ctrl+G"])
self.aFindNext.triggered.connect(lambda: self._docAction(nwDocAction.GO_NEXT))
self.aFindNext.triggered.connect(lambda: self.theParent.docEditor.findNext())
self.srcMenu.addAction(self.aFindNext)
# Search > Find Prev
@@ -792,7 +792,7 @@ class GuiMainMenu(QMenuBar):
self.aFindPrev.setShortcuts(["Ctrl+Shift+G", "Shift+F3"])
else:
self.aFindPrev.setShortcuts(["Shift+F3", "Ctrl+Shift+G"])
self.aFindPrev.triggered.connect(lambda: self._docAction(nwDocAction.GO_PREV))
self.aFindPrev.triggered.connect(lambda: self.theParent.docEditor.findNext(goBack=True))
self.srcMenu.addAction(self.aFindPrev)
# Search > Replace Next
@@ -801,7 +801,7 @@ class GuiMainMenu(QMenuBar):
self.tr("Find and replace next occurrence of text in document")
)
self.aReplaceNext.setShortcut("Ctrl+Shift+1")
self.aReplaceNext.triggered.connect(lambda: self._docAction(nwDocAction.REPL_NEXT))
self.aReplaceNext.triggered.connect(lambda: self.theParent.docEditor.replaceNext())
self.srcMenu.addAction(self.aReplaceNext)
return
+8 -4
View File
@@ -766,14 +766,18 @@ class GuiMain(QMainWindow):
return True
def passDocumentAction(self, theAction):
"""Pass on document action theAction to the document viewer if
it has focus, otherwise pass it to the document editor.
"""Pass on document action to the document viewer if it has
focus, or pass it to the document editor if it or any of
its clid widgets have focus. If neither has focus, ignore the
action.
"""
if self.docViewer.hasFocus():
self.docViewer.docAction(theAction)
else:
elif self.docEditor.hasFocus():
self.docEditor.docAction(theAction)
return True
else:
logger.debug("Action cancelled as neither editor nor viewer has focus")
return
##
# Tree Item Actions