From 28263dcbacb47d0fb6cb6c31411ad313d94f651f Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sun, 6 Aug 2023 23:04:59 +0200 Subject: [PATCH] Make build settings dialog a child of main gui, and ensure only one instance can be open for each build --- novelwriter/tools/manuscript.py | 18 ++++++++++++++---- novelwriter/tools/manussettings.py | 14 ++++++++++++-- tests/test_tools/test_tools_manussettings.py | 12 ++++++------ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py index 1112622f..8292ceb3 100644 --- a/novelwriter/tools/manuscript.py +++ b/novelwriter/tools/manuscript.py @@ -30,7 +30,7 @@ from time import time from typing import TYPE_CHECKING from datetime import datetime -from PyQt5.QtGui import QColor, QCursor, QFont, QPalette, QResizeEvent +from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot from PyQt5.QtWidgets import ( QDialog, QGridLayout, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPushButton, @@ -231,13 +231,13 @@ class GuiManuscript(QDialog): # Events ## - def closeEvent(self, event): + def closeEvent(self, event: QCloseEvent): """Capture the user closing the window so we can save GUI settings. We also check that we don't have a build settings dialog open. """ self._saveSettings() - for obj in self.children(): + for obj in self.mainGui.children(): # Make sure we don't have any settings windows open if isinstance(obj, GuiBuildSettings) and obj.isVisible(): obj.close() @@ -407,13 +407,23 @@ class GuiManuscript(QDialog): def _openSettingsDialog(self, build: BuildSettings): """Open the build settings dialog.""" - dlgSettings = GuiBuildSettings(self, self.mainGui, build) + for obj in self.mainGui.children(): + # Don't open a second dialog if one exists + if isinstance(obj, GuiBuildSettings): + if obj.buildID == build.buildID: + logger.debug("Found instance of GuiBuildSettings") + obj.show() + obj.raise_() + return + + dlgSettings = GuiBuildSettings(self.mainGui, build) dlgSettings.setModal(False) dlgSettings.show() dlgSettings.raise_() qApp.processEvents() dlgSettings.loadContent() dlgSettings.newSettingsReady.connect(self._processNewSettings) + return def _updateBuildsList(self): diff --git a/novelwriter/tools/manussettings.py b/novelwriter/tools/manussettings.py index 0e848fd1..a3f22d2f 100644 --- a/novelwriter/tools/manussettings.py +++ b/novelwriter/tools/manussettings.py @@ -69,8 +69,8 @@ class GuiBuildSettings(QDialog): newSettingsReady = pyqtSignal(BuildSettings) - def __init__(self, parent: QWidget, mainGui: GuiMain, build: BuildSettings) -> None: - super().__init__(parent=parent) + def __init__(self, mainGui: GuiMain, build: BuildSettings) -> None: + super().__init__(parent=mainGui) logger.debug("Create: GuiBuildSettings") self.setObjectName("GuiBuildSettings") @@ -171,6 +171,7 @@ class GuiBuildSettings(QDialog): def __del__(self) -> None: # pragma: no cover logger.debug("Delete: GuiBuildSettings") + return def loadContent(self) -> None: """Populate the child widgets.""" @@ -182,6 +183,15 @@ class GuiBuildSettings(QDialog): self.optTabOutput.loadContent() return + ## + # Properties + ## + + @property + def buildID(self) -> str: + """The build ID of the build of the dialog.""" + return self._build.buildID + ## # Private Slots ## diff --git a/tests/test_tools/test_tools_manussettings.py b/tests/test_tools/test_tools_manussettings.py index 36cf6d79..f84b2e3d 100644 --- a/tests/test_tools/test_tools_manussettings.py +++ b/tests/test_tools/test_tools_manussettings.py @@ -47,7 +47,7 @@ def testBuildSettings_Init(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockRnd build = BuildSettings() # Create the dialog and populate it - bSettings = GuiBuildSettings(nwGUI, nwGUI, build) + bSettings = GuiBuildSettings(nwGUI, build) bSettings.show() bSettings.loadContent() @@ -135,7 +135,7 @@ def testBuildSettings_Filter(qtbot: QtBot, nwGUI: GuiMain, projPath: Path, mockR nwGUI.theProject.tree[hPlotDoc].setActive(False) # type: ignore # Create the dialog and populate it - bSettings = GuiBuildSettings(nwGUI, nwGUI, build) + bSettings = GuiBuildSettings(nwGUI, build) bSettings.show() bSettings.loadContent() @@ -337,7 +337,7 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain): build.setValue("headings.hideSection", False) # Create the dialog and populate it - bSettings = GuiBuildSettings(nwGUI, nwGUI, build) + bSettings = GuiBuildSettings(nwGUI, build) bSettings.show() bSettings.loadContent() @@ -486,7 +486,7 @@ def testBuildSettings_Content(qtbot: QtBot, nwGUI: GuiMain): build.setValue("text.addNoteHeadings", False) # Create the dialog and populate it - bSettings = GuiBuildSettings(nwGUI, nwGUI, build) + bSettings = GuiBuildSettings(nwGUI, build) bSettings.show() bSettings.loadContent() @@ -553,7 +553,7 @@ def testBuildSettings_Format(monkeypatch, qtbot: QtBot, nwGUI: GuiMain): build.setValue("format.rightMargin", 15.0) # Create the dialog and populate it - bSettings = GuiBuildSettings(nwGUI, nwGUI, build) + bSettings = GuiBuildSettings(nwGUI, build) bSettings.show() bSettings.loadContent() @@ -641,7 +641,7 @@ def testBuildSettings_Output(qtbot: QtBot, nwGUI: GuiMain): build.setValue("html.addStyles", False) # Create the dialog and populate it - bSettings = GuiBuildSettings(nwGUI, nwGUI, build) + bSettings = GuiBuildSettings(nwGUI, build) bSettings.show() bSettings.loadContent()