diff --git a/novelwriter/dialogs/editlabel.py b/novelwriter/dialogs/editlabel.py index 6da4947a..5d84b82a 100644 --- a/novelwriter/dialogs/editlabel.py +++ b/novelwriter/dialogs/editlabel.py @@ -86,6 +86,7 @@ class GuiEditLabel(QDialog): @classmethod def getLabel(cls, parent: QWidget, text: str) -> tuple[str, bool]: + """Pop the dialog and return the result.""" cls = GuiEditLabel(parent, text=text) cls.exec_() label = cls.itemLabel diff --git a/novelwriter/enum.py b/novelwriter/enum.py index 5bb41f71..8b84c39e 100644 --- a/novelwriter/enum.py +++ b/novelwriter/enum.py @@ -140,6 +140,7 @@ class nwDocInsert(Enum): NEW_PAGE = 7 VSPACE_S = 8 VSPACE_M = 9 + LIPSUM = 10 # END Enum nwDocInsert diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 3dfc5b41..4d4ac393 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -58,6 +58,7 @@ from novelwriter.common import minmax, transferCase from novelwriter.constants import nwKeyWords, nwLabels, nwShortcode, nwUnicode, trConst from novelwriter.core.item import NWItem from novelwriter.core.index import countWords +from novelwriter.tools.lipsum import GuiLipsum from novelwriter.core.document import NWDocument from novelwriter.gui.dochighlight import GuiDocHighlighter from novelwriter.gui.editordocument import GuiTextDocument @@ -850,18 +851,23 @@ class GuiDocEditor(QPlainTextEdit): text = "[vspace:2]" newBlock = True goAfter = False + elif insert == nwDocInsert.LIPSUM: + text = GuiLipsum.getLipsum(self) + newBlock = True + goAfter = False else: return False else: return False - if newBlock: - self.insertNewBlock(text, defaultAfter=goAfter) - else: - cursor = self.textCursor() - cursor.beginEditBlock() - cursor.insertText(text) - cursor.endEditBlock() + if text: + if newBlock: + self.insertNewBlock(text, defaultAfter=goAfter) + else: + cursor = self.textCursor() + cursor.beginEditBlock() + cursor.insertText(text) + cursor.endEditBlock() return True diff --git a/novelwriter/gui/mainmenu.py b/novelwriter/gui/mainmenu.py index 2500ac3c..fbb47cd1 100644 --- a/novelwriter/gui/mainmenu.py +++ b/novelwriter/gui/mainmenu.py @@ -593,8 +593,10 @@ class GuiMainMenu(QMenuBar): ) # Insert > Placeholder Text - self.aLipsumText = self.mInsBreaks.addAction(self.tr("Placeholder Text")) - self.aLipsumText.triggered.connect(self.mainGui.showLoremIpsumDialog) + self.aLipsumText = self.insMenu.addAction(self.tr("Placeholder Text")) + self.aLipsumText.triggered.connect( + lambda: self.requestDocInsert.emit(nwDocInsert.LIPSUM) + ) return diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 25bf97ca..04ebab1a 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -56,7 +56,6 @@ from novelwriter.dialogs.wordlist import GuiWordList from novelwriter.dialogs.preferences import GuiPreferences from novelwriter.dialogs.projdetails import GuiProjectDetails from novelwriter.dialogs.projsettings import GuiProjectSettings -from novelwriter.tools.lipsum import GuiLipsum from novelwriter.tools.manuscript import GuiManuscript from novelwriter.tools.projwizard import GuiProjectWizard from novelwriter.tools.dictionaries import GuiDictionaries @@ -908,17 +907,6 @@ class GuiMain(QMainWindow): dialog.loadContent() return - @pyqtSlot() - def showLoremIpsumDialog(self) -> None: - """Open the insert lorem ipsum text dialog.""" - if SHARED.hasProject: - dialog = GuiLipsum(self) - dialog.setModal(False) - dialog.show() - dialog.raise_() - qApp.processEvents() - return - @pyqtSlot() def showProjectWordListDialog(self) -> None: """Open the project word list dialog.""" diff --git a/novelwriter/tools/lipsum.py b/novelwriter/tools/lipsum.py index d5febc2b..0f017171 100644 --- a/novelwriter/tools/lipsum.py +++ b/novelwriter/tools/lipsum.py @@ -26,10 +26,10 @@ from __future__ import annotations import random import logging -from PyQt5.QtCore import Qt +from PyQt5.QtCore import Qt, pyqtSlot from PyQt5.QtWidgets import ( - QDialog, QGridLayout, QHBoxLayout, QVBoxLayout, QLabel, QDialogButtonBox, - QSpinBox + QDialog, QDialogButtonBox, QGridLayout, QHBoxLayout, QLabel, QSpinBox, + QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED @@ -41,15 +41,15 @@ logger = logging.getLogger(__name__) class GuiLipsum(QDialog): - def __init__(self, mainGui): - super().__init__(parent=mainGui) + def __init__(self, parent: QWidget) -> None: + super().__init__(parent=parent) logger.debug("Create: GuiLipsum") self.setObjectName("GuiLipsum") if CONFIG.osDarwin: self.setWindowFlag(Qt.WindowType.Tool) - self.mainGui = mainGui + self._lipsumText = "" self.setWindowTitle(self.tr("Insert Placeholder Text")) @@ -92,7 +92,7 @@ class GuiLipsum(QDialog): # Buttons self.buttonBox = QDialogButtonBox() - self.buttonBox.rejected.connect(self._doClose) + self.buttonBox.rejected.connect(self.close) self.btnClose = self.buttonBox.addButton(QDialogButtonBox.Close) self.btnClose.setAutoDefault(False) @@ -101,6 +101,8 @@ class GuiLipsum(QDialog): self.btnSave.clicked.connect(self._doInsert) self.btnSave.setAutoDefault(False) + self.rejected.connect(self.close) + # Assemble self.outerBox = QVBoxLayout() self.outerBox.addLayout(self.innerBox) @@ -112,33 +114,37 @@ class GuiLipsum(QDialog): return - def __del__(self): # pragma: no cover + def __del__(self) -> None: # pragma: no cover logger.debug("Delete: GuiLipsum") return + @property + def lipsumText(self) -> str: + """Return the generated text.""" + return self._lipsumText + + @classmethod + def getLipsum(cls, parent: QWidget) -> str: + """Pop the dialog and return the lipsum text.""" + cls = GuiLipsum(parent) + cls.exec_() + text = cls.lipsumText + cls.deleteLater() + return text + ## - # Slots + # Private Slots ## - def _doInsert(self): - """Load the text and insert it in the open document. - """ + @pyqtSlot() + def _doInsert(self) -> None: + """Generate the text.""" lipsumFile = CONFIG.assetPath("text") / "lipsum.txt" lipsumText = readTextFile(lipsumFile).splitlines() - if self.randSwitch.isChecked(): random.shuffle(lipsumText) - pCount = self.paraCount.value() - inText = "\n\n".join(lipsumText[0:pCount]) + "\n\n" - - self.mainGui.docEditor.insertText(inText) - - return - - def _doClose(self): - """Close the dialog window without doing anything. - """ + self._lipsumText = "\n\n".join(lipsumText[0:pCount]) + "\n\n" self.close() return diff --git a/tests/test_tools/test_tools_lipsum.py b/tests/test_tools/test_tools_lipsum.py index 19160851..f5199c6e 100644 --- a/tests/test_tools/test_tools_lipsum.py +++ b/tests/test_tools/test_tools_lipsum.py @@ -30,43 +30,39 @@ from novelwriter.tools.lipsum import GuiLipsum @pytest.mark.gui -def testToolLipsum_Main(qtbot, nwGUI, projPath, mockRnd): - """Test the Lorem Ipsum tool. - """ +def testToolLipsum_Main(qtbot, monkeypatch, nwGUI, projPath, mockRnd): + """Test the Lorem Ipsum tool.""" # Check that we cannot open when there is no project nwGUI.mainMenu.aLipsumText.activate(QAction.Trigger) assert getGuiItem("GuiLipsum") is None - # Create a new project buildTestProject(nwGUI, projPath) - assert nwGUI.openDocument(C.hSceneDoc) is True - assert len(nwGUI.docEditor.getText()) == 15 + nwLipsum = GuiLipsum(nwGUI) - # Open the tool - nwGUI.mainMenu.aLipsumText.activate(QAction.Trigger) - qtbot.waitUntil(lambda: getGuiItem("GuiLipsum") is not None, timeout=1000) - - nwLipsum = getGuiItem("GuiLipsum") - assert isinstance(nwLipsum, GuiLipsum) - - # Insert paragraphs + # Generate paragraphs nwGUI.docEditor.setCursorPosition(100) # End of document nwLipsum.paraCount.setValue(2) nwLipsum._doInsert() - theText = nwGUI.docEditor.getText() - assert "Lorem ipsum" in theText - assert len(theText) == 965 + assert "Lorem ipsum" in nwLipsum.lipsumText - # Insert random paragraph + # Generate random paragraph nwGUI.docEditor.setCursorPosition(1000) # End of document nwLipsum.randSwitch.setChecked(True) nwLipsum.paraCount.setValue(1) nwLipsum._doInsert() - theText = nwGUI.docEditor.getText() - assert len(theText) > 965 + assert len(nwLipsum.lipsumText) > 0 - # Close - nwLipsum._doClose() + nwLipsum.setObjectName("") + nwLipsum.close() + + # Trigger insertion in document + assert nwGUI.openDocument(C.hSceneDoc) is True + nwGUI.docEditor.setCursorLine(3) + with monkeypatch.context() as mp: + mp.setattr(GuiLipsum, "exec_", lambda *a: None) + mp.setattr(GuiLipsum, "lipsumText", "FooBar") + nwGUI.mainMenu.aLipsumText.activate(QAction.Trigger) + assert nwGUI.docEditor.getText() == "### New Scene\n\nFooBar" # qtbot.stop()