Merge branch 'release' into i18n/update_translations
This commit is contained in:
@@ -44,6 +44,10 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
SPELLRX = QRegularExpression(r"\b[^\s\-\+\/–—\[\]:]+\b")
|
SPELLRX = QRegularExpression(r"\b[^\s\-\+\/–—\[\]:]+\b")
|
||||||
SPELLRX.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption)
|
SPELLRX.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption)
|
||||||
|
SPELLSC = QRegularExpression(nwRegEx.FMT_SC)
|
||||||
|
SPELLSC.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption)
|
||||||
|
SPELLSV = QRegularExpression(nwRegEx.FMT_SV)
|
||||||
|
SPELLSV.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption)
|
||||||
|
|
||||||
BLOCK_NONE = 0
|
BLOCK_NONE = 0
|
||||||
BLOCK_TEXT = 1
|
BLOCK_TEXT = 1
|
||||||
@@ -53,7 +57,8 @@ BLOCK_TITLE = 4
|
|||||||
|
|
||||||
class GuiDocHighlighter(QSyntaxHighlighter):
|
class GuiDocHighlighter(QSyntaxHighlighter):
|
||||||
|
|
||||||
__slots__ = ("_tItem", "_tHandle", "_spellCheck", "_spellErr", "_hRules", "_hStyles")
|
__slots__ = ("_tHandle", "_isInactive", "_spellCheck", "_spellErr",
|
||||||
|
"_hRules", "_hStyles", "_rxRules")
|
||||||
|
|
||||||
def __init__(self, document: QTextDocument) -> None:
|
def __init__(self, document: QTextDocument) -> None:
|
||||||
super().__init__(document)
|
super().__init__(document)
|
||||||
@@ -67,6 +72,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
|
|
||||||
self._hRules: list[tuple[str, dict]] = []
|
self._hRules: list[tuple[str, dict]] = []
|
||||||
self._hStyles: dict[str, QTextCharFormat] = {}
|
self._hStyles: dict[str, QTextCharFormat] = {}
|
||||||
|
self._rxRules: list[tuple[QRegularExpression, dict[str, QTextCharFormat]]] = []
|
||||||
|
|
||||||
self.initHighlighter()
|
self.initHighlighter()
|
||||||
|
|
||||||
@@ -218,11 +224,11 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
))
|
))
|
||||||
|
|
||||||
# Build a QRegExp for each highlight pattern
|
# Build a QRegExp for each highlight pattern
|
||||||
self.rxRules = []
|
self._rxRules = []
|
||||||
for regEx, regRules in self._hRules:
|
for regEx, regRules in self._hRules:
|
||||||
hReg = QRegularExpression(regEx)
|
hReg = QRegularExpression(regEx)
|
||||||
hReg.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption)
|
hReg.setPatternOptions(QRegularExpression.UseUnicodePropertiesOption)
|
||||||
self.rxRules.append((hReg, regRules))
|
self._rxRules.append((hReg, regRules))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -358,7 +364,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
|
|
||||||
# Regular Text
|
# Regular Text
|
||||||
self.setCurrentBlockState(BLOCK_TEXT)
|
self.setCurrentBlockState(BLOCK_TEXT)
|
||||||
for rX, xFmt in self.rxRules:
|
for rX, xFmt in self._rxRules:
|
||||||
rxItt = rX.globalMatch(text, 0)
|
rxItt = rX.globalMatch(text, 0)
|
||||||
while rxItt.hasNext():
|
while rxItt.hasNext():
|
||||||
rxMatch = rxItt.next()
|
rxMatch = rxItt.next()
|
||||||
@@ -439,6 +445,17 @@ class TextBlockData(QTextBlockUserData):
|
|||||||
"""Run the spell checker and cache the result, and return the
|
"""Run the spell checker and cache the result, and return the
|
||||||
list of spell check errors.
|
list of spell check errors.
|
||||||
"""
|
"""
|
||||||
|
if "[" in text:
|
||||||
|
# Strip shortcodes
|
||||||
|
for rX in [SPELLSC, SPELLSV]:
|
||||||
|
rxItt = rX.globalMatch(text, 0)
|
||||||
|
while rxItt.hasNext():
|
||||||
|
rxMatch = rxItt.next()
|
||||||
|
xPos = rxMatch.capturedStart(0)
|
||||||
|
xLen = rxMatch.capturedLength(0)
|
||||||
|
xEnd = rxMatch.capturedEnd(0)
|
||||||
|
text = text[:xPos] + " "*xLen + text[xEnd:]
|
||||||
|
|
||||||
self._spellErrors = []
|
self._spellErrors = []
|
||||||
rxSpell = SPELLRX.globalMatch(text.replace("_", " "), 0)
|
rxSpell = SPELLRX.globalMatch(text.replace("_", " "), 0)
|
||||||
while rxSpell.hasNext():
|
while rxSpell.hasNext():
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ from novelwriter.enum import (
|
|||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe
|
from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe
|
||||||
from novelwriter.constants import nwHeaders, trConst, nwKeyWords, nwLabels
|
from novelwriter.constants import nwHeaders, trConst, nwKeyWords, nwLabels
|
||||||
|
from novelwriter.extensions.configlayout import NColourLabel
|
||||||
from novelwriter.extensions.novelselector import NovelSelector
|
from novelwriter.extensions.novelselector import NovelSelector
|
||||||
from novelwriter.types import (
|
from novelwriter.types import (
|
||||||
QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration, QtUserRole
|
QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration, QtUserRole
|
||||||
@@ -209,19 +210,18 @@ class GuiOutlineToolBar(QToolBar):
|
|||||||
|
|
||||||
logger.debug("Create: GuiOutlineToolBar")
|
logger.debug("Create: GuiOutlineToolBar")
|
||||||
|
|
||||||
iSz = SHARED.theme.baseIconSize
|
|
||||||
mPx = CONFIG.pxInt(12)
|
|
||||||
|
|
||||||
self.setMovable(False)
|
self.setMovable(False)
|
||||||
self.setIconSize(iSz)
|
self.setIconSize(1.4*SHARED.theme.baseIconSize)
|
||||||
self.setContentsMargins(0, 0, 0, 0)
|
self.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
stretch = QWidget(self)
|
stretch = QWidget(self)
|
||||||
stretch.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
stretch.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
||||||
|
|
||||||
# Novel Selector
|
# Novel Selector
|
||||||
self.novelLabel = QLabel(self.tr("Outline of"), self)
|
self.novelLabel = NColourLabel(
|
||||||
self.novelLabel.setContentsMargins(0, 0, mPx, 0)
|
self.tr("Outline of"), parent=self, scale=NColourLabel.HEADER_SCALE, bold=True
|
||||||
|
)
|
||||||
|
self.novelLabel.setContentsMargins(0, 0, CONFIG.pxInt(12), 0)
|
||||||
|
|
||||||
self.novelValue = NovelSelector(self)
|
self.novelValue = NovelSelector(self)
|
||||||
self.novelValue.setIncludeAll(True)
|
self.novelValue.setIncludeAll(True)
|
||||||
|
|||||||
+33
-14
@@ -675,8 +675,10 @@ def makeMinimalPackage(targetOS: int) -> None:
|
|||||||
# Make Debian Package (build-deb)
|
# Make Debian Package (build-deb)
|
||||||
##
|
##
|
||||||
|
|
||||||
def makeDebianPackage(signKey: str | None = None, sourceBuild: bool = False,
|
def makeDebianPackage(
|
||||||
distName: str = "unstable", buildName: str = "") -> str:
|
signKey: str | None = None, sourceBuild: bool = False,
|
||||||
|
distName: str = "unstable", buildName: str = "", oldSetuptools: bool = False
|
||||||
|
) -> str:
|
||||||
"""Build a Debian package."""
|
"""Build a Debian package."""
|
||||||
print("")
|
print("")
|
||||||
print("Build Debian Package")
|
print("Build Debian Package")
|
||||||
@@ -778,11 +780,27 @@ def makeDebianPackage(signKey: str | None = None, sourceBuild: bool = False,
|
|||||||
))
|
))
|
||||||
print("Wrote: setup.py")
|
print("Wrote: setup.py")
|
||||||
|
|
||||||
setupCfg = readFile("pyproject.toml").replace(
|
if oldSetuptools:
|
||||||
"setup/description_pypi.md", "data/description_short.txt"
|
# This is needed for Ubuntu up to 22.04
|
||||||
)
|
setupCfg = readFile("setup/launchpad_setup.cfg").replace(
|
||||||
writeFile(f"{outDir}/pyproject.toml", setupCfg)
|
"file: setup/description_pypi.md", "file: data/description_short.txt"
|
||||||
print("Wrote: pyproject.toml")
|
)
|
||||||
|
writeFile(f"{outDir}/setup.cfg", setupCfg)
|
||||||
|
print("Wrote: setup.cfg")
|
||||||
|
|
||||||
|
writeFile(f"{outDir}/pyproject.toml", (
|
||||||
|
"[build-system]\n"
|
||||||
|
"requires = [\"setuptools\"]\n"
|
||||||
|
"build-backend = \"setuptools.build_meta\"\n"
|
||||||
|
))
|
||||||
|
print("Wrote: pyproject.toml")
|
||||||
|
|
||||||
|
else:
|
||||||
|
pyProject = readFile("pyproject.toml").replace(
|
||||||
|
"setup/description_pypi.md", "data/description_short.txt"
|
||||||
|
)
|
||||||
|
writeFile(f"{outDir}/pyproject.toml", pyProject)
|
||||||
|
print("Wrote: pyproject.toml")
|
||||||
|
|
||||||
# Copy/Write Debian Files
|
# Copy/Write Debian Files
|
||||||
# =======================
|
# =======================
|
||||||
@@ -860,15 +878,15 @@ def makeForLaunchpad(doSign: bool = False, isFirst: bool = False) -> None:
|
|||||||
bldNum = "0"
|
bldNum = "0"
|
||||||
|
|
||||||
distLoop = [
|
distLoop = [
|
||||||
("20.04", "focal"),
|
("20.04", "focal", True),
|
||||||
("22.04", "jammy"),
|
("22.04", "jammy", True),
|
||||||
("23.10", "mantic"),
|
("23.10", "mantic", False),
|
||||||
("24.04", "noble"),
|
("24.04", "noble", False),
|
||||||
]
|
]
|
||||||
|
|
||||||
print("Building Ubuntu packages for:")
|
print("Building Ubuntu packages for:")
|
||||||
print("")
|
print("")
|
||||||
for distNum, codeName in distLoop:
|
for distNum, codeName, _ in distLoop:
|
||||||
print(f" * Ubuntu {distNum} {codeName.title()}")
|
print(f" * Ubuntu {distNum} {codeName.title()}")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
@@ -881,13 +899,14 @@ def makeForLaunchpad(doSign: bool = False, isFirst: bool = False) -> None:
|
|||||||
print("")
|
print("")
|
||||||
|
|
||||||
dputCmd = []
|
dputCmd = []
|
||||||
for distNum, codeName in distLoop:
|
for distNum, codeName, oldSetup in distLoop:
|
||||||
buildName = f"ubuntu{distNum}.{bldNum}"
|
buildName = f"ubuntu{distNum}.{bldNum}"
|
||||||
dCmd = makeDebianPackage(
|
dCmd = makeDebianPackage(
|
||||||
signKey=signKey,
|
signKey=signKey,
|
||||||
sourceBuild=True,
|
sourceBuild=True,
|
||||||
distName=codeName,
|
distName=codeName,
|
||||||
buildName=buildName
|
buildName=buildName,
|
||||||
|
oldSetuptools=oldSetup,
|
||||||
)
|
)
|
||||||
dputCmd.append(dCmd)
|
dputCmd.append(dCmd)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
[metadata]
|
||||||
|
name = novelWriter
|
||||||
|
version = attr: novelwriter.__version__
|
||||||
|
author = Veronica Berglyd Olsen
|
||||||
|
author_email = code@vkbo.net
|
||||||
|
description = A markdown-like text editor for planning and writing novels
|
||||||
|
url = https://novelwriter.io
|
||||||
|
long_description = file: setup/description_pypi.md
|
||||||
|
long_description_content_type = text/markdown
|
||||||
|
license_files = LICENSE.md
|
||||||
|
license = GNU General Public License v3
|
||||||
|
classifiers =
|
||||||
|
Programming Language :: Python :: 3 :: Only
|
||||||
|
Programming Language :: Python :: 3.8
|
||||||
|
Programming Language :: Python :: 3.9
|
||||||
|
Programming Language :: Python :: 3.10
|
||||||
|
Programming Language :: Python :: 3.11
|
||||||
|
Programming Language :: Python :: 3.12
|
||||||
|
Programming Language :: Python :: Implementation :: CPython
|
||||||
|
License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
||||||
|
Development Status :: 5 - Production/Stable
|
||||||
|
Operating System :: OS Independent
|
||||||
|
Intended Audience :: End Users/Desktop
|
||||||
|
Natural Language :: English
|
||||||
|
Topic :: Text Editors
|
||||||
|
project_urls =
|
||||||
|
Bug Tracker = https://github.com/vkbo/novelWriter/issues
|
||||||
|
Documentation = https://docs.novelwriter.io
|
||||||
|
Source Code = https://github.com/vkbo/novelWriter
|
||||||
|
|
||||||
|
[options]
|
||||||
|
zip_safe = False
|
||||||
|
python_requires = >=3.8
|
||||||
|
include_package_data = True
|
||||||
|
packages = find_namespace:
|
||||||
|
install_requires =
|
||||||
|
pyqt5>=5.10
|
||||||
|
pyenchant>=3.0.0
|
||||||
|
|
||||||
|
[options.packages.find]
|
||||||
|
include = novelwriter*
|
||||||
|
|
||||||
|
[options.entry_points]
|
||||||
|
gui_scripts =
|
||||||
|
novelwriter = novelwriter:main
|
||||||
|
|
||||||
|
[bdist_wheel]
|
||||||
|
universal = 0
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
%%~name: New Note
|
%%~name: New Note
|
||||||
%%~path: 0000000000009/0000000000011
|
%%~path: 0000000000009/0000000000011
|
||||||
%%~kind: PLOT/NOTE
|
%%~kind: PLOT/NOTE
|
||||||
%%~hash: 8ff26f8a18ad6390c2ce725c441ab0c792a125cf
|
%%~hash: 3d3697638a70fc86cc023df6d42202a262d93905
|
||||||
%%~date: 2023-08-25 18:15:35/2023-08-25 18:15:35
|
%%~date: 2024-04-14 23:46:49/2024-04-14 23:46:49
|
||||||
# Main Plot
|
# Main Plot
|
||||||
|
|
||||||
@tag: MainPlot
|
@tag: MainPlot
|
||||||
|
|
||||||
This is a file detailing the main plot.
|
This is a file [i]detailing[/i] the main plot.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="2.3a1" hexVersion="0x020300a1" fileVersion="1.5" fileRevision="2" timeStamp="2024-01-26 22:48:13">
|
<novelWriterXML appVersion="2.4rc1" hexVersion="0x020400c1" fileVersion="1.5" fileRevision="3" timeStamp="2024-04-14 23:46:11">
|
||||||
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="3" autoCount="2" editTime="3">
|
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="3" autoCount="2" editTime="3">
|
||||||
<name>New Project</name>
|
<name>New Project</name>
|
||||||
<author>Jane Doe</author>
|
<author>Jane Doe</author>
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
<name status="s000000" import="i000004">Plot</name>
|
<name status="s000000" import="i000004">Plot</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="0000000000011" parent="0000000000009" root="0000000000009" order="0" type="FILE" class="PLOT" layout="NOTE">
|
<item handle="0000000000011" parent="0000000000009" root="0000000000009" order="0" type="FILE" class="PLOT" layout="NOTE">
|
||||||
<meta expanded="no" heading="H1" charCount="48" wordCount="10" paraCount="1" cursorPos="69" />
|
<meta expanded="no" heading="H1" charCount="48" wordCount="10" paraCount="1" cursorPos="76" />
|
||||||
<name status="s000000" import="i000004" active="yes">New Note</name>
|
<name status="s000000" import="i000004" active="yes">New Note</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="000000000000a" parent="None" root="000000000000a" order="2" type="ROOT" class="CHARACTER">
|
<item handle="000000000000a" parent="None" root="000000000000a" order="2" type="ROOT" class="CHARACTER">
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, projPath, tstPaths, mockRnd):
|
|||||||
qtbot.keyClick(docEditor, c, delay=KEY_DELAY)
|
qtbot.keyClick(docEditor, c, delay=KEY_DELAY)
|
||||||
qtbot.keyClick(docEditor, Qt.Key_Return, delay=KEY_DELAY)
|
qtbot.keyClick(docEditor, Qt.Key_Return, delay=KEY_DELAY)
|
||||||
qtbot.keyClick(docEditor, Qt.Key_Return, delay=KEY_DELAY)
|
qtbot.keyClick(docEditor, Qt.Key_Return, delay=KEY_DELAY)
|
||||||
for c in "This is a file detailing the main plot.":
|
for c in "This is a file [i]detailing[/i] the main plot.":
|
||||||
qtbot.keyClick(docEditor, c, delay=KEY_DELAY)
|
qtbot.keyClick(docEditor, c, delay=KEY_DELAY)
|
||||||
qtbot.keyClick(docEditor, Qt.Key_Return, delay=KEY_DELAY)
|
qtbot.keyClick(docEditor, Qt.Key_Return, delay=KEY_DELAY)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user