diff --git a/novelwriter/dialogs/about.py b/novelwriter/dialogs/about.py index 226d0054..628c4e4e 100644 --- a/novelwriter/dialogs/about.py +++ b/novelwriter/dialogs/about.py @@ -85,7 +85,7 @@ class GuiAbout(NDialog): # Buttons self.btnBox = QDialogButtonBox(QtDialogClose, self) - self.btnBox.rejected.connect(self.close) + self.btnBox.rejected.connect(self.reject) # Assemble self.innerBox = QVBoxLayout() diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index fcd463b5..d08498b2 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -27,7 +27,7 @@ from __future__ import annotations import logging from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot -from PyQt5.QtGui import QCloseEvent +from PyQt5.QtGui import QCloseEvent, QKeyEvent, QKeySequence from PyQt5.QtWidgets import ( QAbstractButton, QCompleter, QDialogButtonBox, QFileDialog, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout, QWidget @@ -770,6 +770,16 @@ class GuiPreferences(NDialog): self.softDelete() return + def keyPressEvent(self, event: QKeyEvent) -> None: + """Overload keyPressEvent and only accept escape. The main + purpose here is to prevent Enter/Return from closing the dialog + as it is used for the search box. + """ + if event.matches(QKeySequence.StandardKey.Cancel): + self.close() + event.ignore() + return + ## # Private Slots ## diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py index 010f50e1..c8d72d88 100644 --- a/novelwriter/dialogs/projectsettings.py +++ b/novelwriter/dialogs/projectsettings.py @@ -92,7 +92,7 @@ class GuiProjectSettings(NDialog): # Buttons self.buttonBox = QDialogButtonBox(QtDialogSave | QtDialogCancel, self) self.buttonBox.accepted.connect(self._doSave) - self.buttonBox.rejected.connect(self.close) + self.buttonBox.rejected.connect(self.reject) # Content SHARED.project.countStatus() diff --git a/novelwriter/dialogs/wordlist.py b/novelwriter/dialogs/wordlist.py index 51ce49b6..8f3f53f5 100644 --- a/novelwriter/dialogs/wordlist.py +++ b/novelwriter/dialogs/wordlist.py @@ -109,7 +109,7 @@ class GuiWordList(NDialog): # Buttons self.buttonBox = QDialogButtonBox(QtDialogSave | QtDialogClose, self) self.buttonBox.accepted.connect(self._doSave) - self.buttonBox.rejected.connect(self.close) + self.buttonBox.rejected.connect(self.reject) # Assemble self.outerBox = QVBoxLayout() diff --git a/novelwriter/extensions/modified.py b/novelwriter/extensions/modified.py index 12048497..f07e2553 100644 --- a/novelwriter/extensions/modified.py +++ b/novelwriter/extensions/modified.py @@ -30,8 +30,8 @@ from __future__ import annotations from enum import Enum from typing import TYPE_CHECKING -from PyQt5.QtCore import QSize, Qt -from PyQt5.QtGui import QKeyEvent, QKeySequence, QWheelEvent +from PyQt5.QtCore import QSize, Qt, pyqtSlot +from PyQt5.QtGui import QWheelEvent from PyQt5.QtWidgets import ( QApplication, QComboBox, QDialog, QDoubleSpinBox, QSpinBox, QToolButton, QWidget @@ -54,11 +54,11 @@ class NDialog(QDialog): self.setParent(None) # type: ignore return - def keyPressEvent(self, event: QKeyEvent) -> None: - """Overload keyPressEvent and forward escape to close.""" - if event.matches(QKeySequence.StandardKey.Cancel): - self.close() - event.ignore() + @pyqtSlot() + def reject(self) -> None: + """Overload the reject slot and also call close.""" + super().reject() + self.close() return diff --git a/novelwriter/tools/dictionaries.py b/novelwriter/tools/dictionaries.py index f56e5761..b495ea31 100644 --- a/novelwriter/tools/dictionaries.py +++ b/novelwriter/tools/dictionaries.py @@ -109,7 +109,7 @@ class GuiDictionaries(NNonBlockingDialog): # Buttons self.buttonBox = QDialogButtonBox(QtDialogClose, self) - self.buttonBox.rejected.connect(self._doClose) + self.buttonBox.rejected.connect(self.reject) # Assemble self.innerBox = QVBoxLayout() @@ -220,12 +220,6 @@ class GuiDictionaries(NNonBlockingDialog): SHARED.error("Path not found.") return - @pyqtSlot() - def _doClose(self) -> None: - """Close the dialog.""" - self.close() - return - ## # Internal Functions ## diff --git a/novelwriter/tools/lipsum.py b/novelwriter/tools/lipsum.py index 9296d5b8..9d05c51c 100644 --- a/novelwriter/tools/lipsum.py +++ b/novelwriter/tools/lipsum.py @@ -26,7 +26,7 @@ from __future__ import annotations import logging import random -from PyQt5.QtCore import Qt, pyqtSlot +from PyQt5.QtCore import pyqtSlot from PyQt5.QtWidgets import ( QDialogButtonBox, QGridLayout, QHBoxLayout, QLabel, QSpinBox, QVBoxLayout, QWidget @@ -48,13 +48,10 @@ class GuiLipsum(NDialog): logger.debug("Create: GuiLipsum") self.setObjectName("GuiLipsum") - if CONFIG.osDarwin: - self.setWindowFlag(Qt.WindowType.Tool) + self.setWindowTitle(self.tr("Insert Placeholder Text")) self._lipsumText = "" - self.setWindowTitle(self.tr("Insert Placeholder Text")) - vSp = CONFIG.pxInt(4) nPx = CONFIG.pxInt(64) @@ -96,7 +93,7 @@ class GuiLipsum(NDialog): # Buttons self.buttonBox = QDialogButtonBox(self) - self.buttonBox.rejected.connect(self.close) + self.buttonBox.rejected.connect(self.reject) self.btnClose = self.buttonBox.addButton(QtDialogClose) self.btnClose.setAutoDefault(False) @@ -105,8 +102,6 @@ class GuiLipsum(NDialog): self.btnInsert.clicked.connect(self._doInsert) self.btnInsert.setAutoDefault(False) - self.rejected.connect(self.close) - # Assemble self.outerBox = QVBoxLayout() self.outerBox.addLayout(self.innerBox) diff --git a/novelwriter/tools/noveldetails.py b/novelwriter/tools/noveldetails.py index 9362c640..cd7f5f38 100644 --- a/novelwriter/tools/noveldetails.py +++ b/novelwriter/tools/noveldetails.py @@ -97,7 +97,7 @@ class GuiNovelDetails(NNonBlockingDialog): # Buttons self.buttonBox = QDialogButtonBox(QtDialogClose, self) - self.buttonBox.rejected.connect(self.close) + self.buttonBox.rejected.connect(self.reject) # Assemble self.topBox = QHBoxLayout() diff --git a/tests/test_ext/test_ext_modified.py b/tests/test_ext/test_ext_modified.py index 2158bf60..65865b27 100644 --- a/tests/test_ext/test_ext_modified.py +++ b/tests/test_ext/test_ext_modified.py @@ -22,10 +22,12 @@ from __future__ import annotations import pytest -from PyQt5.QtCore import QPoint, QPointF, Qt -from PyQt5.QtGui import QWheelEvent +from PyQt5.QtCore import QEvent, QPoint, QPointF, Qt +from PyQt5.QtGui import QKeyEvent, QWheelEvent +from PyQt5.QtWidgets import QWidget -from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NSpinBox +from novelwriter.extensions.modified import NComboBox, NDialog, NDoubleSpinBox, NSpinBox +from novelwriter.types import QtModNone, QtRejected from tests.tools import SimpleDialog @@ -47,6 +49,21 @@ class MockWheelEvent(QWheelEvent): return +@pytest.mark.gui +def testExtModified_NDialog(qtbot, monkeypatch): + """Test the NDialog class.""" + widget = QWidget() + dialog = NDialog(widget) + assert dialog.parent() is widget + + dialog.softDelete() + assert dialog.parent() is None + + with qtbot.waitSignal(dialog.rejected, timeout=1000): + dialog.keyPressEvent(QKeyEvent(QEvent.Type.KeyPress, Qt.Key.Key_Escape, QtModNone)) + assert dialog.result() == QtRejected + + @pytest.mark.gui def testExtModified_NComboBox(qtbot, monkeypatch): """Test the NComboBox class.""" diff --git a/tests/test_tools/test_tools_dictionaries.py b/tests/test_tools/test_tools_dictionaries.py index 933f7ed2..699c715a 100644 --- a/tests/test_tools/test_tools_dictionaries.py +++ b/tests/test_tools/test_tools_dictionaries.py @@ -152,6 +152,4 @@ def testToolDictionaries_Main(qtbot, monkeypatch, nwGUI, fncPath): "Additional dictionaries found: 2" ) - # Close - nwDicts._doClose() # qtbot.stop() diff --git a/tests/test_tools/test_tools_lipsum.py b/tests/test_tools/test_tools_lipsum.py index 8720a376..261afeb7 100644 --- a/tests/test_tools/test_tools_lipsum.py +++ b/tests/test_tools/test_tools_lipsum.py @@ -25,6 +25,7 @@ import pytest from PyQt5.QtWidgets import QAction from novelwriter import SHARED +from novelwriter.enum import nwDocInsert from novelwriter.tools.lipsum import GuiLipsum from tests.tools import C, buildTestProject @@ -62,7 +63,8 @@ def testToolLipsum_Main(qtbot, monkeypatch, nwGUI, projPath, mockRnd): with monkeypatch.context() as mp: mp.setattr(GuiLipsum, "exec", lambda *a: None) mp.setattr(GuiLipsum, "lipsumText", "FooBar") - nwGUI.mainMenu.aLipsumText.activate(QAction.Trigger) + with qtbot.waitSignal(nwGUI.docEditor.textChanged): + nwGUI.docEditor.insertText(nwDocInsert.LIPSUM) assert nwGUI.docEditor.getText() == "### New Scene\n\nFooBar" # qtbot.stop()