Merge branch 'main' into release_2.2.1

This commit is contained in:
Veronica Berglyd Olsen
2024-01-27 15:44:16 +01:00
3 changed files with 28 additions and 17 deletions
+14 -14
View File
@@ -46,9 +46,9 @@ from novelwriter.constants import nwConst, nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# =============================================================================================== # ##
# Checker Functions # Checker Functions
# =============================================================================================== # ##
def checkStringNone(value: Any, default: str | None) -> str | None: def checkStringNone(value: Any, default: str | None) -> str | None:
"""Check if a variable is a string or a None.""" """Check if a variable is a string or a None."""
@@ -131,9 +131,9 @@ def checkPath(value: Any, default: Path) -> Path:
return default return default
# =============================================================================================== # ##
# Validator Functions # Validator Functions
# =============================================================================================== # ##
def isHandle(value: Any) -> bool: def isHandle(value: Any) -> bool:
"""Check if a string is a valid novelWriter handle. """Check if a string is a valid novelWriter handle.
@@ -204,9 +204,9 @@ def checkIntTuple(value: int, valid: tuple | list | set, default: int) -> int:
return default return default
# =============================================================================================== # ##
# Formatting Functions # Formatting Functions
# =============================================================================================== # ##
def formatInt(value: int) -> str: def formatInt(value: int) -> str:
"""Formats an integer with k, M, G etc.""" """Formats an integer with k, M, G etc."""
@@ -250,9 +250,9 @@ def formatTime(t: int) -> str:
return "ERROR" return "ERROR"
# =============================================================================================== # ##
# String Functions # String Functions
# =============================================================================================== # ##
def simplified(text: str) -> str: def simplified(text: str) -> str:
"""Take a string and strip leading and trailing whitespaces, and """Take a string and strip leading and trailing whitespaces, and
@@ -371,9 +371,9 @@ def numberToRoman(value: int, toLower: bool = False) -> str:
return roman.lower() if toLower else roman return roman.lower() if toLower else roman
# =============================================================================================== # ##
# Encoder Functions # Encoder Functions
# =============================================================================================== # ##
def jsonEncode(data: dict | list | tuple, n: int = 0, nmax: int = 0) -> str: def jsonEncode(data: dict | list | tuple, n: int = 0, nmax: int = 0) -> str:
"""Encode a dictionary, list or tuple as a json object or array, and """Encode a dictionary, list or tuple as a json object or array, and
@@ -463,9 +463,9 @@ def xmlIndent(tree: ET.Element | ET.ElementTree) -> None:
return return
# =============================================================================================== # ##
# File and File System Functions # File and File System Functions
# =============================================================================================== # ##
def readTextFile(path: str | Path) -> str: def readTextFile(path: str | Path) -> str:
"""Read the content of a text file in a robust manner.""" """Read the content of a text file in a robust manner."""
@@ -507,9 +507,9 @@ def openExternalPath(path: Path) -> bool:
return False return False
# =============================================================================================== # ##
# Classes # Classes
# =============================================================================================== # ##
class NWConfigParser(ConfigParser): class NWConfigParser(ConfigParser):
"""Common: Adapted Config Parser """Common: Adapted Config Parser
+4 -2
View File
@@ -899,7 +899,8 @@ class GuiMain(QMainWindow):
def showBuildManuscriptDialog(self) -> None: def showBuildManuscriptDialog(self) -> None:
"""Open the build manuscript dialog.""" """Open the build manuscript dialog."""
if SHARED.hasProject: if SHARED.hasProject:
dialog = GuiManuscript(self) if (dialog := SHARED.findTopLevelWidget(GuiManuscript)) is None:
dialog = GuiManuscript(self)
dialog.setModal(False) dialog.setModal(False)
dialog.show() dialog.show()
dialog.raise_() dialog.raise_()
@@ -920,7 +921,8 @@ class GuiMain(QMainWindow):
def showWritingStatsDialog(self) -> None: def showWritingStatsDialog(self) -> None:
"""Open the session stats dialog.""" """Open the session stats dialog."""
if SHARED.hasProject: if SHARED.hasProject:
dialog = GuiWritingStats(self) if (dialog := SHARED.findTopLevelWidget(GuiWritingStats)) is None:
dialog = GuiWritingStats(self)
dialog.setModal(False) dialog.setModal(False)
dialog.show() dialog.show()
dialog.raise_() dialog.raise_()
+10 -1
View File
@@ -27,7 +27,7 @@ from __future__ import annotations
import logging import logging
from time import time from time import time
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, TypeVar
from pathlib import Path from pathlib import Path
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal
@@ -42,6 +42,8 @@ if TYPE_CHECKING: # pragma: no cover
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
NWWidget = TypeVar("NWWidget", bound=QWidget)
class SharedData(QObject): class SharedData(QObject):
@@ -215,6 +217,13 @@ class SharedData(QObject):
QThreadPool.globalInstance().start(runnable, priority=priority) QThreadPool.globalInstance().start(runnable, priority=priority)
return return
def findTopLevelWidget(self, kind: type[NWWidget]) -> NWWidget | None:
"""Find a top level widget."""
for widget in self.mainGui.children():
if isinstance(widget, kind):
return widget
return None
## ##
# Signal Proxy # Signal Proxy
## ##