Merge branch 'main' into dev
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"Synopsis": "Synopsis",
|
||||
"Short Description": "Kurzbeschreibung",
|
||||
"Comment": "Kommentar",
|
||||
"Notes": "Notizen",
|
||||
"Tag": "Schlagwort",
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
{
|
||||
"Synopsis": "概要",
|
||||
"Short Description": "简短描述",
|
||||
"Comment": "注释",
|
||||
"Notes": "笔记",
|
||||
"Tag": "标签",
|
||||
"Point of View": "视角",
|
||||
"Focus": "聚焦",
|
||||
"Characters": "角色",
|
||||
"Plot": "情节",
|
||||
"Timeline": "时间线",
|
||||
"Locations": "地点",
|
||||
"Objects": "物品",
|
||||
"Entities": "条目",
|
||||
"Custom": "自定义",
|
||||
"0": "零",
|
||||
"1": "一",
|
||||
"2": "二",
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<h2>Release Notes for 2.2</h2>
|
||||
<p><i>Released on 17 December 2023</i></p>
|
||||
|
||||
<p>Scroll down for <a href="#patch">Patch Notes</a></p>
|
||||
|
||||
<p>This release comes with a number of new features. These are some highlights.</p>
|
||||
<p>In addition to the common Markdown style formatting for bold, italic and strike through, a set
|
||||
of new shortcodes have been added. The shortcodes are far more flexible than the Markdown style
|
||||
@@ -46,5 +48,13 @@ had to be removed. It may be added back later.</p>
|
||||
|
||||
<p><i>See also the <a href="https://github.com/vkbo/novelWriter/releases">Releases</a> page.</i></p>
|
||||
|
||||
<a name="patch"></a><h2>Patch Notes</h2>
|
||||
|
||||
<h3>Patch 2.2.1 – 27 January 2024</h3>
|
||||
|
||||
<p>This is a patch release that fixes an issue where the Project View would sometimes switch to the
|
||||
Novel View when a new item was created. This patch also includes updated translations for German
|
||||
and Chinese.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+14
-14
@@ -46,9 +46,9 @@ from novelwriter.constants import nwConst, nwUnicode
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
##
|
||||
# Checker Functions
|
||||
# =============================================================================================== #
|
||||
##
|
||||
|
||||
def checkStringNone(value: Any, default: str | None) -> str | None:
|
||||
"""Check if a variable is a string or a None."""
|
||||
@@ -131,9 +131,9 @@ def checkPath(value: Any, default: Path) -> Path:
|
||||
return default
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
##
|
||||
# Validator Functions
|
||||
# =============================================================================================== #
|
||||
##
|
||||
|
||||
def isHandle(value: Any) -> bool:
|
||||
"""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
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
##
|
||||
# Formatting Functions
|
||||
# =============================================================================================== #
|
||||
##
|
||||
|
||||
def formatInt(value: int) -> str:
|
||||
"""Formats an integer with k, M, G etc."""
|
||||
@@ -255,9 +255,9 @@ def formatVersion(value: str) -> str:
|
||||
return value.lower().replace("a", " Alpha ").replace("b", " Beta ").replace("rc", " RC ")
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
##
|
||||
# String Functions
|
||||
# =============================================================================================== #
|
||||
##
|
||||
|
||||
def simplified(text: str) -> str:
|
||||
"""Take a string and strip leading and trailing whitespaces, and
|
||||
@@ -376,9 +376,9 @@ def numberToRoman(value: int, toLower: bool = False) -> str:
|
||||
return roman.lower() if toLower else roman
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
##
|
||||
# Encoder Functions
|
||||
# =============================================================================================== #
|
||||
##
|
||||
|
||||
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
|
||||
@@ -468,9 +468,9 @@ def xmlIndent(tree: ET.Element | ET.ElementTree) -> None:
|
||||
return
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
##
|
||||
# File and File System Functions
|
||||
# =============================================================================================== #
|
||||
##
|
||||
|
||||
def readTextFile(path: str | Path) -> str:
|
||||
"""Read the content of a text file in a robust manner."""
|
||||
@@ -512,9 +512,9 @@ def openExternalPath(path: Path) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
# =============================================================================================== #
|
||||
##
|
||||
# Classes
|
||||
# =============================================================================================== #
|
||||
##
|
||||
|
||||
class NWConfigParser(ConfigParser):
|
||||
"""Common: Adapted Config Parser
|
||||
|
||||
@@ -41,6 +41,7 @@ from PyQt5.QtWidgets import (
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout
|
||||
from novelwriter.common import minmax
|
||||
from novelwriter.constants import nwHeaders, nwUnicode, trConst, nwLabels
|
||||
from novelwriter.core.item import NWItem
|
||||
@@ -49,9 +50,6 @@ from novelwriter.dialogs.docmerge import GuiDocMerge
|
||||
from novelwriter.dialogs.docsplit import GuiDocSplit
|
||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||
from novelwriter.dialogs.projectsettings import GuiProjectSettings
|
||||
from novelwriter.enum import (
|
||||
nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwWidget
|
||||
)
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
@@ -682,7 +680,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
|
||||
# Add the new item to the project tree
|
||||
self.revealNewTreeItem(tHandle, nHandle=nHandle, wordCount=True)
|
||||
self.mainGui.switchFocus(nwWidget.TREE)
|
||||
self.projView.setTreeFocus() # See issue #1376
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -833,7 +833,8 @@ class GuiMain(QMainWindow):
|
||||
def showBuildManuscriptDialog(self) -> None:
|
||||
"""Open the build manuscript dialog."""
|
||||
if SHARED.hasProject:
|
||||
dialog = GuiManuscript(self)
|
||||
if (dialog := SHARED.findTopLevelWidget(GuiManuscript)) is None:
|
||||
dialog = GuiManuscript(self)
|
||||
dialog.setModal(False)
|
||||
dialog.show()
|
||||
dialog.raise_()
|
||||
@@ -854,7 +855,8 @@ class GuiMain(QMainWindow):
|
||||
def showWritingStatsDialog(self) -> None:
|
||||
"""Open the session stats dialog."""
|
||||
if SHARED.hasProject:
|
||||
dialog = GuiWritingStats(self)
|
||||
if (dialog := SHARED.findTopLevelWidget(GuiWritingStats)) is None:
|
||||
dialog = GuiWritingStats(self)
|
||||
dialog.setModal(False)
|
||||
dialog.show()
|
||||
dialog.raise_()
|
||||
|
||||
+10
-1
@@ -27,7 +27,7 @@ from __future__ import annotations
|
||||
import logging
|
||||
|
||||
from time import time
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal
|
||||
@@ -43,6 +43,8 @@ if TYPE_CHECKING: # pragma: no cover
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
NWWidget = TypeVar("NWWidget", bound=QWidget)
|
||||
|
||||
|
||||
class SharedData(QObject):
|
||||
|
||||
@@ -230,6 +232,13 @@ class SharedData(QObject):
|
||||
)
|
||||
return Path(projFile) if projFile else None
|
||||
|
||||
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
|
||||
##
|
||||
|
||||
Reference in New Issue
Block a user