diff --git a/.github/workflows/syntax.yml b/.github/workflows/syntax.yml index 5294afe0..68eac6bc 100644 --- a/.github/workflows/syntax.yml +++ b/.github/workflows/syntax.yml @@ -4,9 +4,11 @@ on: push: branches: - main + - patch pull_request: branches: - main + - patch jobs: checkSyntax: diff --git a/.github/workflows/test_linux.yml b/.github/workflows/test_linux.yml index 45de8226..ad331896 100644 --- a/.github/workflows/test_linux.yml +++ b/.github/workflows/test_linux.yml @@ -4,9 +4,11 @@ on: push: branches: - main + - patch pull_request: branches: - main + - patch jobs: testLinux: diff --git a/.github/workflows/test_mac.yml b/.github/workflows/test_mac.yml index b11a2a71..ccb1c0c1 100644 --- a/.github/workflows/test_mac.yml +++ b/.github/workflows/test_mac.yml @@ -4,9 +4,11 @@ on: push: branches: - main + - patch pull_request: branches: - main + - patch jobs: testMac: diff --git a/.github/workflows/test_win.yml b/.github/workflows/test_win.yml index fd0ad402..a976026a 100644 --- a/.github/workflows/test_win.yml +++ b/.github/workflows/test_win.yml @@ -4,9 +4,11 @@ on: push: branches: - main + - patch pull_request: branches: - main + - patch jobs: testWin: diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dcc02db..1c864ca1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ # novelWriter Changelog +## Version 1.6.1 [2022-03-16] + +### Release Notes + +This is a bugfix and patch release that fixes two recursion/loop issues. One can cause a crash if +the window is resized rapidly, and one can cause a hang with certain search parameters in the +editor's search box. The Latin American Spanish translation has also been updated. + +### Detailed Changelog + +**Installation** + +* When using the new installer on Windows, the project file mime type icon path would not be + correctly configured in registry. The correct path is now used. PR #1006. + +**Internationalisation** + +* The Latin American Spanish translation has been updated with two missing translation strings. + PR #1017. + +**Bugfixes** + +* Fix a bug where rapidly resizing the main window could trigger the recursion detector in Python + if done on a slower system. The actual issue may be a race condition or similar, and the change + made at least makes it harder to trigger. PR #1007. +* With some document searches, it was possible to trigger an infinite loop in the function that + counts results. It seems to be caused by the QTextEdit widget's find function returning a + successful result status, but no actual result selection. The fix will now write a warning to the + log and exit in such cases. The number of results is also now capped at 1000. Issue #1015. + PR #1016. + +---- + ## Version 1.6 [2022-02-20] ### Release Notes diff --git a/i18n/nw_es_419.ts b/i18n/nw_es_419.ts index 223d9acf..e465c54f 100644 --- a/i18n/nw_es_419.ts +++ b/i18n/nw_es_419.ts @@ -535,12 +535,12 @@ Hide scene - Hide scene + Ocultar la escena Hide section - Hide section + Ocultar la sección diff --git a/novelwriter/assets/text/release_notes.htm b/novelwriter/assets/text/release_notes.htm index d315a9a4..6c4a7d99 100644 --- a/novelwriter/assets/text/release_notes.htm +++ b/novelwriter/assets/text/release_notes.htm @@ -37,5 +37,13 @@ not compatible.

See also the Releases page.

+

Patch Notes

+ +

Patch 1.6.1 – 16 March 2022

+ +

This is a bugfix and patch release that fixes two recursion/loop issues. One can cause a crash +if the window is resized rapidly, and one can cause a hang with certain search parameters in the +editor's search box. The Latin American Spanish translation has also been updated.

+ diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index b1760be4..4d35c978 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -1436,10 +1436,16 @@ class GuiDocEditor(QTextEdit): theCursor.setPosition(0) self.setTextCursor(theCursor) - while self.find(searchFor, findOpt): + # Search up to a maximum of 1000, and make sure certain special + # searches like a regex search for .* turns into an infinite loop + while self.find(searchFor, findOpt) and len(resE) <= 1000: theCursor = self.textCursor() - resS.append(theCursor.selectionStart()) - resE.append(theCursor.selectionEnd()) + if theCursor.hasSelection(): + resS.append(theCursor.selectionStart()) + resE.append(theCursor.selectionEnd()) + else: + logger.warning("The search returned an empty result") + break if hasSelection: theCursor.setPosition(origA, QTextCursor.MoveAnchor) @@ -2410,7 +2416,7 @@ class GuiDocEditSearch(QFrame): """Set the count values for the current search. """ currRes = "?" if currRes is None else currRes - resCount = "?" if resCount is None else resCount + resCount = "?" if resCount is None else "1000+" if resCount > 1000 else resCount minWidth = self.theTheme.getTextWidth(f"{resCount}//{resCount}", self.boxFont) self.resultLabel.setText(f"{currRes}/{resCount}") self.resultLabel.setMinimumWidth(minWidth) diff --git a/tests/test_gui/test_gui_doceditor.py b/tests/test_gui/test_gui_doceditor.py index 241acd24..8057ca41 100644 --- a/tests/test_gui/test_gui_doceditor.py +++ b/tests/test_gui/test_gui_doceditor.py @@ -1286,13 +1286,13 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum): monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *a: True) nwGUI.theProject.projTree.setSeed(42) - assert nwGUI.openProject(nwLipsum) - assert nwGUI.openDocument("4c4f28287af27") + assert nwGUI.openProject(nwLipsum) is True + assert nwGUI.openDocument("4c4f28287af27") is True origText = nwGUI.docEditor.getText() qtbot.wait(stepDelay) # Select the Word "est" - assert nwGUI.docEditor.setCursorPosition(630) + nwGUI.docEditor.setCursorPosition(630) nwGUI.docEditor._makeSelection(QTextCursor.WordUnderCursor) theCursor = nwGUI.docEditor.textCursor() assert theCursor.selectedText() == "est" @@ -1331,7 +1331,7 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum): assert nwGUI.docEditor.docSearch.isVisible() is True # Search for non-existing - assert nwGUI.docEditor.setCursorPosition(0) + 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 @@ -1342,11 +1342,18 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, nwLipsum): assert nwGUI.docEditor.docSearch.isRegEx is True # Set invalid RegEx - assert nwGUI.docEditor.setCursorPosition(0) + 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 dangerous RegEx (issue #1015) + # If this doesn't get caught, the app will hang + nwGUI.docEditor.setCursorPosition(0) + assert nwGUI.docEditor.docSearch.setSearchText(r".*") + qtbot.mouseClick(nwGUI.docEditor.docSearch.searchButton, Qt.LeftButton, delay=keyDelay) + assert abs(nwGUI.docEditor.getCursorPosition() - 14) < 3 + # Set valid RegEx assert nwGUI.docEditor.docSearch.setSearchText(r"\bSus") qtbot.mouseClick(nwGUI.docEditor.docSearch.searchButton, Qt.LeftButton, delay=keyDelay)